Skip to content

Error codes

Every error code the API returns — what it means, how to fix it and whether to retry.

Every error response has the body { "error": { "type", "code", "message", "param", "doc_url", "request_id" } }; doc_url links to the code on this page. Branch on code (stable), not on message. How to handle errors in code: Errors guide.

Error types

Type HTTP status Meaning
invalid_request_error 400, 409, 413, 415 The request is invalid: a parameter is missing or wrong, or the action is not allowed in the object's current state.
authentication_error 401 No API key, or the key is not valid.
permission_error 403 The key is valid but not allowed to make this request (scope, mode, IP allowlist, account status).
not_found_error 404 The object in the URL (or the URL itself) does not exist in the key's mode.
conflict_error 409 The request conflicts with existing data (duplicate external id, SKU already used, …).
idempotency_error 409 An Idempotency-Key was reused with different parameters, or the first request with that key is still running.
rate_limit_error 429 Too many requests. Wait for the number of seconds in the Retry-After header.
insufficient_funds_error 402 Your wallet does not have enough available credits (only when your account rejects instead of holding such orders).
api_error 500 Something went wrong on our side. Retry with the same Idempotency-Key; contact support with the request id if it persists.

All codes

Code Type Status
missing_api_key authentication_error 401
invalid_api_key authentication_error 401
insufficient_scope permission_error 403
account_suspended permission_error 403
account_closed permission_error 403
organization_suspended permission_error 403
organization_inactive permission_error 403
live_mode_disabled permission_error 403
ip_not_allowed permission_error 403
test_mode_only permission_error 403
forbidden permission_error 403
parameter_invalid invalid_request_error 400
parameter_missing invalid_request_error 400
resource_missing not_found_error 404, 400
route_not_found not_found_error 404
invalid_json invalid_request_error 400
invalid_request invalid_request_error 400
unsupported_media_type invalid_request_error 415
request_too_large invalid_request_error 413
idempotency_key_invalid invalid_request_error 400
idempotency_key_reused idempotency_error 409
idempotency_in_progress idempotency_error 409
idempotency_conflict idempotency_error 409
conflict conflict_error 409
invalid_state invalid_request_error 409
rate_limited rate_limit_error 429
file_invalid invalid_request_error 400
file_too_large invalid_request_error 400
file_unsafe invalid_request_error 400
file_unsupported_type invalid_request_error 400
download_failed invalid_request_error 400
download_not_an_image invalid_request_error 400
download_timeout invalid_request_error 400
file_download_failed invalid_request_error 400
artwork_download_budget_exceeded invalid_request_error 400
file_in_use conflict_error 409
file_not_artwork invalid_request_error 400
file_not_ready invalid_request_error 400
file_not_image invalid_request_error 400
designs_required invalid_request_error 400
unknown_placement invalid_request_error 400
placement_invalid invalid_request_error 400
duplicate_placement invalid_request_error 400
placement_required invalid_request_error 400
placement_unavailable invalid_request_error 400
no_layers invalid_request_error 400
too_many_layers invalid_request_error 400
invalid_transform invalid_request_error 400
invalid_opacity invalid_request_error 400
design_not_visible invalid_request_error 400
artwork_resolution_too_low invalid_request_error 400
catalog_product_unavailable invalid_request_error 400
catalog_variant_inactive invalid_request_error 400
variant_unavailable invalid_request_error 400
variant_disabled invalid_request_error 400
product_archived invalid_request_error 400, 409
product_has_no_designs invalid_request_error 400
sku_mismatch invalid_request_error 400
item_reference_required invalid_request_error 400
no_variants invalid_request_error 400
duplicate_variant invalid_request_error 400
duplicate_sku invalid_request_error 400
sku_taken conflict_error 409
external_id_taken conflict_error 409
variant_exists conflict_error 409
duplicate_external_id conflict_error 409
order_not_editable invalid_request_error 409
order_not_draft invalid_request_error 409
order_not_confirmable invalid_request_error 409
order_not_cancelable invalid_request_error 409
item_unavailable invalid_request_error 400
quantity_too_large invalid_request_error 400
insufficient_funds insufficient_funds_error 402
recipient_field_too_long invalid_request_error 400
recipient_phone_required invalid_request_error 400
recipient_email_required invalid_request_error 400
recipient_tax_id_required invalid_request_error 400
recipient_state_required invalid_request_error 400
po_box_not_supported invalid_request_error 400
military_address_not_supported invalid_request_error 400
recipient_local_script_required invalid_request_error 400
customization_unknown invalid_request_error 400
customization_invalid invalid_request_error 400
customization_required invalid_request_error 400
customization_not_applicable invalid_request_error 400
customization_value_hidden invalid_request_error 400
customization_unsupported invalid_request_error 400
shipping_method_unavailable invalid_request_error 400
variant_unpriceable invalid_request_error 400
variant_product_mismatch invalid_request_error 400
webhook_endpoint_limit_reached invalid_request_error 400
webhook_endpoint_disabled invalid_request_error 409
order_not_advanceable invalid_request_error 409
order_status_changed conflict_error 409
internal_error api_error 500, 502, 503

