Checkout and payment
How an X3D order is priced, discounted and charged: the cart re-quote before payment, gift cards, shipping, and when your card is actually billed.
This page covers everything between the cart and a paid order: how the price is recalculated the moment before you are charged, what a gift card or discount does to the total, and when the money actually leaves your card. Prints are sold by weight, so the number in your cart is not final until the model has been through the slicer.
What you are charged for#
A cart total is three things: goods, shipping, and any discount. There is no handling fee, no per-order fee, and no tax line.
| Line | How it is worked out |
|---|---|
| Print items | Re-quoted on the server from the stored model — billable grams at the material's per-gram rate, rounded up to the whole gram, $1.00 minimum per part. See /docs/pricing. |
| Store products | The catalogue price for that product and quantity. |
| Shipping (US) | $7 flat, free once goods reach $50. |
| Shipping (international) | $30 flat, free once goods reach $500. |
| First-order discount | 10% of goods only, for an account with no previous order and no paid plan. |
| Gift card | Whatever is spendable on the card, up to what is still owed. |
| Sales tax | Not collected. No tax is added to the Stripe session. |
The cart re-prices before it charges#
A print's price is written into your browser when you add it. That number can go stale — an older price sheet, or a quote made from the volume estimate before the slicer had weighed the model. Opening the cart posts your print items back for a fresh quote.
/api/cart-repriceSigned inRe-quote every print in the cart and report which ones are still unmeasured.
The response carries prices, keyed by cart item id, and measuring, a list of ids whose price is still a volume estimate. While measuring is not empty the Checkout button stays disabled and reads Weighing your print. It is capped at 60 requests an hour per account, and the first 40 items in the cart.
One limit worth knowing: the cart quotes each print as a single unit, so the 5-unit and 10-unit bulk tiers are not applied through the cart. They do apply on the Print and Ship button on /print and on API orders, where the quantity reaches the quote.
Paying#
Checkout hands off to Stripe Checkout as a one-off payment. Card details are entered on Stripe's page and never reach X3D. Your account email is prefilled, and the delivery address is collected there rather than in the cart.
Choose United States or International in the cart before checking out. That choice sets both the shipping rate and which countries Stripe will accept an address in: US only for domestic, and CA, GB, AU, DE, FR, IN, IE, NZ, NL, ES, IT, SE, NO, DK, FI, CH, AT, BE, PT, SG, JP or AE for international.
The session does not pin a list of payment methods, so what you are offered on that page comes from Stripe, not from us. A card always works. A gift card is not a payment method here — it is applied as a discount on the session before Stripe asks for anything, which is also how an order fully covered by one can complete at $0.
Discounts, gift cards and promo codes#
First order#
A first order takes 10% off. It is applied as a fixed amount worked out from goods only, so it never comes off postage — a percentage coupon used to take 10% off the shipping line too, which is how the cart once said $10.40 while Stripe charged $9.90. Eligibility is checked on the server: no orders on the account, and no paid plan. If that check errors, the discount is withheld rather than guessed at.
Gift cards#
Enter the code in the cart and press Apply. It is validated before it shows as applied, so a bad code fails there rather than after you have committed to a checkout.
/api/gift-cards/checkSigned inValidate a gift card code and return its spendable balance.
A good card returns valid: true, the tidied-up code, and availableCents — the spendable balance, not the face value, which differ once part of it has been spent. An unknown code, a voided card and an empty card all answer with the same 404, so guessing gets no signal. You get 20 checks an hour.
At checkout the balance is held, not spent. The hold is taken against what is owed after the percentage discount, and only turned into a deduction when Stripe confirms the payment — an abandoned cart never quietly eats somebody's present. If the checkout session fails to open, the hold is released immediately. A card that covers the whole bill leaves nothing to pay; Stripe still collects your delivery address and completes the order at $0.
Promo codes#
A promo code typed into the cart is looked up in Stripe. If it does not match an active code, checkout continues at full price rather than failing. With no code entered, Stripe's own promotion-code box is enabled on the payment page instead. Both only happen when the session's single discount slot is free: a gift card or the first-order discount claims it first, and a promo code entered alongside either one is ignored.
When your card is charged#
- 1You press Checkout
The cart is re-quoted on the server, a gift card hold is taken if you entered a code, and a work order listing every file and print setting is written for the farm. Nothing has been charged yet.
- 2Stripe takes the payment
You are sent to Stripe Checkout. The charge happens when you confirm it there — not when you added to the cart, and not when you pressed Checkout.
- 3The webhook creates the order
Stripe calls back. The order record is written at stage placed, any gift card hold is spent, and the confirmation emails go out. This step is idempotent, so a retried webhook cannot create a second order or a second email.
- 4You land back on /orders
The success redirect is /orders?checkout=success with the session id attached. The page asks the server to confirm the payment status; that probe is read-only and creates nothing.
What the receipt contains#
- A confirmation email from [email protected], subject Order confirmed - <order id>, listing the order id, the items, the total charged and the shipping address.
- Stripe's own receipt for the charge, linked as Receipt beside the payment under Payment History on /orders, whenever Stripe issued one.
- For several orders at once, the Statement / invoice link on /orders builds one printable document for a date range.
The customer copy is a plain summary. Signed download links for the model files go only to the operator copy of the email, since you already hold your own files.
The two checkouts that skip the cart#
| Path | How it charges |
|---|---|
| Print and Ship on /print | Quotes the model at the quantity you chose, so the bulk tiers apply. A Pro plan takes 10% off, any monthly print credit is spent next, and Stripe collects the remainder. An order fully covered by print credit completes with no Stripe step at all. |
| A single store product | Buying from a product page opens its own Stripe session at the catalogue price, accepting addresses in US, CA, GB, AU, DE, FR and IN. |
Print and Ship refuses an unweighed model exactly as the cart does, with the same 409. A store product has nothing to weigh, so it never hits that gate. Either way the order is written only once the bill is settled, whether by Stripe confirming the charge or by print credit covering the whole of it, and both appear on /orders — a single store product redirects you back to /store rather than to the order list, but its order is filed alongside the rest.
API orders are charged at submission#
The developer API works the other way round. There is no checkout page and no cart: the order is submitted and the card saved on your account is charged in the same request.
/api/print/ordersAPI keySubmit a print order and charge the saved card immediately.
curl -X POST https://x3dstudios.com/api/print/orders \
-H "Authorization: Bearer $X3D_API_KEY" \
-F "[email protected]" \
-F "recipientName=Ada Lovelace" \
-F "street1=13359 N Highway 183" \
-F "city=Austin" \
-F "state=TX" \
-F "zip=78750" \
-F "material=pla" \
-F "color=Black" \
-F "quantity=2"A successful charge returns 201 with status RECEIVED, paid true, and charged set to the amount taken. If the card is declined you still get 201 and a real order, but at status PENDING_PAYMENT with a paymentUrl you can send someone to. This is why minting an API key requires a card on file in the first place — and why an order below $0.50 is refused outright.