Read Convor rate-limit response headers and implement bounded retries without relying on obsolete plan-wide request tables.
Convor applies shared and route-specific limits to protect tenant data and platform availability. The effective ceiling can vary by route group, endpoint, organization plan, and caller type.
Do not hardcode one plan-wide requests-per-minute table. The response headers for the request you are making are the source of truth.
Rate-limited API routes return:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1785772860000| Header | Meaning |
|---|---|
X-RateLimit-Limit | Effective request ceiling for the current bucket and window. |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | Unix timestamp in milliseconds when the current window resets. |
When a request is rejected with 429 Too Many Requests, the response also
contains:
Retry-After: 12Retry-After is the number of seconds to wait before retrying. Prefer it over a
locally calculated delay.
A rate-limit rejection uses the normal API error envelope:
{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "Too many requests. Please try again later.",
"details": {
"retryAfter": 12
},
"correlationId": "01J..."
}
}The details and correlationId fields are optional. Use the HTTP header as the
retry source even when the body also includes retryAfter.
Use bounded retries, respect Retry-After, and add jitter so many workers do not
retry at the same instant.
function sleep(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
async function convorRequest(url, options, maxRetries = 4) {
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
const response = await fetch(url, options);
if (response.status !== 429 || attempt === maxRetries) {
return response;
}
const retryAfter = Number(response.headers.get("Retry-After"));
const fallbackSeconds = Math.min(30, 2 ** attempt);
const baseDelay = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: fallbackSeconds * 1000;
const jitter = Math.floor(Math.random() * 250);
await sleep(baseDelay + jitter);
}
throw new Error("Unreachable");
}Do not blindly retry mutations
A 429 response means the rejected request was not accepted by the rate-limit
guard, but other network failures can occur after a mutation is processed. For
POST, PUT, PATCH, and DELETE, follow the endpoint's replay guarantees or
verify resource state before retrying.
429 responses.Ostatnia aktualizacja: 3 sie 2026
Czy ta strona była pomocna?