Rate limits¶
The hosted API enforces two independent limits:
| Limit | Scope | Value |
|---|---|---|
| Requests per minute | per API key | 60 |
| Concurrent requests | per organization | 2 |
When a limit is exceeded the API returns 429 and no engine work runs.
Headers¶
Successful responses (200) on metered endpoints include:
| Header | Meaning |
|---|---|
X-RateLimit-Limit-Requests |
Request limit per minute for this key. |
X-RateLimit-Remaining-Requests |
Requests left in the current window. |
X-RateLimit-Reset-Requests |
Seconds until the window resets. |
A 429 also carries Retry-After (seconds to wait before retrying).
429 responses¶
code |
Limit | Notes |
|---|---|---|
rate_limit_exceeded |
60 requests/minute per key | Retry-After is set. |
concurrency_limit_exceeded |
2 concurrent requests per org | Retry-After: 1; a slot frees when an in-flight request finishes. |
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Melebihi batas 60 request per menit untuk API key ini.",
"param": null,
"request_id": "req_01J…",
"doc_url": "https://docs.trusttyped.com/errors#rate_limit_exceeded"
}
}
Retrying with backoff¶
Always honour Retry-After when it is present; otherwise use exponential
backoff with jitter. Do not retry immediately in a tight loop.
import httpx, random, time
def post_with_retry(url, *, headers, json, attempts=5):
delay = 1.0
for i in range(attempts):
resp = httpx.post(url, headers=headers, json=json, timeout=120)
if resp.status_code != 429:
return resp
retry_after = resp.headers.get("Retry-After")
wait = float(retry_after) if retry_after else delay
time.sleep(wait + random.uniform(0, 0.5))
delay = min(delay * 2, 30)
return resp
async function postWithRetry(url, options, attempts = 5) {
let delay = 1000;
for (let i = 0; i < attempts; i++) {
const resp = await fetch(url, options);
if (resp.status !== 429) return resp;
const ra = Number(resp.headers.get("Retry-After"));
const wait = Number.isFinite(ra) ? ra * 1000 : delay;
await new Promise((r) => setTimeout(r, wait + Math.random() * 500));
delay = Math.min(delay * 2, 30000);
}
throw new Error("rate limited");
}
Concurrency limit = 2 per org
A single organization shares two concurrent engine slots across all its keys. If you need more throughput, spread work over time or contact us about higher limits. Streaming requests also hold a concurrent slot until the stream finishes.