Authentication & permissions

Problems with the API key or what it is allowed to do.

missing_api_key

No API key was sent. HTTP 401 · type authentication_error

What it means: The request has no Authorization header (or it is empty).

How to fix: Send your secret key as a Bearer token: Authorization: Bearer sk_test_…. If you use a proxy or serverless platform, make sure it forwards the Authorization header.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

invalid_api_key

The API key is not valid. HTTP 401 · type authentication_error

What it means: The key is unknown, revoked or expired, or the Authorization header is malformed. The message says which.

How to fix: Copy the key again from Developers → API keys (the full secret is shown only once — create or roll a key if you lost it). Check that you did not mix up test (sk_test_) and live (sk_live_) keys and that there are no extra spaces or quotes.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

insufficient_scope

The key lacks a required scope. HTTP 403 · type permission_error

What it means: The key was created with restricted scopes and the endpoint needs another one. required_scope names it.

How to fix: Create a key that includes the scope (or full access *) in Developers → API keys. A :write scope includes the matching :read scope.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

Extra fields: required_scope

account_suspended

Your account is suspended. HTTP 403 · type permission_error

What it means: API access is paused for this account.

How to fix: Contact support to restore access. Nothing you send will be processed until then.

Retry: No — retrying the same request fails again.

account_closed

Your account is closed. HTTP 403 · type permission_error

What it means: The account that owns the key was closed.

How to fix: Contact support if you believe this is a mistake.

Retry: No — retrying the same request fails again.

organization_suspended

Orders cannot be placed while the account is suspended. HTTP 403 · type permission_error

What it means: The account was suspended, so new orders are refused.

How to fix: Contact support to restore the account.

Retry: No — retrying the same request fails again.

organization_inactive

Orders cannot be placed for a closed account. HTTP 403 · type permission_error

What it means: The account is no longer active.

How to fix: Contact support.

Retry: No — retrying the same request fails again.

live_mode_disabled

Live mode is not enabled yet. HTTP 403 · type permission_error

What it means: A live key was used (or a live order was placed) but live mode is not enabled for the account.

How to fix: Keep building with a test key (sk_test_…). To go live, verify your email address and follow the going live checklist; contact support if live mode still is not available.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

ip_not_allowed

Request IP is not on the key's allowlist. HTTP 403 · type permission_error

What it means: The key has an IP allowlist and the request came from another address.

How to fix: Add your server's public egress IP (or CIDR range) to the key in Developers → API keys, or remove the allowlist. Behind NAT, a load balancer or a serverless platform the egress IP can differ from the server's own address.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

test_mode_only

Endpoint only works with test keys. HTTP 403 · type permission_error

What it means: Test helpers (/test/…) cannot be called with a live key.

How to fix: Use a test key (sk_test_…).

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

forbidden

Not allowed. HTTP 403 · type permission_error

What it means: The action is not allowed for your role or in the current context (for example a dashboard member without the needed permission).

How to fix: Ask an owner or admin of your account to grant a role with the permission, or to perform the action.

Retry: No — retrying the same request fails again.

Request validation

The request itself is malformed or a parameter is wrong. Fix the request before retrying.

parameter_invalid

A parameter is missing or invalid. HTTP 400 · type invalid_request_error

What it means: A parameter has the wrong type or format, is out of range, is missing, or is not a known parameter (unknown parameters are rejected). param names it, e.g. items[0].quantity, and message explains the rule.

How to fix: Correct the parameter named in param. Compare your request with the API reference — request bodies are strict JSON objects with snake_case fields.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

