Visa data
Itinerary decision — answers a trip, not a pair
Post a whole trip — passport, ordered stops with dates, transit stops, passport expiry — and get a per-step decision plus the blockers that only a full itinerary reveals:
- days accumulated across repeat visits to the same country (two 20-day stops in one country are not two independent stays);
- passport validity measured against each arrival date;
- a passport that expires before the last exit.
Every field states its granularity (pair or destination), and every gap comes back as status: "unknown" with a reason — never as a default value. verdict is no_blocker_found or blocked: it reports what the data supports, it is not legal advice.
Known gaps, by design
- Transit: a transit rule exists for 44 of 238 destinations and is recorded per transited country, not per nationality — so even where it exists it never decides whether this passport may transit. The other 158 return status: "unknown". Confirm with the carrier.
- residence and purpose are accepted and echoed back but not modelled: the dataset has no residence dimension and covers short-stay tourism only. Supplying either adds an entry to unknowns.
- Length of stay is computed only where visa_free_days holds a number; where the stay depends on the permit issued, max_stay is unknown rather than a parsed guess.
Billing
One request per distinct country resolved (stops + transit), like /bulk. A 3-country trip costs 3. meta.pairs_charged reports exactly what was billed. Maximum 12 itinerary steps and 12 transit countries per call.
post/api/v1/visa/decision
Request body
Example request
{
"passport": "FRA",
"itinerary": [
{
"country": "FRA",
"from": "2026-09-01",
"to": "2026-09-20"
}
],
"transit": [
"FRA"
],
"passport_expiry": "2027-03-01",
"purpose": "tourism"
}Response
Per-step decision, blockers and unknowns.
Example response
{
"data": {
"passport_country": "FRA",
"steps": [
{
"country": "FRA",
"days": 20,
"regime": {
"value": "visa_free"
},
"max_stay": {
"basis": "visa_free_days"
}
}
],
"transit": [
{
"country": "FRA"
}
],
"passport": {
"per_destination": [
{
"country": "FRA"
}
]
},
"blockers": [
{
"country": "FRA"
}
],
"unknowns": [
{
"field": "transit",
"country": "FRA"
}
]
},
"meta": {
"api_version": "1.0",
"pairs_charged": 3,
"max_steps": 12
}
}