In testing LopoRail is in active testing — some features may be incomplete or change.
Global Rail Platform

LopoRail Public API

Stations, live boards, PPM/performance, and real-time vehicle positions. Versioned, read-only, with API keys and rate limiting.

REST API API Key Auth Rate Limited OpenAPI 3.1 Checking status…
128,500 stations 3,078 with CRS 144 countries 6 live feeds

Quickstart

1

Get an API Key

Sign up for a LopoRail account and generate an API key from your API Keys dashboard.

# Your key looks like:
lra_abcdefghijklmnopqrstuvwxyz123456
2

Make Your First Request

Send your key in the Authorization header:

curl -H "Authorization: Bearer lra_abcdefghijklmnopqrstuvwxyz123456" \
  "https://loporail.com/wp-json/loporail/v1/stations?search=kings+cross&limit=5"
const res = await fetch('https://loporail.com/wp-json/loporail/v1/stations?search=kings+cross&limit=5', {
  headers: { Authorization: 'Bearer lra_abcdefghijklmnopqrstuvwxyz123456' },
});
const data = await res.json();
console.log(data);
import requests

r = requests.get(
    'https://loporail.com/wp-json/loporail/v1/stations',
    params={'search': 'kings cross', 'limit': 5},
    headers={'Authorization': 'Bearer lra_abcdefghijklmnopqrstuvwxyz123456'},
)
print(r.json())
$res = wp_remote_get( 'https://loporail.com/wp-json/loporail/v1/stations?search=kings+cross&limit=5', array(
    'headers' => array( 'Authorization' => 'Bearer lra_abcdefghijklmnopqrstuvwxyz123456' ),
) );
$data = json_decode( wp_remote_retrieve_body( $res ), true );
require 'net/http'
uri = URI('https://loporail.com/wp-json/loporail/v1/stations?search=kings+cross&limit=5')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer lra_abcdefghijklmnopqrstuvwxyz123456'
puts Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }.body
req, _ := http.NewRequest("GET", "https://loporail.com/wp-json/loporail/v1/stations?search=kings+cross&limit=5", nil)
req.Header.Set("Authorization", "Bearer lra_abcdefghijklmnopqrstuvwxyz123456")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
3

Explore the Data

Try the endpoints below or use the interactive playground to test live calls.

# Search stations
GET /stations?search=edinburgh

# Get station by CRS
GET /stations/KGX

# Live departures board
GET /boards/KGX?type=departures&limit=10

# Performance metrics (PPM)
GET /ppm/ch

# Vehicle positions
GET /positions/us-mbta

Authentication

All API endpoints (except /info and /openapi) require an API key.

Header Authentication (Recommended)

Authorization: Bearer YOUR_API_KEY

Query Parameter (For Testing)

GET /stations?api_key=YOUR_API_KEY
Security: Never expose your API key in client-side code, public repositories, or shared screenshots. Rotate keys regularly from your dashboard.

Rate Limits

API keys have tier-based limits:

Tier Daily Monthly Burst (per minute)
Free 1,000 10,000 60
Developer 10,000 100,000 60
Business 100,000 1,000,000 60
Enterprise 1,000,000 10,000,000 60

The Free tier covers /stations, /boards, /info. Live /ppm and /positions require the Developer tier or higher. Free and Developer keys must show a "Powered by LopoRail" link; Business and Enterprise may white-label. See plans

Rate Limit Headers

Every response includes headers to help you manage your quota:

  • X-RateLimit-Limit-Day — Daily limit
  • X-RateLimit-Remaining-Day — Requests remaining today
  • X-RateLimit-Limit-Month — Monthly limit
  • X-RateLimit-Remaining-Month — Requests remaining this month
  • X-RateLimit-Reset-Day — Unix timestamp when daily limit resets
  • X-RateLimit-Reset-Month — Unix timestamp when monthly limit resets

Exceeding Limits

When you exceed a limit, the API returns 429 Too Many Requests with a Retry-After header indicating seconds until reset.

Endpoints

