Lift and Escalator API: Difference between revisions

From Open Rail Data Wiki
m Update link
EvelynSnow (talk | contribs)
Past tense on introductory section
 
(13 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Network Rail's '''[https://portal.nr-lift-and-escalator.net/ Lift and Escalator API]''' contains details of the status of lifts and escalators at many locations in Great Britain. The [https://docs.google.com/document/d/e/2PACX-1vQEcL1yJLUVd8IAKGHi0s2cRsbKuedxuT2YT7b1TNnmjUi07_U15feiVWNlTGEzva7xoTiMrt4AcmE3/pub supplied documentation] is sparse and difficult to follow, and so [https://twitter.com/poggs/ Peter Hicks] of [https://twitter.com/opentraintimes OpenTrainTimes] has written this document for the community to help usage of the API.
Network Rail's '''[https://portal.nr-lift-and-escalator.net/ Lift and Escalator API]''' was an API developed for Network Rail in 2020 by rail technology consultancy Hack Partners Ltd (now a rail AI software company, trading as CrossTech), nominally offering the real-time status of lifts and escalators at many locations across the rail network in Great Britain. The official documentation was quite sparse, hence this article was created by Peter in order to document the API unofficially.


= Signing up =
'''This API was decommissioned on the 31<sup>st</sup> of January 2024, and replaced with [[Stations_Experience_API|a new API]].'''


The developer preview does not require you to [https://nr-lift-and-escalator.developer.azure-api.net/signup sign up], however it is probably worth your while to show how many people are using the API.
== Transition ==
Transition to a [[Stations_Experience_API|new API]] began on the 17<sup>th</sup> of January 2024, with the CrossTech-maintained GraphQL and JSON APIs planned to be discontinued entirely on the 31<sup>st</sup>.


= Access =
== Signing up ==
You can register for an account on the Lift and Escalator API [https://portal.nr-lift-and-escalator.net portal]. Once you've verified your email address, navigate to the "products" tab. Click on "Developer" in the list on this page, then create a new subscription with a name of your choosing. Now, navigate to "Profile", you should be able to see your keys.


The developer preview does not require use of an authentication token, even though the [https://nr-lift-and-escalator.developer.azure-api.net/api-details#api=network-rail-lift-and-escalator-api HTTP requests on the API page] return a 401 Unauthorized.
== Access ==
Official documentation claims that V1 GraphQL functionality migrated to V2 doesn't require authentication, but this isn't entirely true. Some location information (e.g. postcode, toc) was broken out into a ''stations'' table, which is inaccessible while unauthenticated. The inclusion of station CRS codes in the assets table may render this table redundant.


= Data elements =
== Data elements (V1) ==


The following data elements are held within the API:
The following data elements are held within the API:
Line 16: Line 19:
|-
|-
!Field
!Field
!v2 equivalent
!Description
!Description
|-
|-
|uprn
|uprn
|prn (asset)
|Unique asset identifier (not a [https://www.ordnancesurvey.co.uk/business-government/tools-support/open-mastermap-programme/open-id-policy UPRN])
|Unique asset identifier (not a [https://www.ordnancesurvey.co.uk/business-government/tools-support/open-mastermap-programme/open-id-policy UPRN])
|-
|-
|sensorId
|sensorId
|sensorId (status or asset tables)
|A four-digit sensor identifier for the Electronic Monitoring Unit (EMU), left-padded with zeroes if required.  
|A four-digit sensor identifier for the Electronic Monitoring Unit (EMU), left-padded with zeroes if required.  
|-
|-
|blockId
|blockId
|blockId (assets)
|An identifier for the location of the asset within a station
|An identifier for the location of the asset within a station
|-
|-
|blockTitle
|blockTitle
|
|The name of the location within the station
|The name of the location within the station
|-
|-
|station
|station
|name (station)
|Name of the station at which this asset is located
|Name of the station at which this asset is located
|-
|-
|location
|location
|location (asset)
|Name of the location within the station at which this asset is located
|Name of the location within the station at which this asset is located
|-
|-
|lat
|lat
|lat (station)
|Latitude in (WGS84)
|Latitude in (WGS84)
|-
|-
|long
|long
|long (station)
|Longitude (WGS84)
|Longitude (WGS84)
|-
|-
|postcode
|postcode
|postcode (station)
|Postcode of the station in which this asset is located
|Postcode of the station in which this asset is located
|-
|-
|route
|route
|route (station)
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Route] in which this asset is located
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Route] in which this asset is located
|-
|-
|territory
|territory
|region (station)
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Region] in which this asset is located
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Region] in which this asset is located
|-
|-
|toc
|toc
|toc (station)
|Set to 'Managed Stations' for Network Rail Managed Stations, otherwise the name of the train operator
|Set to 'Managed Stations' for Network Rail Managed Stations, otherwise the name of the train operator
|-
|-
|branch
|branch
|Unknown, but possibly the branch of the lift or escalator maintainer's organisation where
|
|Unknown, but possibly the branch of the lift or escalator maintainer's organisation
|-
|-
|type
|type
|type (asset)
|Type of asset, e.g. Lift or Escalator
|Type of asset, e.g. Lift or Escalator
|-
|-
|status
|status
|status (status)
|Current status of the asset
|Current status of the asset
|-
|-
|isolated
|isolated
|isolated (status)
|Indicates whether the asset is powered down or disconnected
|Indicates whether the asset is powered down or disconnected
|-
|-
|engineerOnSite
|engineerOnSite
|engineerOnSite (status)
|Indicates if an engineer has logged in to the sensor and is servicing the asset
|Indicates if an engineer has logged in to the sensor and is servicing the asset
|-
|-
|independant
|independant
|(note the misspelling) Indicates if the lift is on [https://en.wikipedia.org/wiki/Elevator#Independent_service Independent Service] by use of a car preference key
|independent (status)
|('''note the misspelling''' - independ'''ant''' in v1, independ'''ent''' in v2) Indicates if the lift is on [https://en.wikipedia.org/wiki/Elevator#Independent_service Independent Service] by use of a car preference key
|-
|-
|updatedTime
|updatedTime
|
|Date and time when the status was last updated
|Date and time when the status was last updated
|}
|}


= Making a request =
== Tables (V2) ==
=== Asset ===
{| class="wikitable"
|-
!Field
!Official description
!Description
|-
|id
|Unique asset identifier
|Unique identifier (of asset?)
|-
|prn
|Asset property reference number
|Unique asset identifier, renamed from UPRN. '''This field cannot be used in the query builder.'''
|-
|stationNumber
|Asset number
| '''This field cannot be used in the query builder.'''
|-
|description
|
|e.g. "Colonnade Lift", "Lift 3,Platform 20"
|-
|displayName
|Standardised asset name
|e.g. "Lift to Colonnade ", "Lift, Platform 20"
|-
|sensorId
|Associated sensor
|A sensor identifier for the Electronic Monitoring Unit (EMU), '''no longer zero-padded'''
|-
|blockId
|
|An identifier for the location of the asset within a station
|-
|crs
|Associated station
|CRS code of the station at which this asset is located
|-
|location
|
|Name of the location within the station at which this asset is located (e.g. "Colonnade Lift", "Platform 20")
|-
|type
|Asset type (i.e Lift or Escalator)
|Type of asset, e.g. Lift or Escalator
|-
|inCommission
|
|'''This field cannot be used in the query builder. This field is not officially documented.''' Note that this bears a striking resemblence to the misspelled ''inCommision'' you can see in the query builder.
|-
|publicFacing
|
|'''This field is not officially documented.'''
|-
|status
|''relations not covered''
|(Relation) Current status of the asset
|}
 
=== Status ===
{| class="wikitable"
|-
!Field
!Official description
!Description
|-
|sensorId
|Unique sensor identifier
|ID of sensor
|-
|isolated
|
|Indicates whether the asset is powered down or disconnected
|-
|engineerOnSite
|
|Indicates if an engineer has logged in to the sensor and is servicing the asset
|-
|independent
|
|('''note that this is now not misspelled'''), indicates if the lift is in independent service mode.
|-
|status
|last status received
|Current status of the asset (e.g. "Available", "Unknown", "Not Available")
|-
|<s>lastUpdated</s>
|Time of last update to status
|'''Documented in v2 preview documentation, this field is completely absent'''.
|-
|asset
|''relations not covered''
|(Relation) Asset to which this status relates
|}
 
=== Stations ===
{| class="wikitable"
|-
!Field
!Official description
!Description
|-
|id
|Unique station identifier
|API-specific ID for station
|-
|crs
|Station CRS code
|CRS code of station asset is located at
|-
|name
|
|Name of station
|-
|lat
|
|Latitude in (WGS84)
|-
|long
|
|Longitude (WGS84)
|-
|toc
|Train operating company
|Set to 'Managed Stations' for Network Rail Managed Stations, otherwise the name of the train operator
|-
|region
|
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Region] in which this asset is located
|-
|route
|
|Network Rail [https://www.networkrail.co.uk/running-the-railway/our-regions/ Route] in which this asset is located
|-
|postcode
|
|Postcode of the station in which this asset is located
|-
|address
|
|'''This field cannot be used in the query builder.'''
|-
|contactEmail
|
|'''This field cannot be used in the query builder.'''
|}


All requests are through the [https://nr-lift-and-escalator.azure-api.net/gateway/v1/ API endpoint]. Requests must be made via an HTTP POST call - accessing the endpoint through a web browser will make an HTTP GET request, resulting in the following error:
Note that stations are only available if you've authenticated using your bearer token, this includes using the query builder on the portal. If you are not authenticated, you'll see an error which makes it look like the table simply doesn't exist.
 
== Making a GraphQL request ==
All requests are through the API endpoint (https://nr-lift-and-escalator.azure-api.net/graphql/v2). Requests must be made via an HTTP POST request, navigating to this URL in a web browser will make an HTTP GET request, which will result in the following error:


<code>{"path":"$","error":"resource does not exist","code":"not-found"}</code>
<code>{"path":"$","error":"resource does not exist","code":"not-found"}</code>


The API uses [https://graphql.org/ GraphQL], which allows complex queries to be submitted in an HTTP POST request.  A query is just a JSON data structure with some fields to filter on, and other fields to return.
The API uses [https://graphql.org/ GraphQL], which allows complex queries to be submitted in an HTTP POST request.  A query is just a JSON data structure with some fields to filter on, and other fields to return.
== REST API ==
With V2 came the introduction of a handful of REST endpoints, these are
* <code>https://nr-lift-and-escalator.azure-api.net/api/v2/sensors[?num][&offset]</code> - All statuses, essentially equivalent to a graphQL query for statuses with no joins.
Num and offset aren't documented; they're used for paging, with num defining the limit, and offset defining the offset. Both are nominally optional, but num will default to 50 if unset. Instead of paging through these, there's no upper limit to ''num'', if you set it to 20000, you'll get all statuses at once.
* <code>https://nr-lift-and-escalator.azure-api.net/api/v2/sensors/{id}</code> - Statuses by sensor ID, same columns as graphQL status table
* <code>https://nr-lift-and-escalator.azure-api.net/api/v2/stations/{crs}/assets</code> - Assets marked as being at given station CRS
Note that you need to provide bearer authentication for this, since it's passed through to GraphQL.
* <s><code>https://nr-lift-and-escalator.azure-api.net/api/v2/assets/{id}</code></s> - Get asset information by asset ID (broken)
<code>{"error":"field 'uprn' not found in type: 'assets'","path":"$.selectionSet.assets.selectionSet.uprn","code":"validation-failed"}</code>


== Simple requests ==
== Simple requests ==


=== All assets at a station ===
=== All assets at a station (V1) ===


To return the status of all lifts and escalators at a particular station, such as Edinburgh Waverley:
To return the status of all lifts and escalators at a particular station, such as Edinburgh Waverley:
Line 114: Line 302:
}</pre>
}</pre>


=== All assets at all stations ===
=== All assets at a station (V2) ===
<pre>
query {
    assets(where: {crs: {_eq: "EDB"}}) {
        blockId
        crs
        description
        displayName
        id
        location
        sensorId
        status {
            engineerOnSite
            independent
            isolated
            sensorId
            status
        }
        type
    }
}
</pre>


To return data for all stations, remove the text in brackets after status, remove the statement within the brackets of the example above:
=== All assets at all stations (V2) ===


<pre>query MyQuery {
<pre>query {
  status {
assets {
    blockTitle
blockId
    branch
crs
    engineerOnSite
description
    independant
displayName
    isolated
id
    lat
location
    location
sensorId
    long
status {
    postCode
engineerOnSite
    route
independent
    sensorId
isolated
    station
sensorId
    status
status
    territory
}
    toc
type
    type
}
    updatedTime
    uprn
    blockId
  }
}</pre>
}</pre>


Line 146: Line 351:
It is supposedly possible to make an API request and receive a stream of updates using the <code>@live</code> directive on the GraphQL query, but does not seem to work on this API.
It is supposedly possible to make an API request and receive a stream of updates using the <code>@live</code> directive on the GraphQL query, but does not seem to work on this API.


== Room for improvement ==
== Room for improvement (V1) ==


There is some room for improvement on the API:
There is some room for improvement on the API:
Line 157: Line 362:
* '''Lack of machine-interpretable data''' - sensor 5006 is described as 'Wolverhampton Stn Lift/Escalator 05', in location 'Passenger Lift Platform 4', whereas sensor 8127, 'Imperial Wharf Stn Lift/Escalator 01' is in location 'Platform 1' - these are not easy to parse and necessarily link to a particular platform
* '''Lack of machine-interpretable data''' - sensor 5006 is described as 'Wolverhampton Stn Lift/Escalator 05', in location 'Passenger Lift Platform 4', whereas sensor 8127, 'Imperial Wharf Stn Lift/Escalator 01' is in location 'Platform 1' - these are not easy to parse and necessarily link to a particular platform
* '''Non-passenger assets''' - 1032 and 4034 are lifts situated in the South Wales and Thames Valley signalling centres, respectively. 1041 is "Mepham Street Goods No. 2" at London Waterloo, and 5054 will take you to "[https://en.wikipedia.org/wiki/Red_Star_Parcels Red Star Parcels]" in Milton Keynes
* '''Non-passenger assets''' - 1032 and 4034 are lifts situated in the South Wales and Thames Valley signalling centres, respectively. 1041 is "Mepham Street Goods No. 2" at London Waterloo, and 5054 will take you to "[https://en.wikipedia.org/wiki/Red_Star_Parcels Red Star Parcels]" in Milton Keynes
== Official documentation ==
Links to official documentation
=== Version 2 ===
* [https://docs.google.com/document/d/18IWzcjuuj6usxEv6pIRjH39EOouDFyIzk9nTXUP7ymE/edit Lifts & Escalators (LNE) API V2 - Usage Instructions] - overview, registration, creating API subscription, obtaining bearer token
* [https://docs.google.com/document/d/1Aikq_JzP2FvZkIJkKCBNahqIA0HdGwcSQUQUTP6oFY4/edit V2 API Authentication Docs] - creating API subscription, obtaining bearer token
* [https://docs.google.com/document/d/e/2PACX-1vTBUhyCXJoCvKUdIjE5GSyV3CqPgXg5d4K7DAghGilat4j8DTlWwMaTIQwTee-zvifFuW4NVB_0Hd5S/pub Documentation - Lifts & Escalators API v2 (developer preview)] - Types, endpoints, responses, example queries
* [[:File:Nr_lift_escalator_api_introspected_schema_2023-09-09.txt|Introspected GraphQL schema (2023-09-09)]] - Not provided officially (documentation claims that introspection has been disabled)
=== Version 1 ===
* [https://docs.google.com/document/d/e/2PACX-1vQEcL1yJLUVd8IAKGHi0s2cRsbKuedxuT2YT7b1TNnmjUi07_U15feiVWNlTGEzva7xoTiMrt4AcmE3/pub Documentation - Lifts & Escalators API (public preview)]

Latest revision as of 13:09, 6 February 2024

Network Rail's Lift and Escalator API was an API developed for Network Rail in 2020 by rail technology consultancy Hack Partners Ltd (now a rail AI software company, trading as CrossTech), nominally offering the real-time status of lifts and escalators at many locations across the rail network in Great Britain. The official documentation was quite sparse, hence this article was created by Peter in order to document the API unofficially.

This API was decommissioned on the 31st of January 2024, and replaced with a new API.

Transition

Transition to a new API began on the 17th of January 2024, with the CrossTech-maintained GraphQL and JSON APIs planned to be discontinued entirely on the 31st.

Signing up

You can register for an account on the Lift and Escalator API portal. Once you've verified your email address, navigate to the "products" tab. Click on "Developer" in the list on this page, then create a new subscription with a name of your choosing. Now, navigate to "Profile", you should be able to see your keys.

Access

Official documentation claims that V1 GraphQL functionality migrated to V2 doesn't require authentication, but this isn't entirely true. Some location information (e.g. postcode, toc) was broken out into a stations table, which is inaccessible while unauthenticated. The inclusion of station CRS codes in the assets table may render this table redundant.

Data elements (V1)

The following data elements are held within the API:

Field v2 equivalent Description
uprn prn (asset) Unique asset identifier (not a UPRN)
sensorId sensorId (status or asset tables) A four-digit sensor identifier for the Electronic Monitoring Unit (EMU), left-padded with zeroes if required.
blockId blockId (assets) An identifier for the location of the asset within a station
blockTitle The name of the location within the station
station name (station) Name of the station at which this asset is located
location location (asset) Name of the location within the station at which this asset is located
lat lat (station) Latitude in (WGS84)
long long (station) Longitude (WGS84)
postcode postcode (station) Postcode of the station in which this asset is located
route route (station) Network Rail Route in which this asset is located
territory region (station) Network Rail Region in which this asset is located
toc toc (station) Set to 'Managed Stations' for Network Rail Managed Stations, otherwise the name of the train operator
branch Unknown, but possibly the branch of the lift or escalator maintainer's organisation
type type (asset) Type of asset, e.g. Lift or Escalator
status status (status) Current status of the asset
isolated isolated (status) Indicates whether the asset is powered down or disconnected
engineerOnSite engineerOnSite (status) Indicates if an engineer has logged in to the sensor and is servicing the asset
independant independent (status) (note the misspelling - independant in v1, independent in v2) Indicates if the lift is on Independent Service by use of a car preference key
updatedTime Date and time when the status was last updated

Tables (V2)

Asset

Field Official description Description
id Unique asset identifier Unique identifier (of asset?)
prn Asset property reference number Unique asset identifier, renamed from UPRN. This field cannot be used in the query builder.
stationNumber Asset number This field cannot be used in the query builder.
description e.g. "Colonnade Lift", "Lift 3,Platform 20"
displayName Standardised asset name e.g. "Lift to Colonnade ", "Lift, Platform 20"
sensorId Associated sensor A sensor identifier for the Electronic Monitoring Unit (EMU), no longer zero-padded
blockId An identifier for the location of the asset within a station
crs Associated station CRS code of the station at which this asset is located
location Name of the location within the station at which this asset is located (e.g. "Colonnade Lift", "Platform 20")
type Asset type (i.e Lift or Escalator) Type of asset, e.g. Lift or Escalator
inCommission This field cannot be used in the query builder. This field is not officially documented. Note that this bears a striking resemblence to the misspelled inCommision you can see in the query builder.
publicFacing This field is not officially documented.
status relations not covered (Relation) Current status of the asset

Status

Field Official description Description
sensorId Unique sensor identifier ID of sensor
isolated Indicates whether the asset is powered down or disconnected
engineerOnSite Indicates if an engineer has logged in to the sensor and is servicing the asset
independent (note that this is now not misspelled), indicates if the lift is in independent service mode.
status last status received Current status of the asset (e.g. "Available", "Unknown", "Not Available")
lastUpdated Time of last update to status Documented in v2 preview documentation, this field is completely absent.
asset relations not covered (Relation) Asset to which this status relates

Stations

Field Official description Description
id Unique station identifier API-specific ID for station
crs Station CRS code CRS code of station asset is located at
name Name of station
lat Latitude in (WGS84)
long Longitude (WGS84)
toc Train operating company Set to 'Managed Stations' for Network Rail Managed Stations, otherwise the name of the train operator
region Network Rail Region in which this asset is located
route Network Rail Route in which this asset is located
postcode Postcode of the station in which this asset is located
address This field cannot be used in the query builder.
contactEmail This field cannot be used in the query builder.

Note that stations are only available if you've authenticated using your bearer token, this includes using the query builder on the portal. If you are not authenticated, you'll see an error which makes it look like the table simply doesn't exist.

Making a GraphQL request

All requests are through the API endpoint (https://nr-lift-and-escalator.azure-api.net/graphql/v2). Requests must be made via an HTTP POST request, navigating to this URL in a web browser will make an HTTP GET request, which will result in the following error:

{"path":"$","error":"resource does not exist","code":"not-found"}

The API uses GraphQL, which allows complex queries to be submitted in an HTTP POST request. A query is just a JSON data structure with some fields to filter on, and other fields to return.

REST API

With V2 came the introduction of a handful of REST endpoints, these are

Num and offset aren't documented; they're used for paging, with num defining the limit, and offset defining the offset. Both are nominally optional, but num will default to 50 if unset. Instead of paging through these, there's no upper limit to num, if you set it to 20000, you'll get all statuses at once.

Note that you need to provide bearer authentication for this, since it's passed through to GraphQL.

{"error":"field 'uprn' not found in type: 'assets'","path":"$.selectionSet.assets.selectionSet.uprn","code":"validation-failed"}

Simple requests

All assets at a station (V1)

To return the status of all lifts and escalators at a particular station, such as Edinburgh Waverley:

query MyQuery {
  status(where: {station: {_eq: "Edinburgh Waverley"}}) {
    blockTitle
    branch
    engineerOnSite
    independant
    isolated
    lat
    location
    long
    postCode
    route
    sensorId
    station
    status
    territory
    toc
    type
    updatedTime
    uprn
    blockId
  }
}

All assets at a station (V2)

query {
    assets(where: {crs: {_eq: "EDB"}}) {
        blockId
        crs
        description
        displayName
        id
        location
        sensorId
        status {
            engineerOnSite
            independent
            isolated
            sensorId
            status
        }
        type
    }
}

All assets at all stations (V2)

query {
	assets {
		blockId
		crs
		description
		displayName
		id
		location
		sensorId
		status {
			engineerOnSite
			independent
			isolated
			sensorId
			status
		}
		type
	}
}

Stream of updates

It is supposedly possible to make an API request and receive a stream of updates using the @live directive on the GraphQL query, but does not seem to work on this API.

Room for improvement (V1)

There is some room for improvement on the API:

  • Null entries - some fields are set to "#N/A", and some are set to null
  • Unmapped sensors - there are instances (such as sensorId 3104) where no data has been filled in about the asset at all
  • No escalators - some escalators are included but fall fully within the problem above, all have null locational data
  • Incorrect references to territories - the term 'territory' was in use during Railtrack days, but is no longer used - Region and Routes are the current terminology
  • Out-of-date TOC information - sensor 4052 refers to London Midland, sensor 3082 refers to East Coast, and 6148 to Arriva Trains Wales - none of whom currently operate franchises
  • Lack of machine-interpretable data - sensor 5006 is described as 'Wolverhampton Stn Lift/Escalator 05', in location 'Passenger Lift Platform 4', whereas sensor 8127, 'Imperial Wharf Stn Lift/Escalator 01' is in location 'Platform 1' - these are not easy to parse and necessarily link to a particular platform
  • Non-passenger assets - 1032 and 4034 are lifts situated in the South Wales and Thames Valley signalling centres, respectively. 1041 is "Mepham Street Goods No. 2" at London Waterloo, and 5054 will take you to "Red Star Parcels" in Milton Keynes

Official documentation

Links to official documentation

Version 2

Version 1