Services may report this as validation_failed internally; the API always returns parameter_invalid.

parameter_missing

A required parameter is missing. HTTP 400 · type invalid_request_error

What it means: A parameter required by this operation was not sent. param names it.

How to fix: Add the parameter named in param.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

resource_missing

The object does not exist. HTTP 404 / 400 · type not_found_error

What it means: 404: the object in the URL does not exist. 400 (type invalid_request_error): an object referenced in the body — a sku, product_variant_id, file_id, catalog_variant_id, … — does not exist; param points at it.

How to fix: Check the id. Objects belong to one mode: test objects are invisible to live keys and vice versa. Orders can also be looked up with ext:<your external_id>.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

route_not_found

Unknown URL. HTTP 404 · type not_found_error

What it means: No endpoint exists for this method and path.

How to fix: Check the path, the HTTP method and the /api/v1 prefix against the API reference.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

invalid_json

The body is not valid JSON. HTTP 400 · type invalid_request_error

What it means: The request body could not be parsed as JSON.

How to fix: Send a JSON object with Content-Type: application/json. In shells, wrap the body in single quotes so variables and quotes are not mangled.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

invalid_request

The body could not be parsed. HTTP 400 · type invalid_request_error

What it means: The request body could not be read (for example a broken multipart form).

How to fix: Send JSON, or for POST /files a well-formed multipart/form-data body with a file field.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

unsupported_media_type

Unsupported Content-Type. HTTP 415 · type invalid_request_error

What it means: The body uses a content type the endpoint does not accept.

How to fix: Use Content-Type: application/json. Only POST /files also accepts multipart/form-data.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

request_too_large

The body is too large. HTTP 413 · type invalid_request_error

What it means: JSON bodies are limited to 2 MB; file uploads to the maximum file size plus 1 MB of form overhead.

How to fix: Split large batches into several requests. For big artwork, upload by URL (POST /files with {"url": …}) or reduce the file size.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

idempotency_key_invalid

The Idempotency-Key header is invalid. HTTP 400 · type invalid_request_error

What it means: The header is empty, longer than 255 characters, or contains spaces or non-printable characters.

How to fix: Use a UUID or another printable ASCII string of at most 255 characters.

Retry: After fixing the request. The rejected request was not stored, so the same Idempotency-Key can be reused (details).

Idempotency, concurrency & rate limits

Retries and concurrent requests.

idempotency_key_reused

Idempotency-Key reused with different parameters. HTTP 409 · type idempotency_error

What it means: The key was already used in the last 24 hours with a different method, path or body.

How to fix: Use a new key for every distinct request; reuse a key only to retry exactly the same request.

Retry: No — retrying the same request fails again.

idempotency_in_progress

The first request with this key is still running. HTTP 409 · type idempotency_error

What it means: A request with the same Idempotency-Key has not finished yet.

How to fix: Wait for the Retry-After seconds (1) and retry with the same key and body; you will get the original response.

Retry: Yes — retry with the same Idempotency-Key.

idempotency_conflict

Operation already recorded with different values. HTTP 409 · type idempotency_error

What it means: An internal operation key was reused for a different operation (for example two different amounts for the same refund).

How to fix: Do not retry with changed values. Contact support with the request id if you did not expect this.

Retry: No — retrying the same request fails again.

conflict

Conflict with the current state. HTTP 409 · type conflict_error

What it means: The object changed concurrently or the request conflicts with existing data.

How to fix: Fetch the object again and retry the request if it still applies.

Retry: Yes, later — back off and retry.

invalid_state

Not allowed in the current state. HTTP 409 · type invalid_request_error

What it means: The action is not possible in the object's current state.

How to fix: Fetch the object to check its status before retrying.

Retry: No — retrying the same request fails again.

rate_limited

Too many requests. HTTP 429 · type rate_limit_error

What it means: The key exceeded its request rate (a token bucket refilled continuously over a minute).

How to fix: Wait for the number of seconds in Retry-After, then retry; add exponential backoff with jitter. See rate limits.

Retry: Yes, later — back off and retry.

Files & artwork

Uploading artwork and using files in designs.

file_invalid

The file could not be read. HTTP 400 · type invalid_request_error

What it means: The file is empty, corrupt or truncated, or its dimensions cannot be read (for SVG: unreadable or with an absurd declared size).

