X3DStudios

Get order status

Read one print order back by its X3D- code: where it is in the queue, whether it is paid, and the carrier tracking number once the parcel is handed over.

This endpoint answers one question: where is order X3D-…? It returns the current stage, whether the order is paid, what was ordered, and the tracking number once there is one. It is the endpoint you poll after a submit.

GET/api/print/orders/{code}API key

Read one print order belonging to the calling account.

Path parameter
codestringrequired
The public order code from the submit response: X3D- followed by six uppercase characters. Matched exactly and case-sensitively — a lowercased code returns 404. The alphabet excludes 0, 1, I, L and O, so those characters never appear in a real code.
Same key, own orders only
Authenticate with the same x3d_live_ key you submitted with, as Authorization: Bearer or x-api-key. A code that belongs to another account returns 404 rather than 403, so nothing about it leaks.

Request#

curl https://x3dstudios.com/api/print/orders/X3D-K7M2QP \
  -H "Authorization: Bearer $X3D_API_KEY"

Response#

200
{
  "code": "X3D-K7M2QP",
  "status": "SHIPPED",
  "statusLabel": "Shipped",
  "paid": true,
  "fileName": "bracket.stl",
  "material": "pla",
  "color": "Black",
  "quality": "standard",
  "quantity": 2,
  "estimatedCost": 12.04,
  "currency": "USD",
  "tracking": { "number": "9400111899223197428490", "carrier": "usps" },
  "shipTo": { "name": "Ada Lovelace", "city": "Austin", "state": "TX", "country": "US" },
  "createdAt": "2026-09-02T14:11:07.220Z",
  "updatedAt": "2026-09-05T09:41:52.006Z"
}
Response fields
codestringoptional
The order code, echoed back.
statusstringoptional
Machine-readable stage. Branch on this, not on statusLabel.
statusLabelstringoptional
The same stage in words, safe to show a customer. Falls back to the raw status if we ever add a stage before this table catches up.
paidbooleanoptional
Whether money has been taken. false means the order is waiting at PENDING_PAYMENT.
fileNamestringoptional
The file name as submitted.
materialstringoptional
Material key as ordered: pla, petg, abs, asa or tpu.
colorstringoptional
Colour as ordered. "Default" when none was sent.
qualitystringoptional
standard or premium.
quantitynumberoptional
Units ordered.
estimatedCostnumberoptional
Total in USD — print plus postage. This is the amount charged.
currencystringoptional
Always "USD".
trackingobject | nulloptional
null until the parcel is handed over. Then { number, carrier }, where carrier can itself be null if it was not recorded.
shipToobjectoptional
name, city, state, country only. The street and postal code are deliberately not returned.
createdAtstringoptional
ISO 8601 timestamp of submission.
updatedAtstringoptional
ISO 8601 timestamp of the last change. Use it to detect movement between polls.

Status values#

statusstatusLabelWhat it means
PENDING_PAYMENTAwaiting paymentThe order exists but no money has been taken. Nothing is printed until it is paid.
RECEIVEDReceived — in reviewPaid and waiting for an operator to look at it.
ACCEPTEDAccepted — queued to printChecked and queued. It has not started on a machine yet.
PRINTINGPrintingOn a printer now.
PRINTEDPrinted — preparing to shipOff the plate, being checked and packed.
SHIPPEDShippedHanded to the carrier. tracking is populated at this point.
DELIVEREDDeliveredThe carrier reported delivery. Terminal.
CANCELLEDCancelledStopped before completion. Terminal.
REJECTEDRejectedWe could not print it — geometry, material or plate problems. Terminal.
Every status the endpoint can return, with the label shown alongside it.
Treat the order as intended, not guaranteed
The normal path is PENDING_PAYMENT → RECEIVED → ACCEPTED → PRINTING → PRINTED → SHIPPED → DELIVERED, with CANCELLED and REJECTED as exits. Nothing in the system enforces that ordering, so an operator correcting a mistake can move an order backwards. Handle any status at any poll rather than assuming monotonic progress.

Polling#

Poll every five minutes while an order is in flight, and stop at a terminal status. There is nothing to gain from a tighter loop: the fastest stage change happens when the card clears, and everything after that moves on the timescale of a print.

Poll until the parcel ships
const TERMINAL = new Set(["DELIVERED", "CANCELLED", "REJECTED"]);

async function waitForTracking(code) {
  for (;;) {
    const res = await fetch(`https://x3dstudios.com/api/print/orders/${code}`, {
      headers: { Authorization: `Bearer ${process.env.X3D_API_KEY}` },
    });
    if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error}`);

    const order = await res.json();
    if (order.tracking) return order.tracking;
    if (TERMINAL.has(order.status)) return null;

    await new Promise((r) => setTimeout(r, 5 * 60 * 1000));
  }
}
StatuserrorWhen
401Invalid or missing API key.No key, an unrecognised key, or a token that is not an x3d_live_ key.
404Order not found.No order with that code, or it belongs to another account. The two cases are indistinguishable on purpose.
A link you can give your own customer
The submit response also returns statusUrl — /print/order/{code}. That page needs no login and shows the same stages in plain language, so you can forward it instead of building your own status screen.