API reference / Requirements
/v1/checkDoes this traveller need a visa for this destination?
- Operation
checkRequirement- Authentication
- API key
The core question, and the one endpoint where a wrong answer strands someone at a boarding gate. Every answer carries the statutory instrument it came from.
The body is a **person and a journey**, not a passport alone. A nationality lookup cannot express a transit exemption or a residence-permit exemption, which is why `transit_airside` and `residence_permit_iso3` exist. Omitting them does not apply those exemptions.
Request
Body
nationality_iso3stringrequiredPassport nationality, ISO 3166-1 alpha-3. **Must be an assigned code** — three uppercase letters is not enough. `XYZ` is a 400, not a verdict: an airline typo that came back as a plausible `eta_required` looked exactly like an answer, which is the worst shape a wrong answer can take here. Territories (`HKG`, `PSE`) are assigned codes and are accepted; they fall through to the destination’s statutory default.
example: SOM
destination_iso3stringrequiredone of: ETHSOMDJIKEN
example: KEN
visa_typestringone of: touristbusinesstransitworkstudentinvestmentmedicaljournalistconferencereligioussportsresidenceentertainmentngoofficial
passport_typestringSeveral exemption schedules key on passport class rather than nationality. Defaults to `ordinary`, which is not exempt anywhere diplomatic is.
one of: ordinarydiplomaticserviceofficial
transit_airsidebooleanTrue when the traveller stays within the transit area and does not clear immigration. An airline knows this from the booking. Omit it and transit exemptions are NOT applied — the engine will not assume an exemption it was not told about.
residence_permit_iso3stringISO3 of a country whose residence or work permit the traveller holds.
as_ofstringThe date the answer is *about* — normally the travel date, not today. A schedule amended between now and then changes the answer, so answering with today’s rules would be answering a different question. Defaults to today.
example: 2026-11-14
Responses
verdictstringrequired`unknown` is a real answer, returned when we hold no verified rule for this traveller. It is never collapsed into a guess — telling someone they need no visa when we are unsure is the most damaging thing this endpoint can do.
one of: evisa_requiredvisa_required_embassyvisa_on_arrivalexempteta_requiredunknown
visa_requiredbooleannullrequiredNull when the verdict is `unknown`.
max_stay_daysintegernullrequirednotesstring[]requiredproductsProduct[]requiredEmpty for an exempt traveller, and empty for a product withdrawn under a valid rule where the traveller is exempt. Products restricted to a nationality are filtered out here.
sourcesSource[]requiredcitationstringrequiredThe statutory instrument behind the verdict.
example: Kenya Citizenship and Immigration (Amendment) Rules, 2025 (s.48, Act No. 12 of 2011)
source_tierstringrequiredHow strong the source is. `secondary` means the rule rests on an aggregation — IATA Timatic, a Wikipedia mirror — rather than a government publication. A partner deciding whether to board someone should know the difference, so it is a field rather than a footnote in our research directory.
one of: statutoryofficialsecondary
matched_rule_idstringrequiredWhich rule decided this. Makes a contested verdict traceable to its source.
example: ken.transit.airside
answered_as_ofstringrequiredThe date this answer is *about*, which is not the date it was given. It reads `as_of` back, so a caller checking a future flight can confirm their date was considered rather than being silently answered with today’s rules.
example: 2026-11-15
effective_fromstringnullrequiredStart of the deciding rule’s validity window. Null when it is always in force.
effective_tostringnullrequiredEnd of the deciding rule’s validity window. Null when it is always in force.
errorobjectrequirederrorobjectrequirederrorobjectrequirederrorobjectrequirederrorobjectrequiredExample
curl -X POST https://api.haavisa.com/v1/check \
-H "Authorization: Bearer $HAAVISA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nationality_iso3": "SOM",
"destination_iso3": "KEN"
}'More in Requirements
Something unclear? The eligibility guide explains the model behind the answers; the errors guide covers the envelope.