Panduan
Rate limit
Setiap API key boleh mengirim 600 request per menit.
Fixed window per key
- Limit dihitung per API key, bukan per tenant atau IP. Beberapa key dalam satu tenant masing-masing punya jatah sendiri.
- Window berupa bucket tetap satu menit yang diselaraskan dengan menit jam (UTC). Penghitung di-reset di awal setiap menit.
- Setiap request yang terautentikasi ikut dihitung, termasuk request yang kemudian ditolak karena scope atau validasi.
Limit
| Pemanggil | Request per menit |
|---|---|
| API key | 600 per key |
| App token | 600 per instalasi |
| Sandbox mode | 60 per key atau instalasi |
Header
| Header | Dikirim pada | Arti |
|---|---|---|
x-ratelimit-limit | setiap response API key | Jumlah request yang diizinkan per menit (600, atau 60 dalam sandbox mode). |
x-ratelimit-remaining | setiap response API key | Sisa request di window saat ini. |
retry-after | hanya 429 | Detik hingga window di-reset. |
429 RATE_LIMITED
Bila melewati limit, API menjawab 429 dengan kode RATE_LIMITED dan tidak menjalankan request. details.retryAfter mengulang nilai header.
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 600
x-ratelimit-remaining: 0
retry-after: 17
content-type: application/problem+json
{
"type": "about:blank",
"title": "RATE_LIMITED",
"status": 429,
"code": "RATE_LIMITED",
"detail": "Too many requests for this API key",
"details": {
"retryAfter": 17
},
"instance": "/v1/orders?limit=200",
"requestId": "6f1c2d3e-4b5a-4c6d-8e7f-90a1b2c3d4e5"
}Retry dan backoff
Tunggu retry-after detik pada 429. Pada 5xx dan error jaringan, ulangi dengan exponential backoff dan jitter. Jangan mengulang response 4xx lain tanpa perubahan; hasilnya akan gagal dengan cara yang sama.
// Retries 429 (honouring retry-after) and 5xx with exponential backoff and jitter.
async function request(url, init = {}, attempts = 5) {
for (let i = 0; ; i++) {
const res = await fetch(url, init);
const retryable = res.status === 429 || res.status >= 500;
if (!retryable || i === attempts - 1) return res;
const retryAfter = Number(res.headers.get('retry-after'));
const backoff = Math.min(30, 2 ** i) * 1000 * (0.5 + Math.random() / 2);
await new Promise((r) => setTimeout(r, retryAfter > 0 ? retryAfter * 1000 : backoff));
}
}Utamakan halaman limit=200 dan webhook daripada loop polling yang rapat; satu webhook menggantikan banyak panggilan list.