Loading documentation

Access required

Your account doesn't have access to the documentation. Contact your administrator.

Sign out
Skip to main content

Rate limits

Status: stable Category: reference Added: 2026-04-20 Last reviewed: 2026-06-04

Summary​

Rate limits are yours to set. From the developer portal you cap how fast your integration may call the API — across your whole account, a single key, or an individual route — so a runaway loop or a noisy deploy can never burn through more than you intended. Set a number, leave a field blank for no cap, and the API enforces it for you.

When a request would exceed one of your caps it returns 429 RateLimited, and the response tells you exactly which cap you hit and when it clears.

How limits work​

You configure limits in the portal at three levels, and each level takes a value for any of six time windows — per minute, hour, day, week, month, or year:

LevelApplies to
Account-wideEvery key on your account, combined.
Per keyOne key on its own.
Per routeOne endpoint, for a chosen key. A route cap sits on top of that key's caps.

A request is checked against every cap that applies to it, and the tightest one wins. If your key allows 10 requests/minute but you've set a single route to 1/minute, the second call to that route in a minute is limited even though the key still has room. Any window you leave blank simply isn't enforced.

Because you set these values, you always know your limits — there's no hidden number to discover. Adjust them anytime in the portal; changes take effect within about a minute.

When you hit a limit​

The request returns 429 Too Many Requests with headers describing the cap you hit:

HeaderMeaning
Retry-AfterSeconds to wait before retrying.
X-RateLimit-ScopeWhich limit you hit: version (a single key) or consumer (your whole account).
X-RateLimit-WindowThe window that was exceeded: minute, hour, day, week, month, or year.
X-RateLimit-LimitThe cap for that scope and window.
X-RateLimit-RemainingRequests left in the window — 0 on a 429.
X-RateLimit-ResetUnix epoch (seconds) when the window resets.

A real example — a key capped at 10 requests/minute, on the 11th call within the minute:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json; charset=utf-8
Retry-After: 41
X-RateLimit-Scope: version
X-RateLimit-Window: minute
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1780545600

The same shape appears for any cap. A per-route hourly cap reads X-RateLimit-Window: hour with that route's limit; an account-wide cap reads X-RateLimit-Scope: consumer. The headers only appear on a 429.

The 429 body​

The body follows the standard error envelope (see errors.md):

{
"timestamp": "2026-06-04T03:16:44.034Z",
"error": "RateLimited",
"message": "Too many requests",
"request_id": "ce9ea793-1759-4cad-ab1b-fbc11475df3a",
"retry_after": 16
}

retry_after in the body and the Retry-After header always carry the same value. Read either.

When a limit resets​

Windows are aligned to the calendar and reset on their own schedule — the minute window at the top of each minute, the day at 00:00 UTC, the month on the first, and so on. They reset independently: exhausting your hourly cap doesn't touch the daily one, and a minute clearing doesn't help if the hour you're in is still over.

That independence is easy to see in practice. Hammer a key past its per-minute cap and you get 429s until the next minute — then the very next request succeeds:

requests 1–10 -> 200
request 11 -> 429 X-RateLimit-Window: minute Retry-After: 13
... wait for the minute to roll over ...
next request -> 200

You never have to clear anything or contact us — once the window the cap belongs to rolls over, you're through again.

  1. Honor Retry-After. Don't retry before the indicated delay. Retrying early just reconfirms the limit and pushes your recovery out by another window.
  2. Back off on repeated 429s. If a retry after Retry-After is still limited, double your wait and add jitter: wait = Retry-After × 2^attempts + random(0, jitter).
  3. Cap the backoff. Don't grow the wait past a minute — at that point, surface the limit to your caller instead of looping.
  4. Pace bursts. If you have a batch to send, spread it out to stay under the caps you set rather than firing everything at once. If you regularly bump a cap, raise it in the portal.
  5. Don't retry 400, 401, 404, 413, 415, 422. These aren't rate-limit errors; retrying without changing the request wastes calls against your window.

Example retry loop (Python)​

import os
import time
import random
import requests

def call_engine(path: str, body: dict, max_attempts: int = 5) -> dict:
attempt = 0
while True:
attempt += 1
resp = requests.post(
f"https://engine.tripod-health.com{path}",
headers={
"apikey": os.environ["ENGINE_API_KEY"],
"Content-Type": "application/json",
},
json=body,
timeout=30,
)
if resp.status_code != 429:
resp.raise_for_status()
return resp.json()
if attempt >= max_attempts:
resp.raise_for_status() # surface the 429
wait = int(resp.headers.get("Retry-After", "1"))
wait = wait * (2 ** (attempt - 1)) + random.uniform(0, 0.5)
time.sleep(min(wait, 60))

What counts against a limit​

Every authenticated request counts — including 400, 404, and 5xx responses. A 400 ValidationError still consumes the window, so fix validation errors client-side before retrying.

What does not count:

  • Requests rejected with 401 before a key is accepted.
  • The unauthenticated GET /health liveness probe.
  • authentication.md — keys and how to send them.
  • errors.md — full error taxonomy, including RateLimited.
  • credits.md — credit metering and budgets; the contrasting "only successful calls are billed" rule.
  • conventions.md — response-shape rules.

Change history​

DateChange
2026-04-20Initial publication.
2026-06-04Documented configurable account / key / route limits, the six time windows, and the X-RateLimit-* headers.