API billing
How API print orders are paid for: the card on file is charged the moment you submit, what the charge covers, and what happens when it is declined.
An API print order is paid at the moment you submit it. The route quotes the file, writes the order, then charges the card saved on your X3D account for the full amount — print plus postage — and returns the result in the same response. Nothing is invoiced later, and nothing is charged when the part ships.
What the charge covers#
- The print itself, at one all-in rate per gram that covers filament and normal machine time.
- Postage to the address in the request.
- Nothing else. There is no setup fee, no per-order platform fee and no minimum monthly spend.
It is a single payment for the whole order, in USD, taken off-session against the card on file. The payment record carries a description built from the order — material, colour, nozzle, layer height, quantity and file name — so a charge can be traced back to a submission even without the order code, and the order code itself is attached to the payment as metadata.
The rates#
| material | Rate | Density |
|---|---|---|
| pla | $0.12/g | 1.26 g/cm³ |
| petg | $0.12/g | 1.27 g/cm³ |
| abs | $0.12/g | 1.04 g/cm³ |
| asa | $0.14/g | 1.07 g/cm³ |
| tpu | $0.13/g | 1.21 g/cm³ |
- Billable weight rounds up to the whole gram, the way postage does.
- quality=premium (0.1 mm layers) multiplies the per-gram rate by 1.75. quality=standard (0.2 mm) is 1×.
- Minimum $1.00 per part.
- Twelve stock colours bill at the material rate. Any other colour bills at a $0.20/g floor, because the spool has to be bought in.
- Bulk: 5 or more units take 5% off, 10 or more take 10%.
- US postage is $7 flat, free once the print subtotal reaches $50. International is $30 flat, free at $500.
- An order that works out below $0.50 is refused with a 400 — that is the floor our payment processor accepts.
A worked example#
A bracket whose mesh measures 100 cm³, submitted as PLA in Black at standard quality with the default 20% infill, quantity 1, shipping inside the US.
| Step | Arithmetic | Result |
|---|---|---|
| Solid volume | 100 cm³ × (30% walls + 70% × 20% infill) | 44 cm³ |
| Weight | 44 cm³ × 1.26 g/cm³, rounded up | 56 g |
| 56 g × $0.12 × 1.0 (standard) | $6.72 | |
| Machine surcharge | No colour changes on a mesh | $0.00 |
| Postage | US flat, subtotal under $50 | $7.00 |
| Charged | $6.72 + $7.00 | $13.72 |
Three variations on that same part show where the money actually moves. At quantity 10 the print is $6.72 × 10 × 0.90 = $60.48, which clears the $50 threshold, so postage drops to nothing and the total is $60.48. At premium quality the print becomes 56 × $0.12 × 1.75 = $11.76, for $18.76 with postage. With the colour field left out entirely it is 56 × $0.20 = $11.20, for $18.20 — nearly as much as the premium version of the same part, on a standard-quality print.
Already-sliced files are priced differently#
Send an STL or GLB and the weight is estimated from geometry, as above. Send a .gcode or .gcode.3mf and the slicer's own measurements are used instead — its filament weight and its print time — because a volume estimate cannot see purge waste or tool changes. On top of the per-gram charge, hours that the weight cannot explain are billed at $1.50/hour.
| Step | Arithmetic | Result |
|---|---|---|
| Slicer reports | Four-colour plate, PLA | 120 g, 20 h |
| 120 g × $0.12 | $14.40 | |
| Hours a 120 g print normally takes | 120 g ÷ (1.26 g/cm³ × 16 cm³/h) | 5.95 h |
| Excess hours, at $1.50/h | (20 − 5.95) × $1.50 | $21.07 |
| Postage | US flat, subtotal under $50 | $7.00 |
| Charged | $14.40 + $21.07 + $7.00 | $42.47 |
When the charge fails#
The order row is written before the card is charged, so a decline does not throw away the work. You get 201, a real order code, and a response that says plainly what went wrong.
{
"code": "X3D-K7M2QP",
"estimatedCost": 13.72,
"currency": "USD",
"breakdown": { "print": 6.72, "shipping": 7, "grams": 56, "printHours": 2.75 },
"status": "PENDING_PAYMENT",
"paid": false,
"paymentUrl": "https://x3dstudios.com/print/order/X3D-K7M2QP/pay",
"checkoutUrl": "https://checkout.stripe.com/…",
"message": "Auto-charge failed (No card on file). Update your card on file, or pay via paymentUrl."
}| Reason in the message | What it means |
|---|---|
| No card on file | The card was removed after the key was issued. Add one at /profile. |
| Payment requires_action | The card asked for 3-D Secure. The charge runs off-session, so there is nobody to complete the challenge — pay through paymentUrl instead, where there is. |
| Any other text | Passed through verbatim from the payment processor, e.g. a declined or expired card. |
- The order stays at PENDING_PAYMENT and is never auto-retried.
- The farm will not queue it — an operator trying to put an unpaid order on a printer gets refused.
- paymentUrl is a page on x3dstudios.com that forwards to the hosted payment page; checkoutUrl is that page directly. Either works, and both are null if payments are unavailable at that moment.
- Paying through that link flips the order to RECEIVED and marks it paid, the same end state a successful card charge produces.
Receipts and records#
- Every paid API order sends a confirmation email with the order code, a one-line summary and the shipping address.
- The email goes to the order's email field, which defaults to your account address. Set it to your end customer and they receive the receipt for a charge on your card — usually not what you want on a reseller integration.
- The order itself is readable at /print/order/{code} and through GET /api/print/orders/{code}. Both keep working after the print ships.
- The card itself is added and replaced at /profile, in the same Developer API key panel that issues the key. The charges it takes appear in the payment history on /orders.
How this relates to the website#
| API (POST /api/print/orders) | Website print order | |
|---|---|---|
| Rates | Identical — the same quoting code runs for both | Identical |
| Payment | Saved card charged during the request | Payment link, paid in a browser |
| Result if payment fails | 201 with an unpaid order | Order waits at the payment step |
| Gift cards | Not accepted | Accepted in the cart |
| Subscription print credit | Not applied | Applied at checkout |
| First-order discount | Not applied | Applied to the goods, not the postage |
Renting a printer by the hour is a different product with different economics — $1.50/hour or $15/day for the machine, plus filament at raw cost ($0.02/g PLA, $0.025/g PETG, $0.03/g ABS) — and it is not part of this API. Quoting the all-in per-gram rate against a reservation bills machine time twice. See /docs/farm/reservations.
The full explanation of the per-gram rate, quality factors and bulk pricing.
Every status code, and why a 201 is not always a receipt.
Every field the endpoint accepts and what each one defaults to.
Issuing, rotating and revoking the key that carries the charge.