Every failed request on the OLET API returns the same JSON shape: {"error": {"code": "...", "message": "...", "fields": [...]}}. fields only appears when the problem is about specific request fields. Branch your code on code, and show message to a person if you need to.
What does the error envelope look like
Section titled “What does the error envelope look like”curl https://api.oletapp.com/your-store/v1/products/does-not-exist \ -H "Authorization: Bearer olet_live_YOUR_API_KEY"const res = await fetch(url, { headers })if (!res.ok) { const { error } = await res.json() console.error(error.code, error.message)}A validation failure adds fields, a list of {field, message} pairs naming exactly what was wrong:
{ "error": { "code": "VALIDATION_FAILED", "message": "Check the highlighted fields and try again.", "fields": [ { "field": "cursor", "message": "This cursor is invalid. Pass back the exact next_cursor value from a previous response, never one you construct yourself." } ] }}What does each error code mean
Section titled “What does each error code mean”Every code below is also listed in the ErrorEnvelope schema of the OpenAPI spec.
| Code | Status | What to do |
|---|---|---|
UNAUTHORIZED |
401 | Your credential is missing, malformed, unknown, revoked, or has gone idle past 90 days. Check the Authorization header and, for an idle credential, create a new one. |
VALIDATION_FAILED |
400 | The request body, a query parameter (including cursor) or the Idempotency-Key header failed validation. Read fields and fix each one. A nested field is named with dots, such as lines.2. |
NOT_FOUND |
404 | The resource does not exist, is deleted, or belongs to a different store. An id that is not a valid UUID, or a path that is not part of the API, answers the same way. Double-check the id. |
CONFLICT |
409 | The write collided with an existing value or a rule, such as a SKU already in use, a duplicate brand or tag name, or deleting something that is still in use. Change the request and retry. |
UNPROCESSABLE |
422 | The request referenced something that could not be found, exceeded a cap (for example more than 10 codes on one product), or otherwise could not be carried out as written. |
RATE_LIMITED |
429 | You went over a rate limit, or too many product image imports were already running. See rate limits and slow down. |
IDEMPOTENCY_IN_PROGRESS |
409 | A request with the same Idempotency-Key is still being processed. Wait and retry. |
IDEMPOTENCY_KEY_REUSED |
422 | You reused an Idempotency-Key with a different request body. Use a new key per logical operation. |
INTERNAL |
500 | Something went wrong on our side. Safe to retry after a short delay. |
INSUFFICIENT_SCOPE |
403 | Your API key or OAuth connection lacks the scope this endpoint needs. See authentication for the scope table. |
PLAN_REQUIRED, PLAN_USERS_EXCEEDED, PRODUCT_LIMIT_REACHED |
402 | Your store’s current plan does not include API access (it needs the Growth plan), or a plan limit was reached, such as the product limit on a product create. Ask whoever manages billing to review the plan. |
RETAILER_CANCELLED, RETAILER_SUSPENDED, RETAILER_NOT_FOUND |
403 | The store cannot currently take API calls because of its account status. Check the store’s status in the back office. |
RETAILER_PAUSED, TRIAL_DECISION_REQUIRED |
402 | The store’s owner needs to act in Settings › Billing (resume the store, or choose a plan) before API calls resume. |
STALE_VERSION |
409 | The version (or expected_version) you sent with a product update no longer matches the product. Reload it and try your change again. |
NOT_STOCK_TRACKED, REASON_DIRECTION_MISMATCH, INSUFFICIENT_STOCK |
422 | An inventory rule refused the request, for example adjusting stock on a product that does not track it. Read message for the specific reason. |
REASON_NOT_ALLOWED |
422 | The stock adjustment reason_id is a system reason or is turned off. Pick a reason that is enabled and is not a system reason. |
OUTLET_DELETED |
422 | A stock write named an outlet that has been deleted. Nothing is written. |
IMAGE_FETCH_FAILED |
422 | The image_url you supplied could not be downloaded. The product write itself succeeded, and the response carries the saved product in data next to the error. Check that the URL is public and reachable. |
Treat message as the source of truth for exactly what happened, and always check it alongside code.
Do OAuth endpoints use the same envelope
Section titled “Do OAuth endpoints use the same envelope”No. POST /oauth/token answers in the standard OAuth shape, {"error": "invalid_grant", "error_description": "..."}, because OAuth clients expect it. See authentication. Every other call returns the envelope above.
Where to go next
Section titled “Where to go next”See rate limits for what happens after too many requests, or the full API reference for status codes on a specific endpoint.