Stations

  • GET /stations — Search stations
  • GET /stations/{crs} — Station by CRS
  • GET /stations/tocs/{toc} — Stations by operator

Live Boards

  • GET /boards/{crs} — Departures/arrivals

Params: type=departures|arrivals|both, limit, window

Performance (PPM)

  • GET /ppm/{provider} — PPM metrics

Providers: ch, fr, de, us-mbta, dk, etc.

Vehicle Positions

  • GET /positions/{provider} — Live positions

Providers: us-mbta, jp, etc.

Geo

  • GET /geo/nearby — Stations near a point
  • GET /geo/reverse — Nearest place

Meta

  • GET /info — API info (public)
  • GET /status — Service status (public)
  • GET /openapi — OpenAPI spec (public)

Live data demo

A real departures board, rendered server-side from the same feed the API serves. No key needed for this sample.

Time Destination Operator Platform Status
00:01 Cambridge Great Northern 9 On time
00:07 Letchworth Garden City Great Northern — On time
00:31 Cambridge Great Northern — On time
01:07 Royston Great Northern — On time
01:10 Hertford North Great Northern — On time
23:33 Leeds LNER 1 On time

Updated 2026-10-05T22:23:58+00:00. Demo shows one station; get a key for full access.

API Reference

Free and Developer keys must display a "Powered by LopoRail" link on your app; Business and Enterprise may white-label.

GET /stations — Search stations by name or CRS code.
Parameter Description
searchName or CRS to match.
limit1-500 (default 50).
offsetPagination offset.

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/stations"

Example response

{"data":[{"name":"London Kings Cross","crs":"KGX","lat":51.5308,"lon":-0.1238}],"meta":{"count":1,"limit":50,"offset":0}}
GET /stations/{crs} — A single station by CRS code.
Parameter Description
crs3-letter CRS code (path).

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/stations/KGX"

Example response

{"data":{"name":"London Kings Cross","crs":"KGX"}}
GET /boards/{crs} — Live departures/arrivals for a station.
Parameter Description
crs3-letter CRS code (path).
typedepartures | arrivals | both.
limitRows (max 100).
windowMinutes ahead.

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/boards/KGX"

Example response

{"data":{"station":{"id":"KGX","name":"London Kings Cross"},"services":[{"scheduled_time":"13:06","destination":{"name":"Letchworth Garden City"},"platform":"10","status":{"public_text":"On time"}}]}}
GET /ppm/{provider} — PPM/performance metrics. Developer tier or higher.
Parameter Description
providerch, fr, de, dk, us-mbta, ...

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/ppm/ch"

Example response

{"data":{...},"meta":{"provider":"ch","generated_at":"..."}}
GET /positions/{provider} — Live vehicle positions. Developer tier or higher.
Parameter Description
providerus-mbta, jp, ...

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/positions/ch"

Example response

{"data":[{"id":"...","lat":42.3,"lon":-71.1}]}
GET /geo/nearby — Stations within a radius of a point.
Parameter Description
latLatitude (-90..90).
lngLongitude (-180..180).
radiusKm (default 25, max 500).
limitMax results.

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/geo/nearby"

Example response

{"data":[{"name":"King's Cross St Pancras","lat":51.530609,"lon":-0.1239491,"distance_km":0.024}]}
GET /geo/reverse — Nearest station/place to a point (max 50 km).
Parameter Description
latLatitude.
lngLongitude.

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/geo/reverse"

Example response

{"data":{"name":"King's Cross St Pancras","distance_km":0.024}}
GET /info — API metadata + value ladder (public).

Request

curl -H "Authorization: Bearer $LOPORAIL_API_KEY" "https://loporail.com/wp-json/loporail/v1/info"

Example response

{"name":"LopoRail API","version":"0.4.3","tiers":{...}}

Freight Data

Public, read-only freight endpoints under the loporail-freight/v1 namespace. No API key required.

