This endpoint shows the performance of trains against the timetable, measured as the percentage of trains arriving at destination on time. The realtime part of the feed is updated every minute however the historical data is updated just after 0200 UK time.

Historical data is available from April 7, 2013.

Please make certain you have read the Conditions of use before using this API.

The current live performance figures

The current live performance figures are available at http://api.area51.onl/rail/1/rtppm and returns a JSON array of objects, one per rail operator. This list is sorted with the highest performance first and the lowest last.

$ curl -s http://api.area51.onl/rail/1/rtppm | jq '.'
[
  {
    "timestamp": "2016-11-22T13:10:00.000Z",
    "operator": {
      "id": 13,
      "operator": "Chiltern",
      "display": "Chiltern",
      "hashtag": ""
    },
    "run": 173,
    "ontime": 172,
    "late": 1,
    "canc": 0,
    "ppm": 99,
    "rolling": 100
  },
  {
    "timestamp": "2016-11-22T13:10:00.000Z",
    "operator": {
      "id": 20,
      "operator": "c2c",
      "display": "C2C",
      "hashtag": ""
    },
    "run": 175,
    "ontime": 170,
    "late": 5,
    "canc": 1,
    "ppm": 97,
    "rolling": 96
  },
  ...
]

Each object returned by this consists of:

timestamp
The ISO time this data is for
operator.id
Our unique id for this operator
operator.operator
Operators name
operator.display
The display name
operator.hashtag
hashtag used by @TrainWatch on Twitter
run
The number of trains run
ontime
The number of trains that arrived on-time
late
The number of trains that arrived late
canc
The number of cancelled trains & the number of trains more than 29 minutes late
ppm
The PPM as an integer percentage
rolling
The Rolling PPM as an integer percentage

Performance for a specific date

You can query the performance for a specific date by adding the date to the url. For example to query the performance for November 1, 2015 you can use:

$ curl -s http://api.area51.onl/rail/1/rtppm/2015-11-01 | jq '.'
[
  {
    "dt": "2015-11-01T00:00:00.000Z",
    "operator": {
      "id": 34,
      "operator": "TfL Rail",
      "display": "TfL Rail",
      "hashtag": null
    },
    "run": 115,
    "ontime": 96,
    "late": 19,
    "canc": 6,
    "ppm": 83,
    "rolling": 100
  },
  ...
]

Performance for an operator on a specific date

You can limit the historical data to a specific operator by appending the operator's id to the url, so for example Southeastern on November 1, 2015 can be retrieved with:

$ curl -s http://api.area51.onl/rail/1/rtppm/2015-11-01/2 | jq '.' {
  "ppm": {
    "dt": "2015-11-01T00:00:00.000Z",
    "operator": {
      "id": 2,
      "operator": "Southeastern",
      "display": "Southeastern",
      "hashtag": "#southeastern"
    },
    "run": 804,
    "ontime": 707,
    "late": 97,
    "canc": 21,
    "ppm": 87,
    "rolling": 73
  },
  "realtime": [],
  "date": [
    {
      "dt_id": "806305",
      "dt": "2015-11-01T00:00:00.000Z",
      "year": 2015,
      "month": 11,
      "day": 1,
      "doy": 305,
      "isoyear": 2015,
      "week": 44,
      "dow": 0,
      "isodow": 7,
      "quarter": 4,
      "month_index": "2015_11"
    }
  ]
}
        

This returns a single JSON object same as above however it also adds two new keys. Date adds some details about the date being queried whilst realtime will (if held) return the realtime data for this date.

The realtime data is the data recorded every minute, however we only keep this for a limited period as it's a lot of data, so if we dont have this data then this is an empty array.

Here's an example with realtime data:

$ curl -s http://api.area51.onl/rail/1/rtppm/2016-11-01/2 | jq '.'
{
  "ppm": {
    "dt": "2016-11-01T00:00:00.000Z",
    "operator": {
      "id": 2,
      "operator": "Southeastern",
      "display": "Southeastern",
      "hashtag": "#southeastern"
    },
    "run": 2013,
    "ontime": 1785,
    "late": 228,
    "canc": 14,
    "ppm": 88,
    "rolling": 89
  },
  "realtime": [
    {
      "time": "2016-11-01T02:08:00.000Z",
      "run": 2,
      "ontime": 2,
      "late": 0,
      "canc": 0,
      "ppm": 100,
      "rolling": -1
    },
    {
      "time": "2016-11-01T02:09:00.000Z",
      "run": 2,
      "ontime": 2,
      "late": 0,
      "canc": 0,
      "ppm": 100,
      "rolling": -1
    },
    {
      "time": "2016-11-01T02:10:00.000Z",
      "run": 2,
      "ontime": 2,
      "late": 0,
      "canc": 0,
      "ppm": 100,
      "rolling": -1
    },
    ...
    {
      "time": "2016-11-02T01:59:00.000Z",
      "run": 2013,
      "ontime": 1785,
      "late": 228,
      "canc": 14,
      "ppm": 88,
      "rolling": 89
    }
  ],
  "date": [
    {
      "dt_id": "806706",
      "dt": "2016-11-01T00:00:00.000Z",
      "year": 2016,
      "month": 11,
      "day": 1,
      "doy": 306,
      "isoyear": 2016,
      "week": 44,
      "dow": 2,
      "isodow": 2,
      "quarter": 4,
      "month_index": "2016_11"
    }
  ]
}

Operators

The operator endpoints returns all operators on the system.

The http://api.area51.onl/rail/1/rtppm/operator end point returns a JSON array of operators, whilst appending the operator id returns the details for a specific operator.

Now an operator can exist more than once in this list. Over time operators change names or loose their franchises and this is reflected by a new entry being created.

For example Greater Anglia has ID's 10 & 40. It changed because Abellio changed their name so our system just thinks it's a new operator.

id
Our unique id for this operator
operator
Operators name
display
The display name
hashtag
hashtag used by @TrainWatch on Twitter

For example to return all operators:

$ curl -s http://api.area51.onl/rail/1/rtppm/operator | jq '.'
[
  {
    "id": 1,
    "operator": "Southern",
    "display": "Southern (defunct)",
    "hashtag": "#southern"
  },
  {
    "id": 2,
    "operator": "Southeastern",
    "display": "Southeastern",
    "hashtag": "#southeastern"
  },
  {
    "id": 3,
    "operator": "London Midland",
    "display": "London Midland",
    "hashtag": ""
  },
  ...
]

An example of retrieving an operator:

$ curl -s http://api.area51.onl/rail/1/rtppm/operator/2 | jq '.' |head -50
{
  "id": 2,
  "operator": "Southeastern",
  "display": "Southeastern",
  "hashtag": "#southeastern"
}