API Reference

Complete endpoint reference for Trackser Live

Access: Trackser Live is not publicly accessible. All endpoints require a valid API key issued by Curiosity 175. The API currently serves the Trackser app exclusively. Contact support@curiosity175.co.uk to discuss access.

Base URL & authentication

All endpoints are on:

${BASEURL}(You'll receive this when you get access)

Pass your API key as an X-API-Key header or a ?key= query parameter. All responses include full CORS headers (Access-Control-Allow-Origin: *).

API key scopes

Scope Access level
* Full access — live data, timetables, and admin endpoints
internal Live data access (used by the Trackser app)
timetables Timetable endpoints only
admin Admin and monitoring endpoints

Live data

Live snapshots are pre-built every minute by the Trackser Live workers and served directly from Cloudflare R2 — responses are typically <50ms. The as_of timestamp in every response tells you exactly when the snapshot was last built.

Line IDs

Use these identifiers in endpoint paths:

metropolitan  chiltern  bakerloo  central  circle  district
hammersmith-city  jubilee  northern  piccadilly  victoria  waterloo-city 
GET /live/{lineId}/map/latest.json

Gzip-compressed JSON of all trains in the map area for the line. This is the primary endpoint used by the Trackser app map view. Send Accept-Encoding: gzip — most HTTP clients handle this automatically.

GET /live/{lineId}/map/latest-plain.json

Same data, decompressed. Larger response — use when your client can't handle gzip.

GET /live/{lineId}/map/latest-stats.json

Stats only — no trains array. Useful for monitoring line health without fetching full train data.

GET /live/{lineId}/line/latest.json

Gzip-compressed JSON of all trains on the full line, including trains at terminals and depot approaches that fall outside the map area.

GET /live/{lineId}/line/latest-plain.json

Same, decompressed.

GET /live/{lineId}/line/latest-stats.json

Stats only for the full-line snapshot.

GET /live/all/line/latest.json

Gzip-compressed JSON combining every configured line. Includes a top-level lines summary and a missing_lines array for any lines with no current snapshot.

GET /live/all/line/latest-plain.json

Same, decompressed. Also triggers per-line warmups for any lines with missing snapshots.

Example response — live data

{
  "as_of": "2026-03-22T09:43:00.000Z",
  "status": "ok",
  "sources": {
    "unified": "ok",
    "trackernet": "ok"
  },
  "stats": {
    "buildTimeMs": 1240,
    "trainCount": 38,
    "trkReceived": 42,
    "trkExpected": 42
  },
  "trains": [
    {
      "id": "metropolitan:401",
      "lineId": "metropolitan",
      "trainNumber": "401",
      "vehicleId": "424",
      "tripNo": "3",
      "currentLocation": "At Baker Street Platform 1",
      "direction": "Southbound",
      "towards": "Aldgate",
      "nextTowards": "Uxbridge",
      "stoppingPattern": "S",
      "currentLocationBookedPlatform": "BST1",
      "isMaybeStalled": false,
      "isReformed": false,
      "source": "trackernet"
    }
  ]
}

Train object fields

Field Type Description
id string Unique identifier: {lineId}:{trainNumber}
lineId string Line identifier
trainNumber string Operational train number (not a physical unit ID)
vehicleId string Leading car number — the physical train unit. Present when known.
tripNo string TfL trip number for timetable matching
currentLocation string Human-readable position, e.g. "At Baker Street Platform 1" or "Approaching Knightsbridge"
direction string Inferred direction: "Northbound", "Southbound", etc.
towards string Current destination or next significant stop
nextTowards string Next destination after the current terminus (Met line only)
stoppingPattern string Met line stopping pattern code from working timetable
currentLocationBookedPlatform string Booked platform from timetable when at a station (Met line)
isMaybeStalled boolean true if the train has been at the same location longer than the EWMA threshold
isReformed boolean true if a vehicle ID change was detected at a standstill since last snapshot
source string Primary data source for this record: trackernet or unified

Replay & archive

Historical snapshots are archived for 14 days at full resolution. Journey tracking data is maintained per railway day.

GET /replay/{lineId}/list?day=YYYY-MM-DD[&flavor=map]

Lists all archived snapshot keys for a given day. Returns an array of object keys you pass to /replay/get. Use flavor=map for map-variant snapshots (default is line).

GET /replay/get?objectKey={key}

Fetches and decompresses a specific archived snapshot. The objectKey comes from the list endpoint and has the form archive/{lineId}/trains/map/{YYYY-MM-DD}/{HH-MM-SS}.json.

GET /journey/{lineId}/{railwayDay}

Returns journey tracking data for all trains on the given railway day (YYYY-MM-DD). Includes position history, reformation events, and leading car sightings.

GET /journey/{lineId}/{railwayDay}/trains/{trainNumber}

Returns journey data for a specific train on a given day.

Timetables

Timetable endpoints cover the Metropolitan line working timetable, which is stored in Cloudflare R2 and indexed via KV. The KV schedule maps specific dates to timetable IDs and day directories.

All timetable endpoints require the timetables or * scope.

GET /timetables/{lineId}/{YYYY-MM-DD}

Resolves the schedule for a specific date. Returns the timetable ID, day directory, whether it was set explicitly or auto-detected, and the R2 paths used.

{
  "lineId": "metropolitan",
  "date": "2026-03-22",
  "timetableId": "98-26",
  "dayDirectory": "sun",
  "dayDirectorySource": "auto",
  "r2KeyNorthbound": "timetables/metropolitan/98-26/sun/northbound.json",
  "r2KeySouthbound": "timetables/metropolitan/98-26/sun/southbound.json"
}
GET /timetables/{lineId}/current/{direction}

Fetch today's timetable for a direction (northbound or southbound), auto-detecting the day type from the current railway date.

GET /timetables/{lineId}/current/trains

List all train IDs for today, resolved through the KV schedule.

curl "${BASEURL}/timetables/metropolitan/current/trains?key=YOUR_KEY"

{
  "lineId": "metropolitan",
  "timetableId": "347",
  "dayType": "sun",
  "date": "2026-03-22",
  "trains": ["401", "402", "403"],
  "count": 145
}
GET /timetables/{lineId}/current/trains/{trainId}

Fetch a specific train's full trip from today's timetable.

GET /timetables/{lineId}/{YYYY-MM-DD}/trains

List all train IDs for a specific date, resolved through the KV schedule.

GET /timetables/{lineId}/{YYYY-MM-DD}/trains/{trainId}

Fetch a specific train's trip for a given date.

GET /timetables/{lineId}/{dayType}/trains

List trains using an explicit day type: m-f, sat, or sun. Supports ?date=YYYY-MM-DD to override the KV lookup date.

GET /timetables/{lineId}/{dayType}/trains/{trainId}

Fetch a train's trip for an explicit day type.

GET /timetables/{lineId}/{timetableId}/{dayType}/{direction}

Direct access to a specific timetable version — bypasses the KV lookup entirely. Useful for comparing versions.

GET /timetables/{lineId}/list

List all timetable IDs available in R2 for a line.

PUT /timetables/{lineId}/{YYYY-MM-DD} admin

Set or overwrite the timetable schedule for a date. Body: {"timetableId": "98-26"} or with an explicit day directory: {"timetableId": "31-26", "dayDirectory": "tue"}. Response echoes back the resolved R2 paths.

DELETE /timetables/{lineId}/{YYYY-MM-DD} admin

Remove the schedule entry for a date. The worker reverts to the fallback timetable.

Admin

All admin endpoints require the admin or * scope.

GET /admin/status

Lightweight per-line health snapshot. overall is "degraded" if any line has errors. trackerNet.status can be ok, degraded, failed, or skipped (backoff active).

{
  "overall": "ok",
  "now": "2026-03-22T09:43:00.000Z",
  "lines": [
    {
      "line": "metropolitan",
      "ok": true,
      "status": {
        "status": "ok",
        "trackerNet": {
          "status": "ok",
          "failStreak": 0,
          "expected": 42,
          "received": 42,
          "lastOkAt": 1742637780000
        },
        "errorHistory": []
      }
    }
  ]
}
GET /admin/health

Detailed health report including Durable Object metadata per line.

POST /admin/refresh?[all=1 | line={lineId}]

Trigger a manual build. Use ?all=1 for all lines, or ?line={lineId} for a specific one.

curl -X POST "${BASEURL}/admin/refresh?line=metropolitan" \
  -H "X-API-Key: YOUR_KEY"
GET /admin/api-usage?date=YYYY-MM-DD[&key=keyId]

API usage statistics. Without key, returns a summary for all keys on the date. With key, returns detailed per-endpoint counts.

GET /admin/api-keys

List all API keys and their configuration.

GET /admin/logs/summary?lineId={lineId}&date=YYYY-MM-DD&type={type}

Aggregated log summary for a line and date. Valid types: vehicle-id, cache-logs, invalid, reformations, trackcode, dedup, errors.

GET /admin/logs/entries?lineId={lineId}&date=YYYY-MM-DD&type={type}[&limit=N]

Raw log entries for a line, date, and type.

GET /admin/logs/list?lineId={lineId}[&type={type}]

List available log files for a line.

GET /admin/dedup-list?lineId={lineId}&date=YYYY-MM-DD

List deduplication stat snapshots for a line and date.

GET /admin/dedup-get?objectKey={key}

Retrieve a specific deduplication snapshot.

GET /admin/error-list?lineId={lineId}

List error history snapshots for a line.

GET /admin/error-get?objectKey={key}

Retrieve a specific error snapshot.

Archive management

Endpoints for managing the rolling snapshot archive. Require admin scope.

GET /admin/replay-clean/policy

Show the current effective cleanup policy — retention days, downsampling window, cold storage thresholds.

GET /admin/replay-clean/plan?lineId={lineId}&day=YYYY-MM-DD

Preview what would be cleaned for a line on a given day — returns keys to delete and keys to keep. Safe to call; does not modify anything.

POST /admin/replay-clean/apply

Apply one chunk of cleanup. Body: {"lineId": "metropolitan", "day": "2026-03-01", "dryRun": false}.

POST /admin/replay-clean/auto

Run the automated cleanup sweep within the configured window. Safe to call from a cron trigger.

GET /admin/replay-clean/history

List recent auto-clean run logs.

POST /admin/replay-archive/day

Copy a day's snapshots to cold storage. Body: {"lineId": "metropolitan", "day": "2026-01-15"}.

POST /admin/replay-archive/delete-day

Delete a full day from hot and/or cold storage.

POST /admin/purge

Batch delete archived map snapshots. Supports dryRun mode.

{
  "lineIds": ["metropolitan"],
  "before": "2026-01-01",
  "dryRun": true
}

Debug

GET /debug/config

Resolved per-line configuration — TrackerNet station codes, Unified API URLs, feature flags.

GET /debug/last

Current Durable Object metadata per line — last build time, error counts, TrackerNet state.

GET /timetables/debug

Timetable system debug — binding status, first 10 R2 objects, today's KV value.

HTTP status codes

Code Meaning What to do
200 OK All good. Check as_of for data freshness.
204 No content (CORS preflight) Expected response to OPTIONS requests.
401 Unauthorized Missing or invalid API key. Check the X-API-Key header or ?key= parameter.
404 Not found Invalid line ID or endpoint path.
429 Rate limit exceeded Back off and retry. Contact us if you need higher limits.
503 Service unavailable TfL upstream issue or worker error. Check the status page and retry.