Docs › API reference

Errors, limits and idempotency

Error format and every error code, rate limits, order limits and idempotency.

Error format

Errors are returned as application/problem+json (RFC 9457):

json
{
  "type": "https://www.promogator.com/on-demand/docs/errors#error-validation-failed",
  "title": "The order cannot be priced as sent",
  "status": 422,
  "detail": "SKU ST-WILD-SPT-PNK-L is not on your product list.",
  "instance": "/api/on-demand/v1/orders",
  "code": "validation_failed",
  "request_id": "req_8fK2mQ0aB1cD3eF4",
  "errors": [ { "detail": "SKU ST-WILD-SPT-PNK-L is not on your product list." } ]
}

Write your code against code: it never changes. title and detail are written for people and may be reworded. Quote request_id when you contact us.

Error codes

Status Code What to do
400 credentials_in_url Move credentials to the Authorization header and roll the key
400 idempotency_key_required Add an Idempotency-Key header
401 unauthorized Send Authorization: Bearer <token>
401 invalid_token Get a new token
401 token_expired Get a new token and retry
402 card_declined Fix the card; nothing was ordered
402 authentication_required The bank wants approval; contact us
402 payment_method_required Add a card on the Billing tab
402 payment_failed Retry later, or contact us
403 insufficient_scope Use a key with the scope in required_scope
403 ip_not_allowed Call from an allowed address
403 api_not_enabled Live access is not on yet: use your test key
403 sandbox_not_enabled Ask us to switch test mode on
403 partner_suspended Your account is paused; contact us
404 not_found Check the id and the mode (test or live)
409 idempotency_conflict Use a new key for a different order
409 duplicate_external_id Fetch the existing order
409 not_cancellable Too late to cancel; contact us
409 account_incomplete Contact us
415 unsupported_media_type Send Content-Type: application/json
422 validation_failed Fix what errors[] describes
422 limit_exceeded A new live key's probation limit, or too many webhook endpoints
429 rate_limited Wait Retry-After seconds
500 internal_error Retry with the same Idempotency-Key
503 api_unavailable Try again later
503 read_only Reads work; retry writes later

credentials_in_url

A token, key or secret was in the URL. URLs end up in logs, so the request is refused. Send credentials only in the Authorization header, and roll the key: its secret may already be in a log.

idempotency_key_required

POST /orders needs an Idempotency-Key header of up to 255 characters.

unauthorized

No Authorization: Bearer … header. Get a token from POST /oauth/token.

invalid_token

The token is unknown, or its key was revoked or rolled. Get a new token.

token_expired

The token is older than 60 minutes. Get a new token and send the request again.

card_declined

Your card was declined. decline_code has the bank's reason. No order was created and nothing was charged. Update the card on the Billing tab and send the order again (a new request, so use a new Idempotency-Key).

authentication_required

Your bank asked for extra approval of the charge. No order was created. Contact us.

payment_method_required

Your account bills a card but none is saved with permission for automatic charges. Add one on the Billing tab.

payment_failed

The payment could not be completed. No order was created. Try again later or contact us.

insufficient_scope

The token does not have the scope this call needs; required_scope names it. Use a key with that scope.

ip_not_allowed

The key is limited to certain IP addresses and this call came from another one.

api_not_enabled

A live key was used before live access was switched on for your account. Use your test key, or ask us for live access.

sandbox_not_enabled

Test mode is switched off for your account. Ask us to switch it on.

partner_suspended

Your partner account is paused. Reads keep working; new orders are refused. Contact us.

not_found

No such object in your account, or it belongs to the other mode: test keys only see test objects and live keys only live ones.

idempotency_conflict

The Idempotency-Key was already used with a different request body. Each order needs its own key.

duplicate_external_id

An order with this external_id already exists. Fetch it with GET /orders/by-external-id/{external_id} instead of sending it again.

not_cancellable

The order can no longer be cancelled: the 24-hour window has closed, production has started, or it is already cancelled. detail says which. Contact us if you still need a change.

account_incomplete

Your partner account is missing something we need to place orders. Contact us.

unsupported_media_type

Send JSON with Content-Type: application/json.

validation_failed

The request cannot be accepted as sent. Each problem is in errors[] (with a pointer for field errors). Common causes: a missing required field, an unknown field, a SKU that is not on your product list, a quantity under the product's minimum, an address outside the US, a product that ships by freight, or an order over your maximum order value or orders-per-day limit.

limit_exceeded

A new live key is on probation for its first 24 hours and can place up to 3 orders or $500.00 in that time; ask us to end probation early. Also returned when you try to add a sixth webhook endpoint in one mode.

rate_limited

Too many requests. Wait the number of seconds in the Retry-After header, then retry.

internal_error

Something went wrong on our side. Nothing was charged. Retry with the same Idempotency-Key, and contact us with the request_id if it keeps happening.

api_unavailable

The API is switched off for maintenance. Nothing was charged. Try again later.

read_only

The API is read-only for a while: reads work, new orders and quotes are paused. Retry later.

Rate limits

What Limit
Reads (GET) 300 requests a minute per key
Writes (POST, PATCH, DELETE) 60 requests a minute per key
POST /oauth/token 20 requests a minute per key

Over the limit you get 429 with a Retry-After header (seconds).

Order limits

Each account has a maximum order value and a maximum number of orders per day, shown in GET /account under limits. An order over a limit is refused with 422 validation_failed and a message naming the limit. A new live key is also on probation for its first 24 hours: up to 3 orders or $500.00. Ask us to raise a limit or end probation early.

Idempotency

Networks fail. An Idempotency-Key makes it safe to retry POST /orders:

  • Send a unique Idempotency-Key with every new order (your store's order id works well).
  • If you do not get a response, send the same request with the same key. If we already placed the order, you get it back (200 with Idempotent-Replayed: true) instead of a second order.
  • The same key with a different body is refused with 409 idempotency_conflict.
  • external_id is a second safety net: an order number can only be used once in your account.

After a 402 payment error no order exists, so fix the card and send the order with a new key.

Need a hand? Partners: your account manager's details are on the Overview tab of your portal. Everyone else: call (877) 737-8191 or email support@promogator.com.
Compare /

Compare Products

Highlighted rows = products differ on this attribute