Errors
Every error uses the same envelope as a successful response. Read code to
tell them apart: it is "ok" on success and a stable, machine-readable value
on every error.
Error envelope
Section titled “Error envelope”Errors carry a message instead of data:
{ "success": false, "statusCode": 403, "code": "invalid_api_key", "message": "API key is invalid or missing to access to the requested resource"}| Field | Type | Description |
|---|---|---|
success | boolean | false for invalid_api_key, quota_exceeded, and on partner account and travel group errors. true on every other error: don’t rely on it. |
statusCode | integer | Mirrors the HTTP status code. Errors on the country, currency and advisory endpoints come back with 200. |
code | string | "ok" on success, an error code otherwise. Stable: safe to switch on. |
message | string | Human-readable explanation, for logs. Wording may change. |
fields | string array | Only with invalid_fields: the invalid or missing fields. |
Handling errors
Section titled “Handling errors”Branch on code. Neither success nor the HTTP status flags every error:
plan_restricted comes back with success: true, and a malformed parameter on
/advisory/{code} comes back with HTTP 200.
const body = await res.json();if (body.code !== 'ok') { // body.code is stable; body.message is for humans and logs throw new Error(`${body.code}: ${body.message}`);}Never parse message. Treat an unknown code like a generic failure and log
it.
Error catalogue
Section titled “Error catalogue”Any endpoint
Section titled “Any endpoint”Checked before the endpoint runs, in this order.
| Status | code | success | Meaning | What to do |
|---|---|---|---|---|
403 | invalid_api_key | false | Token missing or invalid, or the path isn’t a public endpoint (a typo in the URL ends up here too). | Check the Authorization: Bearer header and the path. See Authentication. |
403 | plan_restricted | true | Your key only covers some destinations (a trial key covers India) and this request targets another one. The message lists the destinations your key covers. Not counted towards your quota. | Stay within the listed destinations, or ask for a wider key. |
429 | quota_exceeded | false | Monthly quota used up. | Wait for the reset in RateLimit-Reset. See Rate limits. |
500 | internal_server_error | true or false | Unexpected failure on our side. | Retry later with backoff. If it persists, contact us with the request URL and time. |
Visa requirements: GET /requirements
Section titled “Visa requirements: GET /requirements”The deprecated alias GET /partner/{partner_name}/requirements returns the same
codes.
| Status | code | Meaning |
|---|---|---|
400 | invalid_parameters | nationality or destination missing, or not a 2 or 3-letter code. |
403 | user_is_unauthorized | Legacy path only: partner_name doesn’t match your partner account. |
403 | countries_restrictions | No destination is enabled on your account. Contact us. |
403 | country_restriction | This destination isn’t enabled on your account. |
404 | user_not_found | The token isn’t linked to a partner account. Contact us. |
404 | country_not_found | nationality or destination doesn’t match any country. |
404 | no_requirements_found | No requirement on record for this nationality and destination. |
Countries, currencies and advisories
Section titled “Countries, currencies and advisories”These errors come back with HTTP 200.
| Endpoint | code | Meaning |
|---|---|---|
GET /country/{code} | invalid_id | No code in the path. |
GET /country/{code} | invalid_parameter_format | code is neither a numeric ID nor a 2 or 3-letter country code. |
GET /country/{code} | no_country_found | No country matches code. |
GET /currency/{code} | invalid_parameter | No code in the path. |
GET /currency/{code} | invalid_parameter_format | code is neither a numeric ID nor a 3-letter ISO 4217 code. |
GET /currency/{code} | no_currency_found | No currency matches code. |
GET /advisory/{code} | invalid_parameters | Malformed code, source or min_level. |
GET /advisory/{code} | no_country_found | No country matches code. |
GET /countries and GET /currencies have no endpoint-specific errors.
Travel formalities
Section titled “Travel formalities”These errors come back with HTTP 400.
| Endpoint | code | Meaning |
|---|---|---|
GET /vaccines | invalid_parameters | country_code missing, or not a 2 or 3-letter code. |
GET /vaccines | no_country_found | No country matches country_code. |
GET /customs | invalid_parameters | country_code missing, or not a 2 or 3-letter code. |
GET /customs | no_country_found | No country matches country_code. |
GET /representations | invalid_parameters | Neither host_country_code nor represented_country_code given, a malformed country code, or an unknown type. The message says which. |
GET /representations | no_country_found | The host or represented country doesn’t match any country. |
Partner accounts: POST /partners and POST /partners/link
Section titled “Partner accounts: POST /partners and POST /partners/link”For approved integrators. Errors use real HTTP
statuses, and success is false on all of them.
| Status | code | Route | Meaning |
|---|---|---|---|
400 | invalid_fields | Both | The fields array lists the invalid or missing fields. |
400 | invalid_json | /partners | The body isn’t a JSON object. |
400 | invalid_code | /partners/link | The connection key is unknown, already used or for another platform. |
400 | code_expired | /partners/link | The connection key expired. Ask the agency for a new one. |
403 | integrator_not_allowed | Both | The platform’s access isn’t active. Contact us. |
409 | email_already_registered | /partners | admin.email already has a Visamundi account. |
409 | external_agency_id_taken | Both | This identifier can’t be used. Pick another one. |
409 | key_not_recoverable | /partners | The account exists but its API key can’t be issued again. Contact us. |
409 | already_connected | /partners/link | This agency is already connected to your platform. |
429 | rate_limited | /partners | Over 30 accounts created in the last hour. |
502 | provisioning_failed | /partners | The account couldn’t be created. Retry. |
502 | link_failed | /partners/link | The agency couldn’t be connected. Retry. |
503 | service_unavailable | Both | Temporarily unavailable. Retry later. |
Find visas: GET /visas and GET /visa/{id}
Section titled “Find visas: GET /visas and GET /visa/{id}”For approved integrators. success is true on all
of these errors.
| Status | code | Route | Meaning |
|---|---|---|---|
200 | missing_query_parameters | /visas | destination is missing. |
200 | invalid_query_parameter_format | /visas | A parameter has the wrong format. |
200 | no_country_found | /visas | destination or nationality doesn’t match any country. |
404 | no_visas_found | /visas | No visa matches. |
200 | invalid_id_format | /visa/{id} | id isn’t a number. |
200 | no_visa_found | /visa/{id} | No published visa has this id. |
Travel groups: POST /partner/{slug}/transaction
Section titled “Travel groups: POST /partner/{slug}/transaction”For approved integrators. success is false,
except on invalid_mode.
| Status | code | Meaning |
|---|---|---|
400 | invalid_fields | The fields array lists the invalid or missing fields. |
400 | invalid_mode | mode must be travel_group with an integrator key. |
403 | integrator_not_allowed | The platform’s access isn’t active. Contact us. |
404 | agency_not_found | No agency has this external_agency_id on your platform. |
409 | partner_not_linked | This agency key isn’t linked to a partner account. Contact us. |
409 | partner_has_no_account | The agency has no active account. Contact us. |
502 | travel_groups_failed | The groups couldn’t be created. Retry. |
503 | service_unavailable | Temporarily unavailable. Retry later. |
Example: lookup error with HTTP 200
Section titled “Example: lookup error with HTTP 200”{ "success": true, "statusCode": 200, "code": "no_currency_found", "message": "No currency found"}The status is 200 and success is true, but code isn’t "ok": this
response is an error.