Skip to content
Alpha — Headcode is currently in alpha. APIs and data may change without notice.

Reference data

Services and station boards return short codes for operators and delay/cancellation reasons. The Operators and Reason Codes APIs let you resolve these codes to names and descriptions your users can understand.

The toc_code field on services and board entries is a two-character code identifying the Train Operating Company running the service — for example GR for LNER.

GET /v1/operators

Returns an array of all known operators:

[
{ "code": "GR", "name": "LNER" },
{ "code": "VT", "name": "Avanti West Coast" }
]
GET /v1/operators/{code}

Returns the operator matching the two-character code. Returns 404 with error code HEADCODE.OPERATORS.NOT_FOUND if the code is unknown.

When a service is delayed or cancelled, the response may include a late_reason or cancel_reason object with a numeric code field. The Reason Codes API resolves these to descriptions.

GET /v1/reference/reason-codes

Returns an array of all known reason codes:

[
{ "code": 100, "description": "This train has been delayed by a broken rail" },
{ "code": 101, "description": "This train has been delayed by a landslip" }
]

A typical workflow is to fetch a service, spot a reason code, and resolve it:

1. Fetch the service

GET /v1/services/202605141A45

The response includes:

{
"toc_code": "GR",
"late_reason": { "code": 100 }
}

2. Resolve the operator

GET /v1/operators/GR
{ "code": "GR", "name": "LNER" }

3. Resolve the reason code

Look up code 100 in the reason codes list (fetched from GET /v1/reference/reason-codes):

{ "code": 100, "description": "This train has been delayed by a broken rail" }

You can now display: “LNER service 1A45 is delayed — broken rail.”

Both operator and reason code datasets change infrequently. Cache the full lists on startup or with a long TTL, then resolve codes locally rather than making a request for every service.