# Train Stations API
> Search a database of 69,000+ European railway stations from the Trainline open dataset. Find stations by name and country, look one up by id or UIC code, or find all stations near a coordinate (radius search). Each record includes coordinates, UIC code, timezone and a main-station flag — ideal for travel apps, journey planners, ticketing and mobility tooling.

## Authentication
All requests require your oanor API key in the `x-oanor-key` header. Get one at https://www.oanor.com/developer/keys.

```bash
curl -H "x-oanor-key: oanor_live_…" "https://api.oanor.com/trainstations-api/..."
```

## Pricing
- **Free** (Free) — 2,000 calls/Mo, 2 req/s
- **Starter** ($9/Mo) — 45,000 calls/Mo, 8 req/s
- **Pro** ($22/Mo) — 225,000 calls/Mo, 20 req/s
- **Mega** ($56/Mo) — 900,000 calls/Mo, 45 req/s

## Endpoints

### Stations

#### `GET /v1/nearby` — Stations near a coordinate (radius search)

**Parameters:**
- `lat` (query, required, string) — Latitude (-90..90) Example: `47.378`
- `lon` (query, required, string) — Longitude (-180..180) Example: `8.540`
- `radius_km` (query, optional, string) — Search radius in km (1-500, default 20) Example: `5`
- `main_only` (query, optional, string) — Only main stations (true/false)
- `limit` (query, optional, string) — Max results (1-100, default 20) Example: `20`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/trainstations-api/v1/nearby?lat=47.378&lon=8.540&radius_km=5&limit=20"
```

**Response:**
```json
{
    "data": {
        "count": 20,
        "center": {
            "lat": 47.378,
            "lon": 8.54
        },
        "results": [
            {
                "id": 67344,
                "uic": null,
                "name": "Zuerich HB",
                "country": "CH",
                "latitude": 47.37806,
                "timezone": "Europe/Zurich",
                "longitude": 8.54028,
                "is_airport": false,
                "distance_km": 0.02,
                "main_station": false
            },
            {
                "id": 6245,
                "uic": "8503000",
                "name": "Zürich HB",
                "country": "CH",
                "latitude": 47.37819,
                "timezone": "Europe/Zurich",
                "longitude": 8.5392,
                "is_airport": false,
                "distance_km": 0.06,
                "main_station": true
            },
            {
                "id": 18235,
                "uic": "8503088",
                "name": "Zürich HB SZU",
                "country": "CH",
                "latitude": 47.37819,
                "timezone": "Europe/Zurich",
                "longitude": 8.5392,
                "is_airport": false,
                "distance_km": 0.06,
                "main_station": false
            },
            {
                "id": 22614,
                "uic": "8595460",
                "name": "Zürich HB (Carpark Sihlquai)",
                "country": "CH",
          
…(truncated, see openapi.json for full schema)
```

#### `GET /v1/search` — Search railway stations by name and country

**Parameters:**
- `q` (query, optional, string) — Station name (substring) Example: `Berlin Hbf`
- `country` (query, optional, string) — Filter by ISO-2 country code Example: `DE`
- `main_only` (query, optional, string) — Only main stations (true/false) Example: `true`
- `limit` (query, optional, string) — Results per page (1-100, default 20) Example: `20`
- `offset` (query, optional, string) — Pagination offset Example: `0`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/trainstations-api/v1/search?q=Berlin+Hbf&country=DE&main_only=true&limit=20&offset=0"
```

**Response:**
```json
{
    "data": {
        "count": 1,
        "limit": 20,
        "total": 1,
        "offset": 0,
        "filters": {
            "q": "berlin hbf",
            "country": "DE",
            "main_only": true
        },
        "results": [
            {
                "id": 7630,
                "uic": "8065969",
                "name": "Berlin Hbf",
                "country": "DE",
                "latitude": 52.52559,
                "timezone": "Europe/Berlin",
                "longitude": 13.36955,
                "is_airport": false,
                "main_station": true
            }
        ]
    },
    "meta": {
        "timestamp": "2026-05-31T01:02:51.768Z",
        "request_id": "85c05000-92ca-43c1-bdcb-0ca8de57a83f"
    },
    "status": "ok",
    "message": "Search completed",
    "success": true
}
```

#### `GET /v1/station` — A single station by id or UIC code

**Parameters:**
- `id` (query, optional, string) — Station id Example: `1128`
- `uic` (query, optional, string) — UIC code (alternative to id)

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/trainstations-api/v1/station?id=1128"
```

**Response:**
```json
{
    "data": {
        "id": 1128,
        "uic": "8727102",
        "name": "Paris Gare du Nord",
        "country": "FR",
        "latitude": 48.88018,
        "timezone": "Europe/Paris",
        "longitude": 2.35515,
        "is_airport": false,
        "main_station": false
    },
    "meta": {
        "timestamp": "2026-05-31T01:02:51.840Z",
        "request_id": "e5685bef-29f9-418c-82de-f8aba10f81fa"
    },
    "status": "ok",
    "message": "Station retrieved",
    "success": true
}
```

### Countries

#### `GET /v1/countries` — Countries with station counts

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/trainstations-api/v1/countries"
```

**Response:**
```json
{
    "data": {
        "count": 43,
        "countries": [
            {
                "country": "CH",
                "stations": 22268
            },
            {
                "country": "DE",
                "stations": 13741
            },
            {
                "country": "FR",
                "stations": 6399
            },
            {
                "country": "SE",
                "stations": 5767
            },
            {
                "country": "ES",
                "stations": 5196
            },
            {
                "country": "IT",
                "stations": 5038
            },
            {
                "country": "GB",
                "stations": 2794
            },
            {
                "country": "AT",
                "stations": 1545
            },
            {
                "country": "NO",
                "stations": 856
            },
            {
                "country": "HR",
                "stations": 730
            },
            {
                "country": "BE",
                "stations": 574
            },
            {
                "country": "PL",
                "stations": 530
            },
            {
                "country": "CZ",
                "stations": 503
            },
            {
                "country": "NL",
                "stations": 447
            },
            {
                "country": "DK",
                "stations": 381
            },
            {
      
…(truncated, see openapi.json for full schema)
```

### Meta

#### `GET /v1/meta` — Dataset totals & coverage

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/trainstations-api/v1/meta"
```

**Response:**
```json
{
    "data": {
        "total": 69053,
        "fields": [
            "id",
            "name",
            "country",
            "latitude",
            "longitude",
            "uic",
            "timezone",
            "main_station",
            "is_airport"
        ],
        "source": "Trainline EU stations database",
        "coverage": "Europe (Trainline)",
        "countries": 43,
        "main_stations": 828
    },
    "meta": {
        "timestamp": "2026-05-31T01:02:51.978Z",
        "request_id": "8db76ac7-ec8e-4879-9745-84a29dadf740"
    },
    "status": "ok",
    "message": "Meta retrieved",
    "success": true
}
```


---
Marketplace page: https://www.oanor.com/api/trainstations-api
OpenAPI spec: https://www.oanor.com/api/trainstations-api/openapi.json
