Rate limits
How much you can ask for, what a 429 looks like, and how to back off.
The limit is per organization, not per key: creating a second key doesn't buy you a second budget. That's deliberate — the budget belongs to the account, and splitting it by credential would mean the load on our side depends on how many keys somebody happened to create.
| Window | Limit |
|---|---|
| Per minute | 120 requests |
| Per hour | 3,000 requests |
Both are evaluated, and whichever runs out first is the one that stops you. There's also a wide per-IP backstop, high enough that it only catches a single machine flooding us — a partner integrating many organizations from one server won't meet it.
What a 429 looks like
HTTP/1.1 429 Too Many Requests
Retry-After: 24{ "error": { "code": "API_KEY_RATE_LIMITED", "message": "Rate limit exceeded for this API key." } }Retry-After is in seconds and it's the real number — waiting that long is enough. Read it instead of guessing a backoff: a fixed sleep is either slower than it needs to be or not long enough.
async function call(url, init) {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
const wait = Number(res.headers.get("Retry-After") ?? 5);
await new Promise((r) => setTimeout(r, wait * 1000));
}
throw new Error("Still rate limited after 5 attempts");
}Staying under it
- Ask for bigger pages.
limit=100reads four times as much per request as the default 25 — see Pagination. - Poll on a schedule, not in a loop. There are no webhooks yet, so polling is the pattern; the mistake is polling as fast as the code can run rather than as fast as the data changes.
- Handle the 429 rather than avoiding it. A retry that reads
Retry-Afteris more robust than a rate you tuned once and never revisited.
If your integration genuinely needs more than this, write to support@trama.so and tell us the shape of the traffic. These numbers are a starting ceiling calibrated on real usage, not a commercial limit — there's nothing to buy.