How to fix: Re-export the artwork as PNG (recommended) or JPEG and upload it again.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_too_large

The file is too large. HTTP 400 · type invalid_request_error

What it means: The file exceeds the maximum upload size (100 MB by default), 30,000 px on a side, or 250 megapixels (width × height) in total — images are checked before they are decoded.

How to fix: Reduce the file size or dimensions. 300 DPI at the print size is all you need — see the placement's recommended_width_px.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_unsafe

The SVG contains unsafe content. HTTP 400 · type invalid_request_error

What it means: SVG files must not contain scripts, event handlers or references to external resources.

How to fix: Export a plain SVG (outlined text, embedded images) or a PNG.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_unsupported_type

Unsupported file type. HTTP 400 · type invalid_request_error

What it means: Only PNG, JPEG, WebP, TIFF, GIF (first frame) and SVG images are accepted.

How to fix: Convert the artwork to PNG.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

download_failed

The file could not be downloaded. HTTP 400 · type invalid_request_error

What it means: We could not download the url (connection error, non-2xx response, more than 5 redirects or a redirect without a location). A connection reset or an HTTP 429/502/503/504 answer is retried once before this error.

How to fix: Make sure the URL is public (no login, no signed URL that expired), returns the image itself with HTTP 200, and is reachable over http(s) from the internet.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

download_not_an_image

The URL returned a web page, not an image. HTTP 400 · type invalid_request_error

What it means: The url answered with an HTML page (a share page, a login page or an error page) instead of the image file itself. Share links of file hosts usually point at such a page.