Endpoint Description
GET /operatorsFreight operators
GET /operators/{slug}Operator detail
GET /servicesFreight services
GET /linesFreight lines
GET /wagon-typesWagon types
GET /terminalsTerminals (optional bbox filter)
GET /movementsWagon movements (optional bbox filter)
GET /locationsLocations (tiploc, search, non_passenger)
GET /searchSearch freight data (q)
GET /summaryDataset summary
curl "https://loporail.com/wp-json/loporail-freight/v1/summary"
curl "https://loporail.com/wp-json/loporail-freight/v1/terminals?bbox=-0.5,51.0,0.5,51.8"

Error Codes

Errors are JSON with a machine-readable code, a message, and — for rate limits — a retry_after value.

Status Code Meaning
401missing_api_keyNo API key supplied.
403invalid_api_keyKey is invalid or revoked.
403expired_keyKey has expired.
403key_suspendedKey temporarily suspended by abuse protection.
403tier_requiredEndpoint needs a higher plan tier (/ppm and /positions require Developer+).
404not_foundNo data for the requested resource.
429rate_limit_exceededDaily / monthly / account limit reached; see Retry-After.
429burst_limit_exceededToo many requests per minute; slow down.
429ip_blockedTemporary block after repeated failed authentication.

Status & Coverage

API status

Checking status…

—avg ms (24h) —requests (24h) —success (24h)

Raw status JSON

Data coverage

  • 128,500 stations
  • 3,078 with a CRS code
  • Multiple live feeds (UK NRE, CH, DE, FR, DK, US MBTA, JP)

Live coverage & provider detail

Uptime & Service Level

Our uptime is published, not claimed. These figures are computed from the API audit log and are public — a prospective customer can verify them without an account.

Rolling availability

—uptime (30d) —uptime (90d) —SLO target —error budget left

Rate-limit responses (HTTP 429) are a correct metered outcome and are excluded from the availability calculation. SLA credits are governed by the applicable commercial agreement.

Machine-readable SLA JSON

Per-endpoint availability

EndpointRequestsAvailability

Enterprise entitlements

Built for teams that redistribute rail data to their own users.

CapabilityDeveloperBusinessEnterprise
Live board & station referenceYesYesYes
Real-time positions (PPM)YesYesYes
Redistribution to your own usersAttribution requiredCommercial licenceCommercial licence
White-label (hide LopoRail branding)NoYesYes
Published uptime SLOBest-effort99.9%99.9%+
Machine-readable SLAYesYesYes
Bulk reference dataset exportsNoNoYes — on request

Upstream credits required in all cases: “Data source: Rail Delivery Group (Rail Data Marketplace)” and the Open Government Licence v3.0 notice. Full terms are published with the API Terms of Use.

Changelog

v0.5.7 2026-10-05

  • Runtime protections: per-account limits, anomaly auto-suspension, IP blocking, key expiry, log retention.
  • Public status surface (/status) + graceful degradation.
  • Geo endpoints: /geo/nearby and /geo/reverse.
  • Freight dataset documented; DK (SIRI-ET) exposed via /ppm/dk.

v0.3.0 2026-09-30

  • Paid API tiers + Stripe checkout; value ladder (Free excludes /ppm and /positions).
  • API-key transactional emails + full i18n.

v0.2.0 2026-09-25

  • Public REST surface: /stations, /boards, /ppm, /positions, /info, /openapi.

Interactive Playground

Try live API calls right here. Requires a valid API key.

SDKs & Tools

Versioned starter clients (SDK 0.5.7) — download and go. Machine-readable manifest: sdk manifest.

Terms of Use & Attribution

Draft — pending owner approval: the full API Terms of Use, commercial-use pricing and attribution requirements are awaiting owner sign-off and will be published here before public launch.
  • Read-only: the LopoRail public API is read-only.
  • Data sources: station data © National Rail / Network Rail and respective operators; performance data © Office of Rail and Road / respective operators.
  • Rate limits: respect the documented limits; do not attempt to circumvent them.
  • Caching: cache responses and poll no more often than necessary.

Site Terms of Service | Privacy Policy

ESC
Go to
↑↓ to move ↵ to open Esc to close
Advertise Sponsorship