X3DStudios

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.

A card is required before a key exists
POST /api/account/api-key refuses to mint a key while the account has no card, returning 402 with code CARD_REQUIRED. Add one at /profile. The card can be removed afterwards, and the key keeps working — submissions then come back unpaid with the reason "No card on file".

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.

estimatedCost is what you were charged
The field is named for the quote it came from, but it is the exact amount taken: the charge is that number in cents. On a successful submission the response repeats it in charged. Nothing is trued up afterwards if the print comes off the plate heavier or lighter than quoted.

The rates#

materialRateDensity
pla$0.12/g1.26 g/cm³
petg$0.12/g1.27 g/cm³
abs$0.12/g1.04 g/cm³
asa$0.14/g1.07 g/cm³
tpu$0.13/g1.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.
Always send a colour
Omit the color field and the order is stored as "Default", which is not one of the twelve stock spool names, so the whole order prices at the $0.20/g custom-colour floor. On the worked example below that is $4.48 of avoidable cost. Sending color=Black is strictly cheaper than sending nothing.

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.

StepArithmeticResult
Solid volume100 cm³ × (30% walls + 70% × 20% infill)44 cm³
Weight44 cm³ × 1.26 g/cm³, rounded up56 g
Print56 g × $0.12 × 1.0 (standard)$6.72
Machine surchargeNo colour changes on a mesh$0.00
PostageUS flat, subtotal under $50$7.00
Charged$6.72 + $7.00$13.72
The response returns the same figures under breakdown, as print, shipping, grams and printHours.

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.

StepArithmeticResult
Slicer reportsFour-colour plate, PLA120 g, 20 h
Print120 g × $0.12$14.40
Hours a 120 g print normally takes120 g ÷ (1.26 g/cm³ × 16 cm³/h)5.95 h
Excess hours, at $1.50/h(20 − 5.95) × $1.50$21.07
PostageUS flat, subtotal under $50$7.00
Charged$14.40 + $21.07 + $7.00$42.47
A four-colour plate spends most of its run swapping and purging filament, which is why time — not material — dominates the price.
The quote is not a slice
For a mesh, the API prices from the geometry it can read; it does not run OrcaSlicer on your STL before charging you. If you want the price to come from a real slice, slice it yourself and submit the .gcode.3mf — then the numbers we bill are the numbers your slicer showed you.

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.

201 — order created, card declined
{
  "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 messageWhat it means
No card on fileThe card was removed after the key was issued. Add one at /profile.
Payment requires_actionThe 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 textPassed 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.
Do not resubmit a declined order
Resubmitting creates a second order at a second price and, once the card works, a second charge. Fix the card and pay the order you already have.

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.
API orders are not on your statement page
/orders and /orders/statement are built from website orders and do not include orders placed through the API. There is also no endpoint that lists your API orders. Store every code you get back at submission — it is the only handle you will have on that order.

How this relates to the website#

API (POST /api/print/orders)Website print order
RatesIdentical — the same quoting code runs for bothIdentical
PaymentSaved card charged during the requestPayment link, paid in a browser
Result if payment fails201 with an unpaid orderOrder waits at the payment step
Gift cardsNot acceptedAccepted in the cart
Subscription print creditNot appliedApplied at checkout
First-order discountNot appliedApplied 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.