Partner documentation

Platform API

2 sectionsUpdated 2026-09-14

The Platform API answers one question, for any pair of countries: what does a traveller holding this passport need in order to enter that country? It is the same data the World of Regions site runs on — entry status, accepted documents, passport validity, vaccinations, insurance, proof of funds, rules for minors and the traveller's nearest embassy — served as JSON to your own booking system, agent desktop or website.

It is read-only. There is nothing to write, nothing to reconcile and no state to keep in step: you ask a question when you need the answer, and cache it for as long as suits you.

Base URL
world-of-regions.com/api
Auth
apikey header
Endpoints
5 · GET only
Billed
per 1,000 requests

Authentication

Every request carries an API key in a header. There is no OAuth flow, no token endpoint and nothing to refresh: a key is a long-lived credential you create in the admin panel and keep on your server.

The apikey header

Send the key as apikey. The name apitoken is accepted as an alias for the same header, so an integration written against the older name keeps working — but prefer apikey in new code.

bash
curl -H "apikey: YOUR_KEY" \
  "https://world-of-regions.com/api/External/TravelInformationConfiguration?query=%7B%22language%22%3A%22EN%22%7D"

Keys are created in the admin panel under API Configurator, which is also where you switch API access on for your organisation. A key is shown in full when it is created and can be copied from that screen afterwards; treat it the way you would a password.

Which domains a key may be called from

A key can be restricted to a list of domains — up to five. When that list is set, every request must arrive with an Origin or a Referer naming one of them.

Two details decide whether this control does what you expect:

  • Only Origin and Referer are read. The request's Host header is deliberately ignored, because Host is our hostname rather than the caller's — a request that sent neither of the other two would otherwise match the allow-list simply by omitting a header.
  • A request that carries neither is refused, not waved through, whenever a key has a domain list. A caller with no verifiable origin cannot satisfy the list, and allowing it would make the list decorative.

Read the control for what it is. Origin and Referer are set by browsers and cannot be forged by page JavaScript, so a domain list genuinely stops a third-party site embedding your key in their front end. It is not protection against a stolen key used from a server, which can send any header it likes. A key with no domain list works from anywhere — the right choice for a server-to-server integration, and the wrong one for a key that ships to a browser.

When a request is refused

Status Message What it means
401 Api key is invalid No key, an unknown key, or a domain-restricted key called from a domain that is not on its list.
401 This API key is restricted to specific domains; the request carried no Origin or Referer The key has a domain list and the request gave nothing to match it against.
402 Insufficient balance — top up to continue using the API The organisation's prepaid balance is spent. Top up in the panel and calls resume immediately.
403 API access is disabled for this organisation The key is valid, but API access is switched off for the organisation that owns it.

Every refusal is a JSON object with a single message field. Note that the two 401s are different problems with the same status: read the message before assuming a key is wrong.

Usage is recorded, and appears a few minutes later

Calls are counted per key and flushed every five minutes, so the first requests from a new integration will not appear in the usage report the instant you make them. The count is what your invoice is built from — see Usage and billing.

Endpoints

Five endpoints, all GET, all under https://world-of-regions.com/api/External/. Each one takes its arguments the same way, which is the first thing to get right.

One query envelope, not query parameters

Arguments arrive as a single query parameter holding URL-encoded JSON — not as separate query-string parameters. This is the same envelope every other reader in the service uses.

bash
# The JSON: {"language":"EN","originCountryCode":"PL","destinationCountryCode":"DE"}
curl -H "apikey: YOUR_KEY" \
  "https://world-of-regions.com/api/External/TravelInformation?query=%7B%22language%22%3A%22EN%22%2C%22originCountryCode%22%3A%22PL%22%2C%22destinationCountryCode%22%3A%22DE%22%7D"

In practice you build the JSON and let your HTTP client encode it:

javascript
const query = JSON.stringify({
    language: 'EN',
    originCountryCode: 'PL',
    destinationCountryCode: 'DE',
})

const response = await fetch(
    `https://world-of-regions.com/api/External/TravelInformation?query=${encodeURIComponent(query)}`,
    {headers: {apikey: process.env.WOR_API_KEY}},
)

A request whose query is missing, is not valid JSON, or omits a required field is answered with a malformed-query message rather than an empty result. Unknown fields in the envelope are ignored, so sending one object shape to several endpoints is fine.

The five endpoints

Endpoint Required fields Answers
TravelInformation language, originCountryCode, destinationCountryCode The entry requirements for one country pair.
TravelBriefing language, originCountryCode, destinationCountryCode The same answer under visaData, plus the identity of both countries — so a trip header renders without a second call.
TravelInformationCountryList language The countries you may ask about, grouped by continent, with the nationalities that have answers.
TravelInformationConfiguration language The field configuration behind the answer: which fields exist, and the options each one can take.
TravelInformationTranslatedList language (countryId narrows it) Every visa record for a nationality, translated.

The call you will make most

TravelInformation is the one nearly every integration is built on: one passport, one destination, one answer.

GET/External/TravelInformationRequires an API key
FieldTypeDescription
languagestringRequiredLanguage of the labels and translated names in the answer. It does not change which pairs exist.
originCountryCodestringRequiredThe traveller's passport. Use an objectId from TravelInformationCountryList.
destinationCountryCodestringRequiredWhere they are going, addressed the same way.

Country codes and languages

Take country codes from TravelInformationCountryList rather than assuming a standard. Each entry carries an objectId, and that value is what originCountryCode, destinationCountryCode and countryId expect. The same response tells you which nationalities are answerable at all — availableNationalities — so a picker built from it can never offer a pair with no answer behind it.

language selects the language of the labels and translated names in the response, not which pairs exist.

What an answer looks like

The public travel-requirements page is built from this endpoint, so it doubles as a preview of the data: everything below is one TravelInformation response, laid out.

The Poland to Thailand travel-requirements page, showing a visa-free result with a 60-day maximum stay, accepted entry documents, required passport validity and the government source it was verified against.

json
{
  "isVisaFree": true,
  "entryDocumentType": ["passport", "identityCard"],
  "entryPermissionType": "",
  "permissionValidity": 0,
  "visaRequiredAfterDays": 90,
  "passportValidity": 0,
  "vaccinationsSuggested": [],
  "vaccinationsMandatory": [],
  "insuranceStatus": "suggested",
  "financialGuarantee": ["none"],
  "minorTraveling": ["letterOfParentalConsent"],
  "visaIssuanceLocation": [],
  "informationBasedOnWebsite": "https://...",
  "embassy": {
    "url": "https://...",
    "nearestCountry": {"name": "Germany", "code": "DE"}
  }
}

Two fields are worth reading carefully. informationBasedOnWebsite is the official source the record was written from — quote it, or link it, wherever you show the answer to a traveller. And embassy.nearestCountry may name a country other than the destination: where the destination has no embassy for that nationality, the answer points at the nearest one that does.

Coded values are not display text. entryDocumentType, financialGuarantee, minorTraveling and their neighbours are stable codes; the human labels for them come from TravelInformationConfiguration in the language you asked for. Resolve them through that response rather than deriving a label from the code, and a new option added on our side appears in your UI without a release on yours.

PodglądWorld of Regions jest w fazie rozwoju — hotele, ceny i treści to dane przykładowe.