API reference

Every endpoint TransCAPI exposes, with its parameters and response shape. For a runnable, always-current version of this generated from the server itself, see the OpenAPI document and the Swagger UI.

Conventions

Base URLhttps://api.transcapi.com
AuthX-Api-Key header, or api_key query parameter. See authentication.
FormatJSON. All endpoints are GET.
TimestampsISO 8601 with offset, e.g. 2026-08-05T16:41:00+01:00.
CoordinatesWGS84 decimal degrees.
Rate limitsPer key, per day and per minute, by tier. See rate limits.

List endpoints share a pagination envelope: page, limit, results_count and a member array of results. Pass page and limit to page through. Every response carries a request_time.

Errors use a consistent envelope and an HTTP status to match:

{ "error": { "code": "missing_api_key", "message": "Missing API key. ..." } }

See error codes for the full list.


Places

GET /v1/places.json

Search stops, settlements, postcodes, streets and landmarks across Great Britain. Settlements come from NPTG, the national register of cities, towns, villages and suburbs, and postcodes from Ordnance Survey's Code-Point Open. A full postcode matches exactly, and a partial one (S1, SW1A) lists the postcodes it starts. Places sharing a name are ranked by size, so Newport returns the city in South Wales first. Settlements and postcodes come before stops, unless you supply lat/lon, in which case everything is sorted by distance. Streets and landmarks (type street and landmark: schools, universities, hospitals, parks, hills, lakes, beaches) come from Ordnance Survey's Open Names, Great Britain only. Name the town to pick one of many streets with the same name: Broad Street, Sheffield or broad street sheffield. Otherwise the nearest comes first if you supply lat/lon, or the one in the largest town. Apostrophes, full stops and a leading "The" don't matter, and Welsh and Gaelic names match too. House numbers are not searchable. Supply a query, a lat/lon, or a bounding box.

ParameterDefaultDescription
query—Free-text search term.
typeallRepeatable. One of bus_stop, train_station, tram_stop, settlement, postcode, street, landmark, airport. Airport results carry an iata code for /v1/airports/{iata}.json.
lat, lon—Bias and sort results by distance from this point.
min_lat, min_lon, max_lat, max_lon—Bounding box. All four required together.
limit201–100.
page1
{
  "request_time": "2026-08-05T15:40:05Z",
  "query": "Sheffield",
  "page": 1, "limit": 1, "results_count": 1,
  "member": [
    {
      "type": "bus_stop",
      "name": "Airport Access Road/Hurst Lane",
      "description": "Doncaster Sheffield Airport",
      "latitude": 53.484269965,
      "longitude": -1.026033473,
      "atcocode": "370046721"
    }
  ]
}

distance (metres) is included on each result when lat/lon is supplied, and omitted otherwise.


Bus

GET /v1/bus/stops.json

Find bus, tram and rail stops near a point or within a bounding box. Across Great Britain, backed by NaPTAN.

ParameterDefaultDescription
lat, lon—Centre point for a radius search.
radius400Metres from lat/lon.
min_lat, min_lon, max_lat, max_lon—Bounding box instead of a radius.
typeallRepeatable stop type filter.
limit20
page1
{
  "member": [
    {
      "type": "bus_stop",
      "atcocode": "370027633",
      "naptan_code": "37027633",
      "name": "Leopold Street/Orchard Lane",
      "short_name": "Leopold Street",
      "indicator": "27633",
      "street": "Leopold Street",
      "locality": "Sheffield Centre",
      "town": "Sheffield",
      "latitude": 53.381315404,
      "longitude": -1.470926487,
      "distance": 59.8
    }
  ]
}

GET /v1/bus/stop_timetables/{atcocode}.json

Departures for a stop, combining the scheduled timetable with live BODS SIRI-VM vehicle positions.

ParameterDefaultDescription
atcocoderequiredIn the path. NaPTAN ATCO code, e.g. 370023169.
datetimenowISO 8601 anchor for the departure window.
from_offset0Window start, minutes relative to datetime.
to_offset60Window end, minutes.
livefalseMatch live vehicles onto departures.
limit20
{
  "atcocode": "370023169",
  "live_requested": true,
  "live_error": null,
  "departures": [
    {
      "line": "X1",
      "line_name": "X1",
      "operator": "First South Yorkshire",
      "destination": "Maltby",
      "direction": 0,
      "mode": "bus",
      "aimed_departure_time":    "2026-08-05T15:41:00+00:00",
      "expected_departure_time": "2026-08-05T15:41:00+00:00",
      "best_departure_estimate": "2026-08-05T15:41:00+00:00",
      "status": "on_time",
      "source": "siri_vm",
      "dated_vehicle_journey_ref": "VJfde1c8a6f4a5b81dfb398429a6ef7793",
      "live_vehicle": {
        "vehicle_ref": "FSYO-35126",
        "operator_ref": "FSYO",
        "latitude": 53.376426,
        "longitude": -1.471027,
        "bearing": "28",
        "destination_name": "Quilter_Road",
        "recorded_at_time": "2026-08-05T15:39:49+00:00"
      }
    }
  ]
}

Use best_departure_estimate when you want a single time to display: it is the live estimate where one exists and the timetabled time otherwise. source tells you which you got — siri_vm for live, gtfs_scheduled for timetable. live_vehicle is null on departures with no vehicle matched, and live_error is non-null if the live feed itself failed, so a feed outage is distinguishable from a quiet stop.


