# API reference

The base URL is `https://api.onde.earth`. All requests use HTTPS and return JSON. To try a route with no key, use the [live console](/#api) on the landing page.

Each successful response has this form:

```json
{
  "data": [
    {
      "id": "city_39sy1dm2dj",
      "name": "Kyoto"
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

The response example of each route shows its `data`. [Errors](/docs/api#errors) gives the form of an error response. [Keys and origins](/docs/keys) tells which key to use and how to send it. [Usage and limits](/docs/usage-and-limits) gives the units and the rate limits.

## Errors

An error response has the content type `application/problem+json`. The body has `code`, `detail`, and `requestId`.

| Code | Status | Meaning |
| --- | --- | --- |
| `invalid_request` | 400 | A parameter or the body is not valid. The `errors` field lists each parameter that is not valid. |
| `unauthorized` | 401 | The request has no key, the key is not valid, or a secret key is in the URL. |
| `origin_not_allowed` | 403 | The origin of the request is not one of the allowed origins of the public key. |
| `not_found` | 404 | The city ID or the country code does not exist. |
| `city_retired` | 410 | The city ID is retired and has no replacement. |
| `rate_limited` | 429 | The requests are above a limit of requests per second. |
| `quota_exceeded` | 429 | The account is above its monthly limit of units. |
| `internal_error` | 500 | An error occurred on the server. |

## City API

City API gives autocomplete, search, and reverse lookup for cities, with names in multiple languages.

### Cities

While a person types, use [autocomplete](/docs/api#autocompleteCities). Then send the ID of the selected city to [Get a city](/docs/api#getCity). For a full name, such as `Burlington, Vermont`, use [search](/docs/api#searchCities). To refuse a guess, accept only a city with `exact` or `alias` in `match`.

- Autocomplete: `GET /v1/cities/autocomplete`
- Search: `GET /v1/cities/search`
- Reverse lookup: `GET /v1/cities/reverse`
- Batch reverse lookup: `POST /v1/cities/reverse/batch`
- Get a city: `GET /v1/cities/{id}`

#### The city object

Autocomplete, search, reverse lookup, and batch reverse lookup return the city object. [Get a city](/docs/api#getCity) returns the full city object. The full city object adds the fields with the full city label, such as the names in each language.

Fields:

- `id` (string): The city ID. The ID never changes.
- `name` (string): The display name in the requested language.
- `localName` (string or null): The name in the main language of the country, such as München, or null.
- `type` (string): The place type: city, or district for a part of a larger city.
- `parentCityId` (string or null): The ID of the parent city of a district, otherwise null.
- `country` (object): The country of the city.
  - `code` (string): The ISO 3166-1 alpha-2 code.
  - `name` (string): The name in the requested language.
  - `names` (object, full city): The country name in each language, by language code.
- `region` (object or null): The region, which is the first-order division of the country, or null.
  - `id` (string): The value for the `region` parameter of search.
  - `isoCode` (string or null): The ISO 3166-2 code, or null.
  - `name` (string): The name in the requested language.
  - `names` (object, full city): The region name in each language, by language code.
- `coordinates` (object): The position of the city.
  - `latitude` (number): The latitude in degrees.
  - `longitude` (number): The longitude in degrees.
- `population` (integer): The population in the dataset.
- `timeZone` (string): The IANA time zone of the city.
- `isCapital` (boolean): True for a national capital.
- `disputed` (boolean): True if the city is in an area on a published list of disputed areas. The value is not a political position.
- `names` (object, full city): The name in each language, by language code.

```json
{
  "id": "city_39sy1dm2dj",
  "name": "Kyoto",
  "localName": "京都市",
  "type": "city",
  "parentCityId": null,
  "country": {
    "code": "JP",
    "name": "Japan",
    "names": {
      "en": "Japan",
      "de": "Japan",
      "es": "Japón",
      "fr": "Japon",
      "it": "Giappone",
      "nl": "Japan",
      "pt": "Japão",
      "ru": "Япония",
      "ja": "日本",
      "ko": "일본",
      "zh": "日本",
      "ar": "اليابان",
      "hi": "जापान"
    }
  },
  "region": {
    "id": "region_yjwfrtj0fe",
    "isoCode": "JP-26",
    "name": "Kyoto",
    "names": {
      "en": "Kyoto",
      "de": "Präfektur Kyōto",
      "es": "Prefectura de Kioto",
      "fr": "Préfecture de Kyoto",
      "it": "prefettura di Kyoto",
      "nl": "Prefectuur Kioto",
      "pt": "Quioto",
      "ru": "Киото",
      "ja": "京都府",
      "ko": "교토 부",
      "zh": "京都府",
      "ar": "كيوتو",
      "hi": "क्योटो प्रीफेक्चर"
    }
  },
  "coordinates": {
    "latitude": 35.02107,
    "longitude": 135.75385
  },
  "population": 1463723,
  "timeZone": "Asia/Tokyo",
  "isCapital": false,
  "disputed": false,
  "names": {
    "en": "Kyoto",
    "de": "Kyōto",
    "es": "Kioto",
    "fr": "Kyōto",
    "it": "Kyoto",
    "nl": "Kyoto",
    "pt": "Quioto",
    "ru": "Киото",
    "ja": "京都市",
    "ko": "교토 시",
    "zh": "京都",
    "ar": "كيوتو",
    "hi": "क्योटो"
  }
}
```

#### Worldviews

The `worldview` parameter sets the country of cities in disputed areas. The default is `us`.

The worldview changes these values:

- `country` of each city
- the `country` filter
- the [list of countries](/docs/api#listCountries)
- the country after a comma in search
- the country that reverse lookup prefers

If the worldview changes the country of a city, `region` is `null`. `disputed` does not change.

Country codes and names are not a political position.

| Value | Country |
| --- | --- |
| `ar` | Argentina |
| `cn` | China |
| `in` | India |
| `jp` | Japan |
| `ma` | Morocco |
| `rs` | Serbia |
| `ru` | Russia |
| `tr` | Türkiye |
| `us` | United States (default) |

#### Autocomplete

`GET /v1/cities/autocomplete`

Cities that start with the text. This route needs a key.

Parameters:

- `q` (string, query, required): The text to match, up to 100 characters.
- `limit` (integer, query): The number of cities to return. From 1 to 10. Default: 5.
- `country` (string, query): Up to 10 ISO 3166-1 alpha-2 codes, separated by commas.
- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

This route returns a list of [city objects](/docs/api#city-object) with this extra field:

- `match` (string): The type of match between the text and the city: exact, alias, prefix, or fuzzy.

[Errors](/docs/api#errors): 400, 401, 403, 429

Request:

```bash
curl "https://api.onde.earth/v1/cities/autocomplete?q=kyoto" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": [
    {
      "id": "city_39sy1dm2dj",
      "name": "Kyoto",
      "localName": "京都市",
      "type": "city",
      "parentCityId": null,
      "country": {
        "code": "JP",
        "name": "Japan"
      },
      "region": {
        "id": "region_yjwfrtj0fe",
        "isoCode": "JP-26",
        "name": "Kyoto"
      },
      "coordinates": {
        "latitude": 35.02107,
        "longitude": 135.75385
      },
      "population": 1463723,
      "timeZone": "Asia/Tokyo",
      "isCapital": false,
      "disputed": false,
      "match": "exact"
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

#### Search

`GET /v1/cities/search`

Cities that match a full name. This route needs a key.

Parameters:

- `q` (string, query, required): The text to match, up to 100 characters.
- `limit` (integer, query): The number of cities to return. From 1 to 10. Default: 5.
- `country` (string, query): Up to 10 ISO 3166-1 alpha-2 codes, separated by commas.
- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us
- `region` (string, query): A region ID, such as region_yjwfrtj0fe.

This route returns a list of [city objects](/docs/api#city-object) with this extra field:

- `match` (string): The type of match between the text and the city: exact, alias, prefix, or fuzzy.

[Errors](/docs/api#errors): 400, 401, 403, 429

Request:

```bash
curl "https://api.onde.earth/v1/cities/search?q=kyoto" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": [
    {
      "id": "city_39sy1dm2dj",
      "name": "Kyoto",
      "localName": "京都市",
      "type": "city",
      "parentCityId": null,
      "country": {
        "code": "JP",
        "name": "Japan"
      },
      "region": {
        "id": "region_yjwfrtj0fe",
        "isoCode": "JP-26",
        "name": "Kyoto"
      },
      "coordinates": {
        "latitude": 35.02107,
        "longitude": 135.75385
      },
      "population": 1463723,
      "timeZone": "Asia/Tokyo",
      "isCapital": false,
      "disputed": false,
      "match": "exact"
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

#### Reverse lookup

`GET /v1/cities/reverse`

The city at a position, or null. This route needs a key.

Reverse lookup prefers a large city to a small neighbor city. Reverse lookup also prefers a capital or the seat of a region within 6 km of the position. If no city is near the position, `data` is `null`. Near a border, the country can be wrong. `timeZone` is the time zone of the city. This time zone can differ from the time zone at the position.

Parameters:

- `latitude` (number, query, required): The latitude of the position.
- `longitude` (number, query, required): The longitude of the position.
- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

This route returns a [city object](/docs/api#city-object) with this extra field:

- `distanceKm` (number): The distance from the position in kilometers.

[Errors](/docs/api#errors): 400, 401, 403, 429

Request:

```bash
curl "https://api.onde.earth/v1/cities/reverse?latitude=35.02&longitude=135.75" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": {
    "id": "city_39sy1dm2dj",
    "name": "Kyoto",
    "localName": "京都市",
    "type": "city",
    "parentCityId": null,
    "country": {
      "code": "JP",
      "name": "Japan"
    },
    "region": {
      "id": "region_yjwfrtj0fe",
      "isoCode": "JP-26",
      "name": "Kyoto"
    },
    "coordinates": {
      "latitude": 35.02107,
      "longitude": 135.75385
    },
    "population": 1463723,
    "timeZone": "Asia/Tokyo",
    "isCapital": false,
    "disputed": false,
    "distanceKm": 0.37023042894617736
  },
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

#### Batch reverse lookup

`POST /v1/cities/reverse/batch`

The city at each position, or null, in the request order. This route needs a key.

`data` has the [reverse lookup](/docs/api#reverseCity) result for each position, at the index of the position. If no city is near a position, the result is `null`. If one position is not valid, the request fails and returns no results.

Parameters:

- `positions` (array, body, required): The positions. The results have the same order. From 1 to 100 items.
  - `latitude` (number, required): The latitude of the position. From -90 to 90.
  - `longitude` (number, required): The longitude of the position. From -180 to 180.
- `language` (string, body): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, body): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

This route returns a list of [city objects](/docs/api#city-object) with this extra field:

- `distanceKm` (number): The distance from the position in kilometers.

[Errors](/docs/api#errors): 400, 401, 403, 429

Request:

```bash
curl "https://api.onde.earth/v1/cities/reverse/batch" \
  -H "Authorization: Bearer $ONDE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"positions":[{"latitude":35.02,"longitude":135.75}]}'
```

Response 200:

```json
{
  "data": [
    {
      "id": "city_39sy1dm2dj",
      "name": "Kyoto",
      "localName": "京都市",
      "type": "city",
      "parentCityId": null,
      "country": {
        "code": "JP",
        "name": "Japan"
      },
      "region": {
        "id": "region_yjwfrtj0fe",
        "isoCode": "JP-26",
        "name": "Kyoto"
      },
      "coordinates": {
        "latitude": 35.02107,
        "longitude": 135.75385
      },
      "population": 1463723,
      "timeZone": "Asia/Tokyo",
      "isCapital": false,
      "disputed": false,
      "distanceKm": 0.37023042894617736
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

#### Get a city

`GET /v1/cities/{id}`

The city with the ID. This route needs a key.

If the ID is retired and has a replacement, the API returns the replacement city, and `meta.retiredId` is the requested ID. Otherwise, `meta.retiredId` is `null`.

Parameters:

- `id` (string, path, required): The city ID.
- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

This route returns a [full city object](/docs/api#city-object), with all fields.

[Errors](/docs/api#errors): 400, 401, 403, 404, 410, 429

Request:

```bash
curl "https://api.onde.earth/v1/cities/city_39sy1dm2dj" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": {
    "id": "city_39sy1dm2dj",
    "name": "Kyoto",
    "localName": "京都市",
    "type": "city",
    "parentCityId": null,
    "country": {
      "code": "JP",
      "name": "Japan",
      "names": {
        "en": "Japan",
        "de": "Japan",
        "es": "Japón",
        "fr": "Japon",
        "it": "Giappone",
        "nl": "Japan",
        "pt": "Japão",
        "ru": "Япония",
        "ja": "日本",
        "ko": "일본",
        "zh": "日本",
        "ar": "اليابان",
        "hi": "जापान"
      }
    },
    "region": {
      "id": "region_yjwfrtj0fe",
      "isoCode": "JP-26",
      "name": "Kyoto",
      "names": {
        "en": "Kyoto",
        "de": "Präfektur Kyōto",
        "es": "Prefectura de Kioto",
        "fr": "Préfecture de Kyoto",
        "it": "prefettura di Kyoto",
        "nl": "Prefectuur Kioto",
        "pt": "Quioto",
        "ru": "Киото",
        "ja": "京都府",
        "ko": "교토 부",
        "zh": "京都府",
        "ar": "كيوتو",
        "hi": "क्योटो प्रीफेक्चर"
      }
    },
    "coordinates": {
      "latitude": 35.02107,
      "longitude": 135.75385
    },
    "population": 1463723,
    "timeZone": "Asia/Tokyo",
    "isCapital": false,
    "disputed": false,
    "names": {
      "en": "Kyoto",
      "de": "Kyōto",
      "es": "Kioto",
      "fr": "Kyōto",
      "it": "Kyoto",
      "nl": "Kyoto",
      "pt": "Quioto",
      "ru": "Киото",
      "ja": "京都市",
      "ko": "교토 시",
      "zh": "京都",
      "ar": "كيوتو",
      "hi": "क्योटो"
    }
  },
  "meta": {
    "dataset": "2026-11-17",
    "retiredId": null
  }
}
```

### Countries

These routes return the countries and the regions of a country. A region is a first-order division of a country. Use a region ID as the value of the `region` parameter of search.

- List countries: `GET /v1/countries`
- List regions: `GET /v1/countries/{code}/regions`

#### List countries

`GET /v1/countries`

All countries. This route needs a key.

Parameters:

- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

Returns:

- `code` (string): The ISO 3166-1 alpha-2 code.
- `name` (string): The name in the requested language.
- `continentCode` (string): The continent code.

[Errors](/docs/api#errors): 400, 401, 403, 429

Request:

```bash
curl "https://api.onde.earth/v1/countries" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": [
    {
      "code": "AD",
      "name": "Andorra",
      "continentCode": "EU"
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

#### List regions

`GET /v1/countries/{code}/regions`

The regions of a country. This route needs a key.

Parameters:

- `code` (string, path, required): The ISO 3166-1 alpha-2 country code.
- `language` (string, query): The language of the names. Default: en. en, de, es, fr, it, nl, pt, ru, ja, ko, zh, ar, hi
- `worldview` (string, query): The worldview, which sets the country of a city in a disputed area. Default: us. ar, cn, in, jp, ma, rs, ru, tr, us

Returns:

- `id` (string): The value for the `region` parameter of search.
- `isoCode` (string or null): The ISO 3166-2 code, or null.
- `name` (string): The name in the requested language.

[Errors](/docs/api#errors): 400, 401, 403, 404, 429

Request:

```bash
curl "https://api.onde.earth/v1/countries/FR/regions" \
  -H "Authorization: Bearer $ONDE_KEY"
```

Response 200:

```json
{
  "data": [
    {
      "id": "region_84pj8sf7v2",
      "isoCode": "FR-ARA",
      "name": "Auvergne-Rhône-Alpes"
    }
  ],
  "meta": {
    "dataset": "2026-11-17"
  }
}
```

### Meta

This route returns the dataset version that the API serves.

- Get dataset details: `GET /v1/meta`

#### Get dataset details

`GET /v1/meta`

The dataset version. This route needs no key.

Returns:

- `dataset` (string): The dataset version.

Request:

```bash
curl "https://api.onde.earth/v1/meta"
```

Response 200:

```json
{
  "data": {
    "dataset": "2026-11-17"
  },
  "meta": {
    "dataset": "2026-11-17"
  }
}
```
