Appearance
Handle errors
Every error, from /oauth/token and from /v1, has the same shape:
json
{
"error": "invalid_request",
"error_description": "shipping_type: \"pigeon\" is not a supported courier; use one of: ecopost, ems, flash, jt, kex, spx_dropoff, spx_pickup"
}Branch on error, never on the text of error_description. The wording may improve over time, but the codes will not change. error_description is for people reading logs, and names the field at fault where there is one, e.g. products[1].qty.
Error codes
| Status | error | Meaning | What to do |
|---|---|---|---|
400 | invalid_request | Something in the request is wrong. Sending an id as a number instead of a string lands here too. | Fix the request. Do not retry it unchanged. |
400 | unsupported_grant_type | grant_type was not client_credentials. | Fix the request. |
401 | invalid_client | Token request: credentials rejected. | Check the Client ID and Secret. Do not retry in a loop: ten failures in five minutes block the client for 15 minutes. |
401 | invalid_token | /v1 call: the access token is missing, malformed or expired. | Get a new token and retry once. |
403 | access_denied | Your app may not do that for its store. | Contact the store owner. |
403 | quota_exceeded | The store's subscription order quota is used up. | Only the store owner can resolve it. |
404 | not_found | No such order or product, for you. | Check the id and its scope. |
413 | invalid_request | The request body is over 1 MB. | Send less. |
429 | slow_down | Token request rate limited. | Wait for as long as Retry-After says, and cache your token. |
500 | server_error | Our problem. | Retry. With an external_order_id, retrying an order create is safe. |
When to retry
500and network errors onorder/create: retry with the sameexternal_order_id. You get the order back whether or not the first attempt went through. See Retrying safely.401 invalid_token: get a new token, then retry the call once.429: wait forRetry-After, then retry.- Every other
4xx: do not retry. The same request will fail the same way.
Things we deliberately do not tell you
Some misses look the same on purpose, so the API cannot be used to probe for data that is not yours:
- An address id that is not your store's returns
400"no such address for this store", whether it does not exist at all or belongs to someone else. Askubehaves the same way. - Every miss on
POST /v1/order/detailis the same404: another store's order, another app's external id, a deleted order or an id that never existed. - Every miss on
POST /v1/product/detailis the same404too. - Every failed token request is the same
401 invalid_client: an unknown client, a wrong secret or an expired app.
Asking us for help
Include the request id of the failing call: the X-Request-Id response header, which every response carries, errors included. Successful responses also repeat it in the body as request_id. With it we can find that exact request in our logs.