Rail

GET /v1/rail/stations.json

Find rail stations near a point or within a bounding box. Covers all of Great Britain (~2,600 stations). Stations are keyed by 3-letter CRS code.

ParameterDefaultDescription
lat, lon—Centre point.
radius5000Metres.
min_lat, min_lon, max_lat, max_lon—Bounding box instead of a radius.
limit20
page1
{
  "member": [
    { "crs_code": "SHF", "name": "Sheffield",
      "latitude": 53.3782362148, "longitude": -1.4621101656, "distance": 558.9 }
  ]
}

GET /v1/rail/station_timetables/{crs_code}.json

Departures and arrivals for a station, scheduled from the national timetable and merged with live running from National Rail's Darwin.

ParameterDefaultDescription
crs_coderequiredIn the path, e.g. LDS.
datetimenowISO 8601 anchor for the window.
from_offset0Minutes.
to_offset60Minutes.
limit20
typedeparturesdepartures, arrivals or both.
livetrueMerge live running from Darwin.
{
  "crs_code": "LDS",
  "station": { "crs_code": "LDS", "name": "Leeds",
               "latitude": 53.7954, "longitude": -1.5476 },
  "live_requested": true,
  "live": true,
  "live_error": null,
  "messages": [
    "Trains running in the Exeter St Davids area may be delayed, cancelled or revised. ..."
  ],
  "departures": [
    { "mode": "rail", "line": "TP", "line_name": "TransPennine Express",
      "operator": "TransPennine Express", "trip_id": "T19113",
      "destination": "Newcastle",
      "aimed_departure_time":    "2026-09-28T16:52:00+00:00",
      "expected_departure_time": "2026-09-28T17:00:00+00:00",
      "best_departure_estimate": "2026-09-28T17:00:00+00:00",
      "status": "late", "platform": "15",
      "delay_reason": "This service has been delayed by trespassers on the railway earlier today",
      "cancel_reason": null, "source": "darwin" }
  ]
}

Live running comes from National Rail's Darwin, the railway's own real-time system, and is on by default (live=false turns it off). Each scheduled train is matched to Darwin's board for the station and gains an expected time, a platform, and a status: on_time, late, early, delayed (late, with no estimate yet), or cancelled, with delay_reason or cancel_reason where Darwin gives one. source is darwin for a matched train and gtfs_scheduled for one Darwin did not list, which is a few percent at a busy station. messages carries National Rail's station notices as plain text.

Darwin covers two hours either side of now. A board asked for further out is scheduled only, and live is false. live_error says why if Darwin could not be reached, and the board still comes back, scheduled.


Journey planning

GET /v1/journey.json

Plan a door-to-door journey between two coordinates, with fare estimates and live vehicle positions. Covers Great Britain. See the journey planning docs for the full detail on fares, live data and coverage.

ParameterDefaultDescription
from_lat, from_lonrequiredOrigin.
to_lat, to_lonrequiredDestination.
datetimenowDeparture, or arrival when arrive_by=true.
arrive_byfalse
transit_modestram,railOptional sub-modes. Bus and coach always searched.
modeswalk,bicycleNon-transit alternatives.
include_farestrue
include_livetrue
include_intermediate_stopsfalse
max_walk_distance—Metres. Caps the longest single walking leg.
max_total_walk_distance—Metres. Caps total walking across the journey.
include_stepsfalseTurn-by-turn directions on walking legs.
limit51–20.
{
  "coverage": { "area": "Great Britain",
                "bbox": [49.8, -8.7, 61.0, 2.0] },
  "next_available": false,
  "itineraries": [
    {
      "start_time": "2026-08-05T16:36:36+01:00",
      "end_time":   "2026-08-05T17:09:14+01:00",
      "duration_s": 1958.0,
      "fare": { "amount_gbp": 2.80, "complete": true },
      "legs": [ /* see journey planning docs */ ]
    }
  ],
  "alternatives": { "walk": { "itineraries": [] },
                    "bicycle": { "itineraries": [] } }
}

An origin or destination outside the covered area returns 422 outside_coverage rather than an empty list, so "we don't plan here yet" is distinguishable from "no journeys found".


Disruptions

GET /v1/disruptions.json

Planned works, incidents and line status, merging the national BODS SIRI-SX situation feed with TfL's line status. See the disruptions docs for the response shape and the caveats on matching a situation to a service.

ParameterDefaultDescription
modeallbus, tram, rail, tube, dlr, overground, elizabeth-line.
severityallsevere, minor, information, good, unknown.
atcocode—Only situations naming this stop.
operator, line—Substring match.
lat, lon, radius2000 mMax 50000. Both lat and lon, or neither.
min_lat, min_lon, max_lat, max_lon—Bounding box instead of a radius.
path—Encoded polyline (precision 5). Only situations naming a stop near it, matched on their complete stop list.
path_radius300 mHow far off the path a stop may be. Maximum 5000.
plannedbothtrue for works only, false for incidents only.
active_onlytrueExclude situations outside their validity period.
include_good_servicefalseInclude healthy TfL lines.
limit, page50Maximum 100 per page.

Ordered most disruptive first, then most recently raised. Only situations naming a stop with coordinates can match a geographic query. National Rail incidents are placed by the stations named in their affected routes.


Service

GET /health

Unauthenticated liveness check. Returns {"status": "ok"}.

GET /openapi.json

The OpenAPI 3.0 document for this API, generated from the running server. Unauthenticated.