# Cities & towns (SBX-CITY)

171k cities and towns with population, timezone and coordinates, plus nearest-city search. Turkey's 974 districts and 36k neighbourhood and village postal codes.

Version: v1.0

## Authentication

Send your API key on every request, either as a Bearer token or as the `apikey` query parameter:

```
Authorization: Bearer <YOUR_API_KEY>
https://api.servicebox.io/v1/cities/...?apikey=<YOUR_API_KEY>
```

Get a key: sign up at https://servicebox.io/en/signup and create one on the dashboard. An agent can sign up itself with `POST https://api.servicebox.io/v1/accounts` and `{"email": "...", "apis": ["cities"]}`: the owner of the mailbox approves by email and the agent collects a short-lived key by polling the returned `poll_url`.

## Base URL

`https://api.servicebox.io`

## Endpoints

### GET /v1/cities/cities

**List cities**

Cities and towns with at least 1,000 inhabitants (about 171,000 worldwide), largest first unless `sort=name`. Filter by country, subdivision, a name search (start of a word, case- and accent-insensitive: `kadikoy` finds Kadıköy) and a minimum population. Turkish places carry their Turkish names.

**Credits:** 1 per call

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `country` | query | string | no | ISO 3166-1 alpha-2 code. |
| `subdivision` | query | string | no | Subdivision id, e.g. TR.34. |
| `q` | query | string | no | Name search. |
| `minPopulation` | query | integer | no | Minimum population. |
| `sort` | query | string (`population`, `name`) | no | `population` (default, largest first) or `name`. |
| `limit` | query | integer | no | Items per page, 1–200. |
| `cursor` | query | string | no | The `next_cursor` of the previous page, with the same filters. |

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/cities" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

### GET /v1/cities/cities/nearby

**List cities near a point**

Cities within `radiusKm` of a point, nearest first, each with `distanceKm`. Pages through at most the 500 nearest.

**Credits:** 1 per call

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `lat` | query | number | yes | Latitude (WGS84). |
| `lon` | query | number | yes | Longitude (WGS84). |
| `radiusKm` | query | number | no | Search radius, 0.1–200 km. |
| `minPopulation` | query | integer | no | Minimum population. |
| `limit` | query | integer | no | Items per page, 1–200. |
| `cursor` | query | string | no | The `next_cursor` of the previous page, with the same filters. |

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/cities/nearby?lat=0&lon=0" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

### GET /v1/cities/cities/{id}

**Get a city**

One city by its id.

**Credits:** 1 per call

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string | yes |  |

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/cities/<id>" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

### GET /v1/cities/districts

**List districts**

Second-level administrative divisions: Turkey's 974 districts (ilçe) with their Turkish names, counties and similar elsewhere. Give `subdivision` (the districts of one province) or `country`. Sorted by name.

**Credits:** 1 per call

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `subdivision` | query | string | no | Subdivision id, e.g. TR.34. |
| `country` | query | string | no | ISO 3166-1 alpha-2 code. |
| `q` | query | string | no | Name search. |
| `limit` | query | integer | no | Items per page, 1–200. |
| `cursor` | query | string | no | The `next_cursor` of the previous page, with the same filters. |

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/districts" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

### GET /v1/cities/postal-codes

**List postal codes**

Postal codes with the places they serve: for Turkey, about 36,000 neighbourhoods (mahalle) and villages, each with its district and province. Filter by `code`, `district`, `subdivision` or a name search. `country` is required; available for TR.

**Credits:** 1 per call

**Parameters**

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `country` | query | string | yes | ISO 3166-1 alpha-2 code; TR. |
| `code` | query | string | no | A postal code, e.g. 34710. |
| `district` | query | string | no | District id, e.g. TR.34.7732454. |
| `subdivision` | query | string | no | Subdivision id, e.g. TR.34. |
| `q` | query | string | no | Place name search. |
| `limit` | query | integer | no | Items per page, 1–200. |
| `cursor` | query | string | no | The `next_cursor` of the previous page, with the same filters. |

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/postal-codes?country=<country>" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

### GET /v1/cities/timezones

**List timezones**

Every IANA timezone the cities use, with its city count, sorted by name. Free. Not paged: the whole list in one answer.

**Credits:** free (0 credits per call)

No parameters.

**Example**

```bash
curl "https://api.servicebox.io/v1/cities/timezones" \
  -H "Authorization: Bearer $SBX_API_KEY"
```

## Errors

Errors are RFC 9457 `application/problem+json` bodies with a machine-readable `type`.

- `401` — the key is missing, unknown, expired or revoked.
- `402` — not enough credits: the body carries `credits_required` and `upgrade_url` (https://servicebox.io/en/pricing).
- `403` — the key is not allowed to call this API.
- `429` — rate limited: wait `retry_after` seconds (also sent as the `Retry-After` header); `upgrade_url` points to a larger plan.

## Links

- OpenAPI document: https://api.servicebox.io/v1/cities/openapi.json
- Pricing: https://servicebox.io/en/pricing?api=SBX-CITY
- API page: https://servicebox.io/en/apis/cities
