Errors
This page gathers the errors described across the other pages so you can handle them in one place. The API answers every error with the same JSON envelope; the OAuth endpoints use the RFC 6749 shape instead.
The API error envelope
{
"error": { "code": "forbidden", "message": "Missing scope: orders:write" },
"meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }
}
error.code is stable and meant for your code. error.message is for humans and can change. Quote meta.request_id when you write to DZBuild about a call. Some errors add fields inside error, for example retry_after on a 429.
API status codes
| Status | error.code | Message | Cause and what to do |
|---|---|---|---|
400 | bad_request | varies | The Idempotency-Key header is missing or malformed on a POST, PATCH or DELETE, the body is not valid JSON, or a path id is not numeric. Fix the request; send a new key. |
401 | unauthorized | Missing Authorization header | No Authorization header. |
401 | unauthorized | Unsupported Authorization scheme | The header does not start with Bearer. |
401 | unauthorized | Invalid or revoked API key | The token is wrong, or the merchant uninstalled your app. Treat it as an uninstall unless you know otherwise. |
402 | no_credit | The store's WhatsApp wallet is empty. Nothing was queued or charged. Retrying does not help; the merchant tops up in the dashboard. | |
402 | quota_exceeded | The store reached a monthly request quota DZBuild set for it. Retrying does not help. | |
403 | forbidden | Missing scope: <scope> | The token lacks the scope the endpoint needs. Some writes need the read scope too; see Scopes. |
403 | forbidden | Apps cannot use this endpoint | /v1/keys, /v1/webhooks and /v1/changes are closed to install tokens. |
403 | app_uninstalled | This app is no longer installed on this store | The install is no longer active. Stop using the token and delete the store's data. |
403 | app_suspended | This app has been suspended by DZBuild | DZBuild suspended or rejected the app. Calls work again once the suspension is lifted. |
403 | app_not_approved | This app is in test mode and only runs on its developer's stores | The app has not been approved yet and the store does not belong to you. |
403 | app_plan_required | This app requires the ... plan | The store's plan, or an expired paid plan, is below the app's minimum plan. Tell the merchant which plan is needed. |
403 | addon_not_active | WhatsApp only. The merchant has not turned on the WhatsApp Sender addon. | |
403 | plan_required | Home page sections only. The write would leave more sections than the store's plan allows. error carries plan and cap. | |
404 | not_found | No record with this id on this store. | |
404 | section_not_found | Home page sections only. No section with this id on the store's home page. | |
409 | already_sent | WhatsApp only. This template was already sent for this order. error carries the existing message id and status. | |
409 | write_conflict | Home page sections only. Another write changed the layout first, or the version sent on PUT is not the current one. When error carries sections and version, retry from them; otherwise read the layout again. | |
422 | idempotency_key_reuse | The same Idempotency-Key was sent with a different method, path or body. Use one key per operation. | |
422 | WhatsApp codes | unknown_template, invalid_language, invalid_number, suppressed, template_not_approved, empty_param. Nothing was charged. Fix the cause and call again with a new key. See WhatsApp API. | |
422 | home page section codes | invalid_settings (error.fields lists the refused settings, on PUT those of the first refused section), invalid_section_type, limit_reached, invalid_order, no_changes. Fix the request and call again with a new key. See Home page sections. | |
429 | rate_limited | Per-minute API limit exceeded for this app install | Your install's budget of 120 requests per minute is used up. Wait retry_after seconds (also in the Retry-After header) and resend with the same Idempotency-Key. |
429 | rate_limited | Per-minute API limit exceeded for this store | The store's shared budget is used up. Same handling. |
429 | rate_limited | Per-minute API limit exceeded for this key | The gateway's ceiling of 600 requests per minute per store. Same handling. |
429 | too_many_concurrent | Too many costly operations at once (image uploads, courier calls, home page section writes). retry_after is 5 seconds. | |
500 | send_failed | WhatsApp only. The message could not be queued. Retry later. | |
502 | server_error | Key lookup failed, retry shortly | The gateway could not check the token with DZBuild. Retry after a short wait with the same Idempotency-Key. |
Retry or not
| Answer | Retry | With |
|---|---|---|
429 | Yes, after retry_after seconds | The same Idempotency-Key |
5xx and 502 | Yes, after a short wait | The same Idempotency-Key; these answers are never stored, so the request runs |
400, 401, 403, 404, 422 | No. Fix the cause first | A new Idempotency-Key, because a stored 4xx is replayed for 24 hours |
402 | No. The merchant has to act | |
409 already_sent | No. The message exists | |
409 write_conflict | Yes, from the sections and version in error, or after reading the layout again | A new Idempotency-Key |
OAuth errors
Before DZBuild has matched your client_id and redirect_uri, it shows an error page to the merchant and never redirects. After that, it redirects to your redirect_uri with an error parameter:
error | Cause |
|---|---|
unsupported_response_type | response_type is not code. |
invalid_request | state missing or longer than 1024 characters, code_challenge not 43 base64url characters, or code_challenge_method not S256. |
invalid_scope | A scope not registered on the app, not allowed for apps, or a scope parameter longer than 512 characters. |
access_denied | The merchant clicked Deny. |
The token endpoint answers JSON with error and error_description:
| HTTP | error | Cause |
|---|---|---|
401 | invalid_client | Missing or wrong client_id or client_secret. |
400 | unsupported_grant_type | grant_type is not authorization_code. |
400 | invalid_grant | Unknown, expired or used code, a code issued to another app, a different redirect_uri, a verifier that does not match, or no selected store could be installed. |
500 | server_error | A platform fault. Send the merchant through the authorize step again. |
403 | none, HTML body | The request carried no User-Agent header: dzbuild.com answers a POST without one with a challenge page instead of JSON. Send one, for example my-app/1.0 (+https://example.com). |
A claimed code is spent even when the exchange fails, so start a new authorize request instead of retrying with the same code. The full order of checks and the error pages are on the OAuth page.
Webhook delivery failures
A delivery succeeds when your server answers 2xx within 10 seconds. Any other status, a redirect, a timeout or a connection error counts as a failed attempt. DZBuild tries each delivery up to 5 times with growing waits, then marks it dead. After 10 failed attempts in a row on one install, that endpoint is disabled; press Verify in the developer console to turn it back on. Details and the schedule are on the Webhooks page.
Your own verification should answer 401 when the signature or the timestamp check fails. Because that is a non-2xx answer, DZBuild counts it as a failed attempt and retries; a request that keeps failing verification is not from DZBuild, or your signing secret is out of date.