Every error code the PrintedSimply API can return, with its HTTP status and an actionable fix. Errors share a structured body — code, message, and a request_id. An error's doc_url links straight to its entry below (not_available's, to the API reference).
68 of 68 codes
Rate limit exceeded. Try again later.
Suggestion: The limit is 60 requests per 60 seconds. Check the X-RateLimit-Reset header for when you can retry.
Daily request quota exceeded for your plan.
Suggestion: You've reached your plan's daily request limit. It resets at 00:00 UTC. Retrying before then will not clear it.
Request body failed validation.
Suggestion: Check the details field for specific validation failures. Refer to the endpoint reference for required fields.
invalid_json400The request body is not valid JSON.
Suggestion: Send a JSON body with Content-Type: application/json and check for syntax errors.
The catalog this cursor walks is now served from another source.
Suggestion: A GET /v1/products cursor names a place in the catalog as it was served when the cursor was returned: live, from the last-good snapshot, from the local synced copy, or from our price book (details.issued_under). This page is served from another (details.source, with X-Catalog-Stale and X-Catalog-Degraded saying why), which is another list, so continuing would skip or repeat rows. Leave cursor out and walk the catalog again from the first page. details.issued_under is null for a cursor returned before cursors named their source; it is refused the same way. Retrying the same cursor succeeds only once the catalog is served from the source it names again.
Request body exceeds the size limit for this endpoint.
Suggestion: Most endpoints accept up to 256 KB. Asset uploads accept up to 70 MB of base64 in JSON; bulk orders have their own limit. Send artwork through POST /v1/assets and reference it by id rather than inlining it elsewhere.
not_found404The requested resource was not found.
Suggestion: Check the ID in the path. A resource another account owns answers the same 404 as one that does not exist. For a product, GET /v1/products lists every SKU you can order.
This path does not take the request's method.
Suggestion: The Allow header, and details.allow, list the methods this path takes; check the method against the API reference. Every path that takes GET also answers HEAD, and every path answers OPTIONS.
This API does not implement the request's method on any path.
Suggestion: Send GET, HEAD, OPTIONS, POST, PUT, PATCH or DELETE: no other method is implemented anywhere. Where the path exists, the Allow header and details.allow list the methods it takes.
Order not found.
Suggestion: Check the order ID and ensure you're using the correct API key mode (test vs live).
Order has already been cancelled.
Suggestion: This order was previously cancelled. Use GET /order/{id} to check current status.
Could not cancel order in production system.
Suggestion: The order may have already entered production. Contact support if this persists.
The order can no longer be cancelled.
Suggestion: An order can be cancelled only before it goes into production (pending_payment, paid or accepted). Once production has started it is made and shipped as placed, and nothing is refunded by this call; for anything else about the order, contact support at /contact.
The order can no longer be modified.
Suggestion: Address, shipping and line changes are taken only before the order goes into production (pending_payment, paid or accepted). Past that the order is made and shipped as placed; actions on GET /v1/order/{id} says what an order still takes, and support (/contact) answers anything else.
An order with this reference was already placed. Nothing was charged.
Suggestion: details.order_id names the order that already carries this reference (placed in the last 30 days and not cancelled, with a key of the same mode): read it with GET /v1/order/{id} instead of placing it again. details.in_flight means another request with this reference is being placed right now; wait a moment and look it up with GET /v1/orders?reference=. Cancelling an order frees its reference. To place a second order under the same reference on purpose, send allow_duplicate_reference: true.
The shipping address cannot be delivered as written. Nothing was charged.
Suggestion: details.findings names each problem with its field: zip_format (send five digits, or ZIP+4 as 12345-6789), state_unknown (send a USPS state, territory or military code such as TX, PR or AE), zip_state_mismatch (the ZIP belongs to a state that does not border the one named, so one of the two is wrong), or delivery_point_not_found (USPS has no delivery point at the street address: check the house number and street; a live order only, where USPS verification is configured). details.address_check.normalized is the address in USPS style. Check an address before ordering with POST /v1/addresses/validate. Nothing was charged and the Idempotency-Key is free for the corrected order.
A shopper paid for this order, so it takes no charge on your card.
Suggestion: A shopper paid for this order, so its refunds go back to the shopper. Place a separate order for anything you want to add.
This order cannot be reported as a missing letter.
Suggestion: details.reason says why: not_a_letter (it shipped as a parcel; use its tracking), not_shipped (it has not left the plant), not_yet_due (wait until details.expected_by), already_reshipped (one free replacement per letter; details.replacement_order_id names it) or is_a_reship (a replacement is not reshipped again; contact support).
order_error500The order could not be processed.
Suggestion: Retry the request; if the problem persists, contact support with the request id.
The payment was processed but the order record could not be updated. This request will not be retried automatically.
Suggestion: The money movement already completed — do NOT retry with a new Idempotency-Key, which would charge or refund a second time. Fetch the order to see its current state and contact support with the request id if it looks wrong.
The resource is not in a state that allows this operation.
Suggestion: Fetch the resource to confirm its current state before retrying.
The resource is already in a terminal state.
Suggestion: No further transitions are possible for this resource.
Another request with this Idempotency-Key is still in flight.
Suggestion: Wait for the original request to finish, then retry with the same key to get its result.
This Idempotency-Key was already used for a request with a different payload.
Suggestion: An Idempotency-Key identifies one specific request. Reuse it only to retry that exact payload; generate a new key for a new request.
Another request is already modifying this resource.
Suggestion: A competing write is in flight for the same resource. Retry shortly — this is a lock conflict, not a rejection, and the retry usually succeeds.
Variable data on one or more lines failed the preflight.
Suggestion: details.problems names each problem by item, unit and slot, with a code: not_own_plant (the SKU is not flat goods made at our own plant, or the order names another provider), count_mismatch (units needs exactly one entry per unit of quantity), unknown_slot, slot_conflict, missing_value, overflow (a value longer than its slot's max_length, or a QR payload over its ceiling) or too_many_units. Nothing was priced or charged; fix the lines and send the request again.
The artwork on one or more own-plant lines cannot be printed as it is.
Suggestion: details.problems names each line by item_index with a code: unreachable (the artwork URL answered 404 or 410), not_an_image (it returned a page or other non-image bytes) or low_resolution (too few pixels for the print size; the message says how many it needs). Nothing was charged and the Idempotency-Key is free: fix the files and send the order again. A test key (ps_test_*) is never refused for artwork; its response carries the same verdict in artwork_check.would_refuse.
One or more lines our own plant makes carry no artwork.
Suggestion: details.items names each line by item_index and sku (and order_index on POST /v1/orders/bulk). Send the line's file as artwork_url, or as print_file: a URL, or an asset id from POST /v1/assets. Nothing was charged and the Idempotency-Key is free. A test key (ps_test_*) is never refused for it; its response lists the lines in artwork_check.missing_artwork and says artwork_check.would_refuse.
Item not found.
Suggestion: Check the item ID. Use GET /order/{id} to see all items in the order.
This order exceeds a spend cap set on the API key.
Suggestion: The API key has a per-order or daily spend cap. Raise the cap in the dashboard, or use a different key. A cap bounds what one key can spend, whoever holds it.
No payment method on file. Add one at printedsimply.com/dashboard/billing.
Suggestion: Add a credit card at printedsimply.com/dashboard/billing before placing live orders.
Card was declined.
Suggestion: Update your payment method at printedsimply.com/dashboard/billing.
This payment requires 3DS authentication.
Suggestion: The card's bank wants the cardholder to approve this payment. On POST /order, details carries payment_intent and client_secret: approve it with Stripe.js handleNextAction, then send the same order again with payment_intent and a new Idempotency-Key. A caller with no browser (an MCP client, a server) hands the order to the person instead: they place the same order on the dashboard's order page, /dashboard/order, which runs the bank's check in their browser. Nothing is charged until that order is placed.
Could not process refund.
Suggestion: The refund could not be processed automatically. Contact support with your order ID and request ID.
fraud_review402The order was held for fraud review.
Suggestion: Our team reviews held orders quickly. Contact support to expedite.
Could not calculate price. Check SKUs are valid.
Suggestion: Verify that the SKUs exist by calling GET /products. Common SKUs: STICKER-DIE-CUT-3X3, STICKER-KISS-CUT-3X3.
These items require different production facilities.
Suggestion: Split the cart into one order per production method and place them separately.
The quote token is invalid or has expired.
Suggestion: Request a fresh quote and place the order before it expires.
The order does not match the quoted items or destination.
Suggestion: Place the order with exactly the items and address that were quoted, or get a new quote.
We do not hold an exchange rate for that presentment currency.
Suggestion: Quote in one of the supported currencies listed in the error details, or omit currency to settle in USD.
This order would cost more to make and ship than it is charged.
Suggestion: Nothing was charged. details.skus names the items and details.contribution_cents how far below zero the order falls at worst-case postage. Add units, combine it with another order, or choose another shipping method on offer.
unknown_sku400One or more SKUs are not in the catalog.
Suggestion: Check each SKU against GET /v1/products/{sku}: only a product the catalog can make can be ordered, quoted or sold. details.skus names the ones it does not have.
Production submission needs reconciliation.
Suggestion: Do not retry with a new key or refund the payment. Contact support with the request ID; production may already exist.
Could not complete operation in the production system.
Suggestion: This is a temporary issue with the production system. Retry with an Idempotency-Key header. Contact support if it persists.
Could not fetch data from upstream service.
Suggestion: This is usually a temporary issue: retry the request shortly. If the X-Catalog-Degraded header reads not_configured, the catalog is not set up on this deployment and a retry will not help; quote the request_id to support.
Payments are not configured on this deployment.
Suggestion: The Stripe signing secret is set but the Stripe secret key is not, so this event's handler cannot reach Stripe. Set STRIPE_SECRET_KEY; the event redelivers on Stripe's own retry schedule and is processed then.
The request could not be completed because of an unexpected error on our side.
Suggestion: This is our fault, not the request's — the same request may well succeed on retry. If it does not, quote the request_id from this response to support; it identifies the captured error.
The shop that produced this order does not support this operation.
Suggestion: This operation is unavailable at the producing facility. Contact support to confirm the existing production order before retrying an amendment or replacing it.
This operation is not available on this portal.
Suggestion: The API reference lists every operation this portal serves: orders, quotes, products, pricing and shipping estimates, artwork validation, asset uploads, webhooks and events.
This product isn't available from PrintedSimply.
Suggestion: details.skus names each one, and details.did_you_mean the products it most likely meant, when one is close. Only products our own plant makes can be ordered here — stickers, decals, magnets and posters; GET /v1/products lists them. Nothing was priced or charged; remove or replace those lines and send the request again.
Orders here are made by PrintedSimply.
Suggestion: Omit provider, or send "printedsimply". Nothing was priced or charged.
This webhook event isn't raised on PrintedSimply.
Suggestion: details.events names each one, and details.available lists every event a subscription can name here — an order's lifecycle, the catalog's and your endpoints' own — with "*" for all of them. Nothing was saved; drop those names and send the request again.
Need help debugging? Troubleshooting guide · Full API docs
Every error on this page comes back in the envelope by default. Send Accept: application/problem+json and the same error comes back as an RFC 9457 problem document, with Content-Type: application/problem+json: the shape HTTP clients and API tooling read without knowing ours.
curl https://portal.printedsimply.com/api/v1/order/ord_missing \
-H "x-api-key: ps_test_YOUR_KEY" \
-H "Accept: application/problem+json"| Member | What it carries |
|---|---|
type | Where the code is documented, as an absolute URI: its entry on this page, the same link as doc_url. |
title | The code's short title, the same on every occurrence: “Order not found” for order_not_found. |
status | The HTTP status, always the response's own. |
detail | What went wrong this time: the envelope's message. |
instance | This occurrence, as urn:uuid: and the request id: the id X-Request-Id and request_id carry. An idempotent replay is the original answer, so it repeats the original's request_id and instance under a new X-Request-Id. |
code, request_id, doc_url, suggestion, details | The envelope's own members, unchanged, as extension members. Keep branching on code. |
Accept names application/problem+json with a higher weight than application/json: application/problem+json alone, application/problem+json, application/json;q=0.9, or application/problem+json, */*.Accept, or with */*, application/* or application/json — and when application/json and application/problem+json are listed at the same weight.Vary: Accept, its headers (X-Request-Id, the rate-limit fields, Retry-After) are the same either way, and an idempotent replay of a stored error is converted like the original.A path no operation is at answers 404 not_found, and a method a path does not take answers 405 method_not_allowed with an Allow header that names the methods it takes (and details.allow), both with a request id, in either shape. A method no path takes at all, such as PROPFIND, answers 501 method_not_implemented on any path. Every path that takes GET answers HEAD too, and every path answers OPTIONS.