How to fix: Use a direct link to the image file (for example the host's "download" or "raw" link), or upload the file with multipart/form-data.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

download_timeout

Downloading the file timed out. HTTP 400 · type invalid_request_error

What it means: The url did not deliver the file in time.

How to fix: Host the file somewhere faster (a CDN or object storage) or upload it with multipart/form-data.

Retry: Yes, later — back off and retry.

file_download_failed

Artwork URL of an order item could not be downloaded. HTTP 400 · type invalid_request_error

What it means: A url layer of an inline order design was refused (not an http(s) URL, a URL with credentials, or a host that is not public or cannot be resolved) or could not be downloaded. Problems with a more specific cause are reported with that code instead: download_failed, download_not_an_image, download_timeout, file_too_large, file_invalid, file_unsupported_type, file_unsafe. param points at the layer.

How to fix: Check that the URL is public and returns a supported image, or upload the file first and use its file_id.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

artwork_download_budget_exceeded

The order's artwork took too long to download. HTTP 400 · type invalid_request_error

What it means: An order downloads all of its url layers within one time budget (45 seconds by default; a few at a time). The budget ran out before every URL was downloaded, so nothing was created. URLs downloaded so far are kept as artwork files and reused when you send the order again, so a retry is cheaper.

How to fix: Upload large or slow artwork first with POST /files and reference it with file_id, host the artwork on a fast CDN, or split the order.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_in_use

The file is used by a product. HTTP 409 · type conflict_error

What it means: Files used by a product that is not archived cannot be deleted.

How to fix: Archive the product (DELETE /products/{id}) or replace its artwork first, then delete the file.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_not_artwork

The file cannot be used as artwork. HTTP 400 · type invalid_request_error

What it means: Only files uploaded as artwork or logo can be placed in designs (not mockups or other generated files).

How to fix: Upload the image with POST /files and use the returned file_id.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

file_not_ready

The file is not ready. HTTP 400 · type invalid_request_error

What it means: The file is still processing or failed processing.

How to fix: Use files whose status is ready. Upload again if it failed.

Retry: Yes, later — back off and retry.

file_not_image

The file is not an image. HTTP 400 · type invalid_request_error

What it means: Designs need image files with known pixel dimensions.

How to fix: Upload a PNG, JPEG, WebP, TIFF, GIF or SVG image.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Designs

Placing artwork on print areas (see Designs & transforms).

designs_required

No designs. HTTP 400 · type invalid_request_error

What it means: A product needs at least one design.

How to fix: Send designs: [{ "placement": "front", "layers": [{ "file_id": "file_…" }] }].

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

unknown_placement

Unknown placement. HTTP 400 · type invalid_request_error

What it means: The placement key does not exist on this catalog product. The message lists the available keys.

How to fix: Use a placements[].key from GET /catalog/products/{id}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

placement_invalid

Placement not available on this product. HTTP 400 · type invalid_request_error

What it means: A price calculation was asked for a placement key (placement_keys) the catalog product does not have. Order requests, estimates and shipping-rate quotes report an unknown design placement as unknown_placement instead.

How to fix: Use a placements[].key from GET /catalog/products/{id}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

duplicate_placement

Placement listed twice. HTTP 400 · type invalid_request_error

What it means: Each placement may appear only once in designs.

How to fix: Merge the layers into one design entry per placement (up to 20 layers each).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

placement_required

A required placement has no artwork. HTTP 400 · type invalid_request_error

What it means: The catalog product requires artwork on a placement (placements[].required: true) that your designs do not cover.

How to fix: Add a design for the placement named in the message.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

placement_unavailable

No production option prints this placement. HTTP 400 · type invalid_request_error

What it means: Reported in errors of an item_unavailable error: no production option of the item's variant can print on this placement for the destination, so the item can't be made with a design there. param names the design (items[i].designs[j].placement).

How to fix: Remove the design from this placement (or move the artwork to another placement), or choose another variant.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

no_layers

A design has no layers. HTTP 400 · type invalid_request_error

What it means: Every design entry needs at least one layer.

How to fix: Add a layer with a file_id or url, or remove the design entry.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

too_many_layers

Too many layers. HTTP 400 · type invalid_request_error

What it means: A placement can have at most 20 layers — for an order item that appends layers to a saved product's design, the product's layers count too.

How to fix: Flatten artwork into fewer images.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

invalid_transform

Invalid position. HTTP 400 · type invalid_request_error

What it means: A layer's position has non-numeric values, a zero/negative size, or values beyond ±10.

How to fix: Use fractions of the print area (0–1, small overshoots allowed for bleed) — see Designs & transforms.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

invalid_opacity

Invalid opacity. HTTP 400 · type invalid_request_error

What it means: opacity must be a number between 0 and 1.

How to fix: Send a value from 0 to 1 (default 1).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

design_not_visible

No artwork inside the print area. HTTP 400 · type invalid_request_error

What it means: Every layer of a placement lies completely outside the printable area, so nothing would be printed.

How to fix: Move the layers inside the area (fractions between 0 and 1), or omit position to center the artwork.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

artwork_resolution_too_low

Artwork resolution too low to print. HTTP 400 · type invalid_request_error

What it means: At the size you placed it, the artwork would print below the minimum resolution (75 DPI by default). The message shows the effective DPI.

How to fix: Use a larger image or place it smaller. Aim for 300 DPI: recommended_width_px of the placement covers the full area at 300 DPI.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Products & SKUs

Creating products, variants and SKUs, and referencing them in orders.

catalog_product_unavailable

Catalog product no longer available. HTTP 400 · type invalid_request_error

What it means: The catalog product exists but is not offered anymore.

How to fix: Pick another product from GET /catalog/products.

Retry: No — retrying the same request fails again.

catalog_variant_inactive

Catalog variant no longer available. HTTP 400 · type invalid_request_error

What it means: The catalog variant was retired.

How to fix: Pick another variant from GET /catalog/products/{id}.

Retry: No — retrying the same request fails again.

variant_unavailable

Variant not available. HTTP 400 · type invalid_request_error

What it means: The variant (or its catalog product) is no longer available, so it cannot be added or ordered.

How to fix: Choose another variant; disable this one in your store. Listen to catalog.price_changed and check available on variants.

Retry: No — retrying the same request fails again.

variant_disabled

Product variant is disabled. HTTP 400 · type invalid_request_error

What it means: You disabled this product variant, so it cannot be ordered.

How to fix: Re-enable it with PATCH /products/{id}/variants/{variant_id} {"enabled": true}, or order another variant.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

product_archived

Product is archived. HTTP 400 / 409 · type invalid_request_error

What it means: Archived products cannot be ordered (400) or edited (409).

How to fix: Restore the product by setting a status: PATCH /products/{id} {"status": "active"}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

product_has_no_designs

Product has no artwork. HTTP 400 · type invalid_request_error

What it means: The product has no designs, so there is nothing to print.

How to fix: Add designs with PATCH /products/{id} {"designs": […]}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

sku_mismatch

SKU does not match the variant. HTTP 400 · type invalid_request_error

What it means: Both a product variant id and a SKU were given and they refer to different variants.

How to fix: Identify each item with exactly one of product_variant_id, sku or catalog_variant_id.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

item_reference_required

Item has no product reference. HTTP 400 · type invalid_request_error

What it means: An item does not say which product to make.

How to fix: Set sku, product_variant_id, or catalog_variant_id + designs on every item.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

no_variants

No available variants. HTTP 400 · type invalid_request_error

What it means: The catalog product currently has no variant you can add.

How to fix: Pick another catalog product or try again later.

Retry: No — retrying the same request fails again.

duplicate_variant

Variant listed twice. HTTP 400 · type invalid_request_error

What it means: The same catalog_variant_id appears more than once in variants.

How to fix: List each catalog variant once.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

duplicate_sku

SKU used twice in the request. HTTP 400 · type invalid_request_error

What it means: Two variants in the same request have the same SKU.

How to fix: Give every variant a unique SKU (or omit sku to have one generated).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

sku_taken

SKU already in use. HTTP 409 · type conflict_error

What it means: Another product variant in your account already has this SKU. SKUs are unique per account (disabled and archived variants keep theirs).

How to fix: Use a different SKU, or change the SKU of the other variant first. Find it with GET /products/by_sku/{sku}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

external_id_taken

Product external_id already in use. HTTP 409 · type conflict_error

What it means: Another product already uses this external_id.

How to fix: Use a unique external_id per product (for example your store's product id).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

variant_exists

Variant already on the product. HTTP 409 · type conflict_error

What it means: The catalog variant is already part of this product.

How to fix: Update the existing variant with PATCH /products/{id}/variants/{variant_id} instead.

Retry: No — retrying the same request fails again.

Orders

Creating, changing and canceling orders (see Orders).

duplicate_external_id

An order with this external_id exists. HTTP 409 · type conflict_error

What it means: external_id is unique per mode, and an order already has it. existing_id is that order's id.

How to fix: Do not create the order again — fetch it with GET /orders/{existing_id} (or GET /orders/ext:<external_id>). This usually means your integration already forwarded the order.

Retry: No — retrying the same request fails again.

Extra fields: existing_id

order_not_editable

Only draft orders can be changed. HTTP 409 · type invalid_request_error

What it means: The order was already confirmed.

How to fix: Cancel the order (if it has not gone into production) and create a corrected one.

Retry: No — retrying the same request fails again.

order_not_draft

The order is not a draft. HTTP 409 · type invalid_request_error

What it means: Only draft orders can be confirmed; this one is already confirmed (or canceled).

How to fix: Fetch the order to see its status. Confirming twice is not needed.

Retry: No — retrying the same request fails again.

order_not_confirmable

The draft cannot be confirmed. HTTP 409 · type invalid_request_error

What it means: The draft has no items, or it was changed (items, recipient or shipping method) while it was being confirmed.

How to fix: Add items with PATCH /orders/{id} first. After a concurrent change, fetch the draft again and confirm it then.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

order_not_cancelable

The order can no longer be canceled. HTTP 409 · type invalid_request_error

What it means: Production already started, the order is being sent to production right now, or it already shipped, failed or was delivered. The message says which.

How to fix: If the message says to try again in a minute, retry later. Once production has started the order cannot be canceled.

Retry: Yes, later — back off and retry.

item_unavailable

Item cannot be produced for this destination. HTTP 400 · type invalid_request_error

What it means: No production option can make this item for this order right now (param names it): nothing ships it to the recipient's country, it is out of stock, or several requirements of the order rule out every option. Problems you can fix yourself are reported with their own codes instead (recipient fields, shipping method, quantity, customizations); errors may name a placement that can't be printed (placement_unavailable).

How to fix: Remove the item, choose another variant, or contact support for availability.

Retry: No — retrying the same request fails again.

quantity_too_large

Quantity too large for this item. HTTP 400 · type invalid_request_error

What it means: The production options of this item accept at most max_quantity units of it in one order (param = items[i].quantity). Nothing was created.

How to fix: Lower the quantity to max_quantity or less, or split the units over several orders.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: max_quantity

insufficient_funds

Not enough credits. HTTP 402 · type insufficient_funds_error

What it means: Your account is set to reject (not hold) orders your wallet cannot cover, and available credits are too low. required_amount and available_amount are in cents. Nothing was created.

How to fix: Add credits (or enable auto-recharge), then send the order again with a new Idempotency-Key (for example order-1042:2). The 402 is stored under the original key for 24 hours, so a retry with that key returns this error again even after you added credits; external_id still prevents a duplicate order. Or switch Settings → Orders → When credits run out to hold so orders wait and resume automatically, with nothing to retry. In test mode call POST /test/wallet/fund.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: required_amount, available_amount, currency

Recipient & destination

Checked when an order is created, estimated or confirmed, against what the production options of its items can accept: nothing is created or reserved, and param names the recipient field. Messages never repeat the recipient's data.

recipient_field_too_long

A recipient field is too long. HTTP 400 · type invalid_request_error

What it means: The field named by param (for example recipient.city or recipient.address1) is longer than every production option of an item accepts. max_length is the largest length (characters, as people count them: an emoji or an accented letter is one) that at least one option accepts; errors lists other fields that option needs shorter.

How to fix: Shorten the field to max_length characters or fewer (for street addresses, move part of address1 to address2) and send the order again.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: max_length

recipient_phone_required

A recipient phone number is required. HTTP 400 · type invalid_request_error

What it means: The carriers available for this destination and shipping method need a phone number to deliver. When another shipping method would deliver without one, available_shipping_methods lists those methods.

How to fix: Add recipient.phone, or choose one of available_shipping_methods.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: available_shipping_methods

recipient_email_required

A recipient email address is required. HTTP 400 · type invalid_request_error

What it means: The carriers available for this destination and shipping method need an email address for delivery notifications. When another shipping method would deliver without one, available_shipping_methods lists those methods.

How to fix: Add recipient.email, or choose one of available_shipping_methods.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: available_shipping_methods

recipient_tax_id_required

A recipient tax id is required. HTTP 400 · type invalid_request_error

What it means: Customs of the destination require the recipient's tax id (for Brazil the CPF or CNPJ).

How to fix: Add recipient.tax_id.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

recipient_state_required

A state is required. HTTP 400 · type invalid_request_error

What it means: Shipments to this country need a state or province (recipient.state_code).

How to fix: Add recipient.state_code (ISO 3166-2 subdivision code, e.g. CA for California).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

po_box_not_supported

PO boxes are not supported for this order. HTTP 400 · type invalid_request_error

What it means: An address line is a PO box (param names it), and the items can't be delivered to PO boxes with this shipping method (couriers deliver to street addresses only). available_shipping_methods lists the methods that do deliver to it, when there are any.

How to fix: Use a street address, or one of available_shipping_methods (usually standard).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: available_shipping_methods

military_address_not_supported

Military addresses are not supported. HTTP 400 · type invalid_request_error

What it means: The address is an APO / FPO / DPO military address (state AA, AE or AP, or city APO / FPO / DPO), which the production options of an item can't deliver to.

How to fix: Use a civilian address, or remove the item.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

recipient_local_script_required

The address must be in the local script. HTTP 400 · type invalid_request_error

What it means: For this destination (for example Japan, China, Korea or Russia) the address lines and city must be written in the local script; the field named by param has too many Latin letters.

How to fix: Send the address as the recipient would write it locally (e.g. 東京都渋谷区…).

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Customizations

Options of a catalog product beyond its variants (a frame color, thread colors, a name…). An order item gets the values saved on its product, else each option's default; param is items[i].customizations.<key> (just items[i] for an option that is managed only in the dashboard) and every problem of the request is listed in errors.

customization_unknown

Unknown customization. HTTP 400 · type invalid_request_error

What it means: The key is not a customization of this product. allowed_values lists the valid keys (empty when the product has none).

How to fix: Use the keys of the catalog product's customizations.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: allowed_values

customization_invalid

Invalid customization value. HTTP 400 · type invalid_request_error

What it means: The value has the wrong type (types are never converted: the string "true" is not a boolean, the string "3" is not a number) or is outside the option's range, length, pattern or palette; the message says which. For a choice, allowed_values lists the accepted values ([true, false] for yes/no options). A product's saved value that is no longer valid is reported the same way.

How to fix: Send a value of the option's type and range (or one of allowed_values), or update the product's saved value.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: allowed_values

customization_required

A customization value is required. HTTP 400 · type invalid_request_error

What it means: The option is required and has no default, and neither the item nor the product sets it. allowed_values lists the choices of choice and yes/no options.

How to fix: Send a value for the key named by param.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: allowed_values

customization_not_applicable

The option needs a design on its placement. HTTP 400 · type invalid_request_error

What it means: The option belongs to one placement (for example embroidery thread colors of the left chest) and the item has no design there.

How to fix: Add a design on that placement, or leave the option out.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

customization_value_hidden

The value is no longer offered. HTTP 400 · type invalid_request_error

What it means: The value was retired for new orders. Products that already use it keep it, but it can't be chosen again. allowed_values lists the current choices.

How to fix: Choose one of allowed_values.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: allowed_values

customization_unsupported

Option not available for this destination. HTTP 400 · type invalid_request_error

What it means: No production option can make the item with this customization value for this destination (for example a frame color one factory doesn't stock). With the default value the item could be made.

How to fix: Choose another value, leave the option at its default, or ship to another destination.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Shipping & pricing

Prices and shipping methods for a destination.

shipping_method_unavailable

Shipping method not available. HTTP 400 · type invalid_request_error

What it means: The shipping_method is not offered for these items and this destination (or nothing can ship there). The message and available_shipping_methods list the methods that are available.

How to fix: Call POST /shipping/rates and use one of the returned methods (or one of available_shipping_methods); standard is the most widely available.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Extra fields: available_shipping_methods

variant_unpriceable

Variant cannot be priced right now. HTTP 400 · type invalid_request_error

What it means: The variant has no available production source at the moment.

How to fix: Try another variant or try again later.

Retry: Yes, later — back off and retry.

variant_product_mismatch

Variant does not belong to the product. HTTP 400 · type invalid_request_error

What it means: A catalog variant was combined with a different catalog product.

How to fix: Use variant ids from the same GET /catalog/products/{id} response.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Webhooks

Managing webhook endpoints.

webhook_endpoint_limit_reached

Too many webhook endpoints. HTTP 400 · type invalid_request_error

What it means: Each mode can have up to 16 endpoints by default.

How to fix: Delete unused endpoints, or subscribe one endpoint to several event types.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

webhook_endpoint_disabled

The endpoint is disabled. HTTP 409 · type invalid_request_error

What it means: Test events and replays cannot be sent to a disabled endpoint.

How to fix: Re-enable it with PATCH /webhook_endpoints/{id} {"status": "enabled"}.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Test mode

Test helpers (see Test mode).

order_not_advanceable

The test order cannot advance. HTTP 409 · type invalid_request_error

What it means: The order is a draft, already finished (delivered, canceled, failed), or on hold for a reason that needs action (for example waiting for credits), or the requested outcome doesn't fit its current state (for example a partial shipment of a single unit, or a delivery problem before anything shipped).

How to fix: Confirm drafts first; add test credits with POST /test/wallet/fund for orders waiting for funds. Fetch the order and pick an outcome that fits its status.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

order_status_changed

The test order changed status first. HTTP 409 · type conflict_error

What it means: The simulated step was requested for an order status that is no longer current: the simulator (or another request) moved the order on in the meantime. Nothing was changed.

How to fix: Fetch the order again, check its new status, and simulate the next step from there if it is still needed.

Retry: After fixing the cause, with a new Idempotency-Key: the original key can replay this error for 24 hours, even after the fix (details).

Server errors

Problems on our side.

internal_error

Internal error. HTTP 500 / 502 / 503 · type api_error

What it means: Something went wrong on our side. No details are returned; the error is logged with the request id.

How to fix: Retry with exponential backoff and the same Idempotency-Key (the request is never half-applied). If it keeps happening, contact support with the request_id.

Retry: Yes — retry with the same Idempotency-Key.

Warnings

Product create and update responses can include non-blocking warnings (code, message, param, placement, effective_dpi). The request succeeded; review them before selling the product.

dpi_low

Artwork may print slightly blurry. At the placed size the artwork is below the recommended resolution (150 DPI by default, or the placement's min_dpi when higher). effective_dpi shows the value.

How to fix: Use a larger image or place it smaller. The product is still created.

layer_outside_area

Layer will not be printed. A layer is completely outside the print area (or has opacity 0), so it will not appear on the product.

How to fix: Move the layer inside the area or remove it.