✈
    TravelmodeDevelopers
    🔎/
    🔑Manage API Keys
    Feature
    🌦️Weather🛂Visa🧩Platform🧭Trips🤖Agent Runs📅Events

    Visa Intelligence API · v1

    📖Overview🧪API Reference (Try It)
    Guides
    🚀Getting Started🔐Authentication & Scopes⏱️Rate Limits🔔Changes & Webhooks⚠️Errors
    ⬇️Download openapi.yaml
    Developers / Visa / Rate Limits

    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:

    HeaderMeaning
    X-RateLimit-LimitYour hourly cap for this key.
    X-RateLimit-RemainingRequests left in the current window (never negative).
    X-RateLimit-ResetUnix-seconds timestamp when the window resets.
    Retry-AfterSeconds 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/check results — 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. See changes-webhooks.md.
    • Read X-RateLimit-Remaining and back off proactively before you hit zero.
    Previous
    ← Authentication & Scopes
    Next
    Changes & Webhooks →