✈
    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 / Getting Started

    Getting Started

    Last verified: 2026-06-20 (Task #389 — Visa Intelligence API docs).

    Every public Visa Intelligence endpoint lives under /v1/visa/ and shares the same authentication scheme, flat error envelope, and rate-limit headers. Once you can call GET /v1/visa/health, everything else is a matter of swapping the path and reading the response.

    Base URL

    EnvironmentURL
    Productionhttps://api.travelmode.ai
    Self-hosted Replit deploymenthttps://your-app-domain.replit.app

    On the api.travelmode.ai host, paths are /v1/visa/.... On a self-hosted deployment domain the same routes are served under /api/v1/visa/....

    Get an API key

    Visa Intelligence is a contracted, customer-facing API. Keys are issued per tenant from the self-serve dashboard at /visa/account (your account must be linked to a tenant first — see the onboarding guide). The plaintext key is shown exactly once — store it somewhere safe.

    A key looks like:

    vsk_live_abc123def456ghi789...
    

    See authentication.md for the scope model, the two ways to send the key, and the customer-vs-key distinction.

    Your first request

    GET /v1/visa/health needs the visa:health scope and confirms your key works:

    curl -s "https://api.travelmode.ai/v1/visa/health" \
      -H "X-Visa-Intel-Key: vsk_live_..."
    
    {
      "status": "ok",
      "module": "visa-intel",
      "version": "1.0.0",
      "apiVersion": "v1",
      "checks": {
        "database": { "status": "ok" },
        "sources": { "total": 312, "active": 280, "archived": 32 }
      },
      "generatedAt": "2026-06-20T12:00:00.000Z"
    }
    

    You can also send the key as a bearer token — pick whichever fits your existing HTTP plumbing:

    curl -s "https://api.travelmode.ai/v1/visa/health" \
      -H "Authorization: Bearer vsk_live_..."
    

    Your first visa check

    The headline endpoint resolves visa requirements for a traveler and destination. It needs the visa:check scope:

    curl -s -X POST "https://api.travelmode.ai/v1/visa/check" \
      -H "X-Visa-Intel-Key: vsk_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "nationalityCode": "US",
        "destinationCountryCode": "FR",
        "purpose": "tourism",
        "arrivalDate": "2026-07-01",
        "departureDate": "2026-07-12"
      }'
    
    {
      "status": "ok",
      "result": {
        "requirement_type": "visa_free",
        "summary": "US passport holders can enter France visa-free for stays up to 90 days in any 180-day period.",
        "required_actions": [],
        "documents": [
          { "name": "Passport", "description": "Valid for at least 3 months beyond departure.", "required": true }
        ],
        "warnings": [],
        "confidence": { "level": "high", "reason": "Backed by an official-source-verified rule." },
        "sources": [
          {
            "id": 42,
            "authority_name": "France-Visas",
            "url": "https://france-visas.gouv.fr/",
            "source_type": "government",
            "last_checked_at": "2026-06-18T09:00:00.000Z",
            "excerpt": "Short-stay (Schengen) visa is not required for US nationals."
          }
        ],
        "manual_review_required": false,
        "max_stay_days": 90
      },
      "meta": { "apiVersion": "v1", "moduleVersion": "1.0.0", "generatedAt": "2026-06-20T12:00:00.000Z" }
    }
    

    The same call in JavaScript (fetch):

    const res = await fetch("https://api.travelmode.ai/v1/visa/check", {
      method: "POST",
      headers: {
        "X-Visa-Intel-Key": process.env.VISA_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        nationalityCode: "US",
        destinationCountryCode: "FR",
        purpose: "tourism",
      }),
    });
    if (!res.ok) throw new Error(`visa check failed: ${res.status}`);
    const { result } = await res.json();
    console.log(result.requirement_type); // "visa_free"
    

    Where next

    • The full per-endpoint contract is the interactive API reference (and the raw openapi.yaml).
    • Scopes and the customer-vs-key model are in authentication.md.
    • Per-key quota and headers are in rate-limits.md.
    • Polling changes or subscribing with webhooks is in changes-webhooks.md.
    • Every error code is in errors.md.
    Next
    Authentication & Scopes →