Rate limits
Every request made with an install token passes two per-minute counters: one for your install, then one for the store. Writes also need an Idempotency-Key header so a retry never runs twice.
Per-install bucket
Each install of your app gets its own budget of 120 requests per minute. It is checked first, so an app that loops on one store hits its own limit before it can use up the merchant's store budget.
The counter is a fixed window that resets at the start of every clock minute. Every request counts, including requests that fail. Requests refused with 429 still count too, so retrying in a tight loop does not bring the reset closer.
Store bucket
After the install bucket, the request counts against the store's per-minute budget. That budget is shared by every key and every app on the store, including the merchant's own API keys. App install tokens get the Enterprise budget of 600 requests per minute whatever plan the store is on, unless DZBuild set a different limit for that store.
The gateway at https://api.dzbuild.app also applies a ceiling of 600 requests per minute per store before a request reaches DZBuild's servers. It ignores a different limit that DZBuild set for a store, so such a store is still capped at 600 there.
A few costly endpoints have an extra per-store budget on top of these two:
| Endpoints | Limit per store |
|---|---|
| Product image upload | 10 per minute, 3 at the same time |
| Send to delivery, courier link, test and rate sync | 6 per minute, 2 at the same time |
| Home page section writes | 30 per minute, 5 at the same time |
429 Too Many Requests
When a bucket is full the API answers 429:
{
"error": {
"code": "rate_limited",
"message": "Per-minute API limit exceeded for this app install",
"retry_after": 23
},
"meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }
}
The response also carries a Retry-After header with the same number of seconds. The message tells you which bucket is full: Per-minute API limit exceeded for this app install for yours, Per-minute API limit exceeded for this store for the store's. The gateway's own refusal of the store ceiling reads Per-minute API limit exceeded for this key. Wait retry_after seconds, then send the request again with the same Idempotency-Key.
Too many costly operations running at once answer 429 with the code too_many_concurrent and retry_after of 5 seconds.
402 Payment Required
A 402 means the call cannot go through until the merchant pays for something. Retrying does not help. Show the merchant what to do instead.
| Code | Meaning |
|---|---|
no_credit | The store's WhatsApp wallet is empty (see WhatsApp API). The merchant tops it up in the dashboard. |
quota_exceeded | The store reached a monthly request quota that DZBuild set for it. |
Idempotency-Key
POST, PATCH and DELETE requests must carry an Idempotency-Key header. GET and PUT requests do not need one.
POST /v1/orders HTTP/1.1
Host: api.dzbuild.app
Authorization: Bearer dzpk_live_xxxxxxxx
Idempotency-Key: create-order-7f3a9c21
Content-Type: application/json
The rules, as the API applies them:
- The key is at most 64 characters from
A-Z,a-z,0-9,_,-,:and.. A missing or malformed key answers400with the codebad_request. - A key belongs to one install token. Keys of different installs never collide.
- DZBuild stores the response for 24 hours. Sending the same key again with the same method, path and body returns the stored status and body without running the request again, plus the header
Idempotency-Replay: 1. - Using the same key with a different method, path or body answers
422with the codeidempotency_key_reuse. The query string is not part of the comparison. 4xxanswers are stored too. If a request failed with a4xxand you fix the body, send it with a new key.5xxand429answers are not stored, so a retry with the same key runs the request again.- The response is stored when the first request finishes. Two requests sent at the same moment with the same key can both run, so do not fire parallel retries.
Generate one key per operation, for example from your own job id, and reuse it for every retry of that operation.