TypeScript SDK
Types generated from the same OpenAPI document that builds this site, so they cannot drift from the API. Retries, timeouts and typed errors are handled for you.
pnpm add @haavisa/sdkimport { createHaavisa } from '@haavisa/sdk';
const hv = createHaavisa({ apiKey: process.env.HAAVISA_API_KEY! });
const result = await hv.check({
nationality_iso3: 'SOM',
destination_iso3: 'KEN',
transit_airside: true
});
result.verdict; // 'exempt'
result.citation; // the statutory instrument behind it
result.matched_rule_id; // 'ken.transit.airside'Errors
Every failure throws a HaavisaError. Branch on code, not on the message.
import { HaavisaError } from '@haavisa/sdk';
try {
await hv.applications.create({ product_code: 'KEN_ETA_TOURIST', nationality_iso3: 'SOM', destination_iso3: 'KEN' });
} catch (error) {
if (error instanceof HaavisaError) {
error.code; // 'forbidden' | 'validation_failed' | ...
error.status; // 403
error.requestId; // quote this in a support ticket
error.details; // field-level problems on validation failures
error.isRetryable;
}
}Retries are already right
GETandDELETEretry on429and5xx, honouringRetry-After.- A
POSTretries only if you pass an idempotency key — a retried create could produce two applications. check()is the exception: it retries freely, because it is a query that uses POST to carry a body and has no side effect.
await hv.payments.capture(body, { idempotencyKey: 'order-42' });