# IziVisas API

Visa requirements and country practical info as JSON, in English, French or Spanish.
Human-readable version: https://izivisas.com/en/developers

These are the only public endpoints. Do not call any other path under /api: other routes are internal, undocumented and blocked for third parties.

## Access

Every call needs an API key in the `X-API-Key` header (never in the URL). Keys are issued by hand: https://izivisas.com/en/contact

| Plan | Price | Endpoints | Quota | Conditions |
|------|-------|-----------|-------|------------|
| Free key | 0 | visa-check | 200 responses per rolling 24 h, 50 per hour | Non-commercial use only. A visible, clickable link to https://izivisas.com wherever the data appears. |
| Paid plan | 9 EUR/month or 90 EUR/year | visa-check + country-info | 500 responses per rolling 24 h, 125 per hour | Commercial use allowed. No link required. |

Subscribe to the paid plan (the key is issued, or your existing key upgraded, within 24 hours):

- Monthly: https://buy.stripe.com/bJefZh4hr8NV1CUfQBfYY00
- Yearly: https://buy.stripe.com/14A8wPg095BJ95mdItfYY01

Higher volumes and full catalogue exports are on quote. Both endpoints share the key's quota. Only successful (200) responses count.

Not allowed without a contract: systematically extracting the catalogue (via the API, the website, several keys or several IPs), building a competing database, reselling the raw data. Call the API from your server, never from client-side code where the key would be exposed. Cache responses on your side (verdicts change rarely).

## GET /api/public/visa-check

Short-stay tourist visa verdict for a traveller of one nationality going to one destination.

| Parameter | Required | Description |
|-----------|----------|-------------|
| from | yes | Traveller nationality, ISO 3166-1 alpha-2 (e.g. SN) |
| to | yes | Destination, ISO 3166-1 alpha-2 (e.g. FR) |
| locale | no | fr, en or es. Default: fr |

```bash
curl -H "X-API-Key: $IZIVISAS_API_KEY" \
  "https://izivisas.com/api/public/visa-check?from=SN&to=FR&locale=en"
```

Response:

```json
{
  "from": { "code": "SN", "name": "Senegal" },
  "to": { "code": "FR", "name": "France" },
  "verdict": { "regime": "consular", "color": "red", "duration": "90 days per 180-day period" },
  "visa": {
    "name": "Short-stay (tourism)",
    "price": { "min": 90, "max": 90, "currency": "EUR" },
    "processingTime": "15-45 days",
    "officialUrl": "https://www.france-visas.gouv.fr/en/short-stay-visa"
  },
  "arrivalForm": null,
  "detailsUrl": "https://izivisas.com/en/visas/SN/FR",
  "attribution": "Visa data by IziVisas, https://izivisas.com"
}
```

- `verdict.regime`: visaFree, onArrival, eVisa, consular, notEligible or unknown (most permissive regime for a short tourist stay).
- `verdict.color`: green, yellow, red or null.
- `verdict.duration`: permitted stay, or null.
- `visa`: referenced tourist visa, or null. `price`, `processingTime` and `officialUrl` may be null.
- `arrivalForm`: mandatory online arrival form (e.g. Thailand's TDAC), required even without a visa: `{ name, url, when, free, alsoOnExit }`, or null.
- `detailsUrl`: IziVisas page for the route. `attribution`: ready-to-display text (free keys must show a link).

## GET /api/public/country-info (paid plan only)

What a traveller needs to know on the ground, for one country.

| Parameter | Required | Description |
|-----------|----------|-------------|
| code | yes | Country, ISO 3166-1 alpha-2 (e.g. TH) |
| locale | no | fr, en or es. Default: en |

```bash
curl -H "X-API-Key: $IZIVISAS_API_KEY" \
  "https://izivisas.com/api/public/country-info?code=TH&locale=en"
```

Response (cost lists shortened):

```json
{
  "code": "TH",
  "name": "Thailand",
  "currency": { "code": "THB", "symbol": "฿", "name": "Thai Baht" },
  "timezone": "Asia/Bangkok",
  "callingCode": "+66",
  "drivingSide": "left",
  "electricity": { "plugs": ["Type A", "Type B", "Type C", "Type O"], "voltage": ["220V"], "frequency": ["50Hz"] },
  "emergency": { "fire": "199", "police": "191", "ambulance": "1669" },
  "tapWater": { "status": "unsafe", "label": "Not safe to drink", "note": null },
  "tipping": "Not mandatory, round up or small tip 10%",
  "costs": {
    "city": "in Bangkok",
    "currency": "USD",
    "updatedAt": "2026-10-10",
    "food": [{ "label": "Meal at an inexpensive restaurant", "price": "3" }],
    "transport": [{ "label": "Public transport, one way", "price": "1" }],
    "housing": [],
    "health": [],
    "leisure": [],
    "other": []
  },
  "detailsUrl": "https://izivisas.com/en/countries/TH"
}
```

- `tapWater.status`: safe, unsafe, varies (depends on city or region) or unknown. `label` is the status in the requested language, `note` an extra detail or null.
- `costs`: prices in USD collected in the main city, by category (food, transport, housing, health, leisure, other). A range reads "350-600". null when there is no data.
- `emergency`: police, ambulance, fire (sometimes general). `drivingSide`: left, right or null.

## Errors

| Code | Meaning |
|------|---------|
| 400 | Invalid country code (two ISO letters expected) |
| 401 | Key missing, unknown or revoked |
| 403 | country-info called with a free key |
| 404 | Country code unknown |
| 429 | Quota used up for the last 24 hours or the last hour; retry after the Retry-After header |
| 500 | Internal error |

Errors are JSON: `{ "error": "..." }`.

Data is for guidance: travellers should always check official sources before travelling.
