Rate Limits
Last verified: 2026-06-20 (Task #389 — Visa Intelligence API docs).
Every customer key has a per-key, hourly request quota. The default is 1,000 requests per key per hour; your contract may set a higher cap per key (up to 1,000,000).
How the window works
- The window is a fixed, rolling one-hour bucket counted per key.
- Each authenticated request consumes one unit, regardless of endpoint.
- The master development key is not rate-limited.
Headers
Successful (and rate-limited) responses carry these headers so you can self-throttle without guessing:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your hourly cap for this key. |
X-RateLimit-Remaining | Requests left in the current window (never negative). |
X-RateLimit-Reset | Unix-seconds timestamp when the window resets. |
Retry-After | Seconds to wait — present only on 429 responses. |
curl -i -s "https://api.travelmode.ai/v1/visa/rules?destinationCountryCode=FR" \
-H "X-Visa-Intel-Key: vsk_live_..." | grep -i "x-ratelimit\|retry-after"
x-ratelimit-limit: 1000
x-ratelimit-remaining: 994
x-ratelimit-reset: 1782561600
When you exceed it
You get HTTP 429 with the flat error envelope and a retryAfter value
(also mirrored in the Retry-After header):
{
"error": "Rate limit exceeded",
"code": "visa_api_rate_limited",
"retryAfter": 1800
}
Handling 429 in code
Respect Retry-After rather than retrying immediately:
async function visaGet(path, key) {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(`https://api.travelmode.ai${path}`, {
headers: { "X-Visa-Intel-Key": key },
});
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get("Retry-After")) || 60;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
}
throw new Error("visa API: still rate-limited after retries");
}
Staying under the cap
- Cache
POST /v1/visa/checkresults — rule data changes slowly, so a short TTL (minutes to hours) per(nationality, destination, purpose)pair cuts most traffic. - Prefer webhooks over tight polling of
GET /v1/visa/changes. Seechanges-webhooks.md. - Read
X-RateLimit-Remainingand back off proactively before you hit zero.