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 keyRead 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#
| status | statusLabel | What it means |
|---|---|---|
| PENDING_PAYMENT | Awaiting payment | The order exists but no money has been taken. Nothing is printed until it is paid. |
| RECEIVED | Received — in review | Paid and waiting for an operator to look at it. |
| ACCEPTED | Accepted — queued to print | Checked and queued. It has not started on a machine yet. |
| PRINTING | Printing | On a printer now. |
| PRINTED | Printed — preparing to ship | Off the plate, being checked and packed. |
| SHIPPED | Shipped | Handed to the carrier. tracking is populated at this point. |
| DELIVERED | Delivered | The carrier reported delivery. Terminal. |
| CANCELLED | Cancelled | Stopped before completion. Terminal. |
| REJECTED | Rejected | We could not print it — geometry, material or plate problems. Terminal. |
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));
}
}| Status | error | When |
|---|---|---|
| 401 | Invalid or missing API key. | No key, an unrecognised key, or a token that is not an x3d_live_ key. |
| 404 | Order 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.