Realtime Websocket API 1.0.1

Websocket API for realtime vehicle positions and stop sequences based on scheduled times and realtime updates.

The websocket API works by receiving commands from and sending messages to the client application. The possible commands and messages are described in detail in the Operations section of this AsyncAPI documentation.

Quick Start

OpenLayers Client Library

Note that for basic browser applications, it might not be necessary to talk directly to the realtime API. Consider using our client library instead. If your use-case is not covered by that, feel free to read on.

Connecting

You have to establish a websocket connection as described in the Servers section using your favorite client library. A valid API key is needed. See terms of service for more information on API keys.

Ping? Pong!

If your client library does not support websocket native ping/pong frames (for example if your application runs in a web browser), you have to periodically send application layer PingCommands to keep the connection alive. The payload of a PingCommand is simply PING. If the connection is still alive, you should receive a PongMessage shortly after. If you don't get a PongMessage within a reasonable amount of time, consider reconnecting.

Vehicles on a Map

A typical use case is to draw vehicles (trains, trams, busses, ...) moving on a map. The coordinate system used by the API is Web Mercator (EPSG:3857) and the zoom level is given as a mapbox zoom level. In order to get vehicle positions within a given bounding box, you have to subscribe using the BBoxCommand. For example, a payload to get initial vehicle positions and vehicle position updates close to Olten in Switzerland at zoom level 11 would look like this:

BBOX 837468 5963148 915383 6033720 11

See BBoxCommand for details and additional filters.

You will then start receiving PartialTrajectoryMessages. Each message is basically a section of the trajectory of a train (in the sense of a series of vehicles) together with timing information. This spatial and temporal information can be used to interpolate the vehicle position in your client application. The longest possible partial trajectory is between two stops of a train. You will receive new partial trajectories whenever a train passes the next stop or new timing information is available. Here is an example of such a partial trajectory in spacetime:

{
  "source": "trajectory",
  ...
  "content": {
    "type": "Feature",
    "geometry": {
      "type": "LineString",
      "coordinates": [
        [
          287268,
          6246052
        ],
        [
          286486,
          6245972
        ]
      ]
    },
    "properties": {
      ...
      "time_intervals": [
        [
          1699631460000,
          0,
          0
        ],
        [
          1699631460000,
          0,
          0
        ],
        [
          1699631580000,
          1,
          0
        ],
        [
          1699631580000,
          1,
          0
        ]
      ],
      ...
    }
  }
}

The spatial part is given as a GeoJSON LineString Feature. The temporal information is given in the Feature properties at the time_intervals key. The value is a JSON array. Each item is a JSON array with 3 entries: The timestamp (milliseconds since the epoch), the fraction along the LineString from 0 to 1, and the rotation of the vehicle in radians (with zero pointing west).

If you want to change the bounding box or zoom level, simply send another BBoxCommand. Mind that choosing a bounding box bigger than what the user actually sees and sending a new command only when the user's view leaves this bounding box will help to reduce communication load.

You can find suitable background maps here.

What else is possible?

We can also offer station information and departure and arrival timetables at stations for selected data sources. If you are interested in such functionalities, please contact us.

Servers

  • wss://api.geops.io/tracker-ws/{BACKEND}wsAPIGateway
    object
    BACKEND
    required
    string

    Backend to connect to. v1 corresponds to production, dev to development. Note that this asyncapi schema describes only the v1 backend. API version and schema can differ on dev backend.

      Allowed values:
    • "v1"
    • "dev"
      Examples values:
    • "v1"
    • "dev"
    Security:
    • HTTP API key
      • Name: key
      • In: query

      Your API key. See terms of service for more information.

Operations

  • PUB /

    The exclusive channel that corresponds to the websocket connection.

    Commands that can be sent to the application.

    Commands are used to request messages from the application, to subsribe to message streams and to keep the connection alive. Unlike messages sent by the application, commands are not JSON objects but plain strings.

    Operation IDPublishOperation

    Available only on servers:

    object

    Accepts one of the following messages:

    • #0PingCommandPingCommand
      Message IDPingCommand
      Payload
      string

      Application-Layer Ping Command

      Application-Layer ping command for clients not supporting websocket ping/pong frames. Send this (periodically) to avoid connection timeouts or to validate the connection. If the connection is alive, the application will respond with a PongMessage. Not needed if your client supports websocket native ping/pong frames (browsers usually don't).

      The form of the command is

      PING
      
      Const:"PING"
        Allowed values:
      • "PING"
      • #command

      Examples

    • #1BBoxCommandBBoxCommand
      Message IDBBoxCommand
      Payload
      string
      must match: ^BBOX .*$

      BBox Command

      Subscribe to PartialTrajectoryMessages for a given bounding box and zoom level with optional additional filters. The form of the command is

      BBOX <left> <bottom> <right> <top> <zoom> [<tenant>] [<has_realtime>] [<gen>] [<mots>]
      

      The bounding box is in web mercator epsg:3857 units. The zoom level is a mapbox zoom level. Arguments can also be passed by name (see examples). Subscribing will also trigger sending the initial content once. If buffering is enabled (see BufferCommand), the last message in the buffer array of the initial content will always be a null message.

      Optional Filter Arguments:

      • tenant: filter on a specific data source (tenant)
      • has_realtime: filter on GTFS tenants with GTFS-RT
      • gen:preferred generalization level (5, 10, 30, 100, 150). So far, only effective for tenant sbb.
      • mots: comma separated list of modes of transport (MOT) to filter on. Possible MOTs:
        • tram
        • subway
        • rail
        • bus
        • ferry
        • cablecar
        • gondola
        • funicular
        • coach

      A new BBoxCommand will always abort all previous running or queued BBoxCommands.

      • #command

      Examples

    • #2GetFullTrajectoryCommandGetFullTrajectoryCommand
      Message IDGetFullTrajectoryCommand
      Payload
      string
      must match: ^GET\s+full_trajectory_[a-z0-9_-]+_[0-9]+(?:_gen[0-9]+)?(?:\s+client_ref=\S*)?$

      Get Full Trajectory Command

      Get the full trajectories for all journeys of a given train. The command has the form

      GET full_trajectory_<train_id>[_gen<gen_level>][ client_ref=<client_ref>]
      

      The parameters are as follows:

      • train_id: the id of the train as found in a trajectory message
      • gen_level: the preferred generalization level (optional, see also BBoxCommand)
      • client_ref: optional client reference forwarded to the FullTrejectoryMessage

      The result will be a FullTrajectoryMessage with the source set according to the request.

      • #command

      Examples

    • #3GetPartialTrajectoryCommandGetPartialTrajectoryCommand
      Message IDGetPartialTrajectoryCommand
      Payload
      string
      must match: ^GET\s+partial_trajectory_[a-z0-9_-]+_[0-9]+(?:_gen[0-9]+)?(?:\s+client_ref=\S*)?$

      Get Partial Trajectory Command

      Get the partial trajectory for a given train. The command has the form

      GET partial_trajectory_<train_id>[_gen<gen_level>][ client_ref=<client_ref>]
      

      The parameters are as follows:

      • train_id: the id of the train as found in a trajectory message
      • gen_level: the preferred generalization level (optional, see also BBoxCommand)
      • client_ref: optional client reference forwarded to the PartialTrejectoryMessage

      The result will be a PartialTrajectoryMessage with the source set according to the request.

      • #command

      Examples

    • #4GetStopSequenceCommandGetStopSequenceCommand
      Message IDGetStopSequenceCommand
      Payload
      string
      must match: ^GET\s+stopsequence_[a-z0-9_-]+_[0-9]+(?:\s+client_ref=\S*)?$

      Get Stop Sequence Command

      Get the stop sequences for all journeys of a given train. The command has the form

      GET stopsequence_<train_id>[ client_ref=<client_ref>]
      

      The parameters are as follows:

      • train_id: the id of the train as found in a trajectory message
      • client_ref: optional client reference forwarded to the StopSequenceMessage

      The result will be a StopSequenceMessage with the source set according to the request.

      • #command

      Examples

    • #5SubStopSequenceCommandSubStopSequenceCommand
      Message IDSubStopSequenceCommand
      Payload
      string
      must match: ^SUB\s+stopsequence_[a-z0-9_-]+_[0-9]+$

      Sub Stop Sequence Command

      Subscribe to the stop sequences for all journeys of a given train. The command has the form

      SUB stopsequence_<train_id>
      

      The parameters are as follows:

      • train_id: the id of the train as found in a trajectory message

      The result will be StopSequenceMessages with the source set according to the request. This command will only subscribe to updates. Use the according GET command first to get the current state.

      Note that trains without any realtime information will not receive stop sequence updates for performance reasons. Instead, the client is responsible for calculating the current call based on time. This is indicated by "state": "TIME_BASED" in the stations field.

      • #command

      Examples

    • #6BufferCommandBufferCommand
      Message IDBufferCommand
      Payload
      string
      must match: BUFFER(?:\s+[0-9]+){1,2}

      Buffer Command

      Request that messages tagged as buffer should be sent in chunks via BufferMessage.

      The command has the form

      BUFFER <timeout> [<size>]
      

      The parameters are as follows:

      • timeout: the timeout for flushing the buffer in ms
      • size: the buffer size (defaults to the max buffer size of 500)

      Note that buffer settings cannot be changed unless after sending a ResetCommand. The channel default is to not use any buffering.

      • #command

      Examples

    • #7ResetCommandResetCommand
      Message IDResetCommand
      Payload
      string

      Reset Command

      Reset all settings and cancel all subscriptions to get back to a websocket channel state as before sending any commands.

      The form of the command is

      RESET
      
      Const:"RESET"
        Allowed values:
      • "RESET"
      • #command

      Examples

  • SUB /

    The exclusive channel that corresponds to the websocket connection.

    Messages sent by the application.

    Messages sent by the application as a result of having received a command in the past. All messages are JSON objects with the fields source, timestamp, client_reference and content. The source field serves as a virtual channel/topic.

    Operation IDSubscribeOperation

    Available only on servers:

    object

    Accepts one of the following messages:

    • #0StatusMessageStatusMessage
      Message IDStatusMessage
      object [StatusMessage]

      Status Message

      When the channel is ready to receive commands, a status open message is sent.

      • #message

      Examples

    • #1PongMessagePongMessage
      Message IDPongMessage
      object [PongMessage]

      Application-Layer Pong Message

      Response to an application-layer PING command.

      • #message

      Examples

    • #2PartialTrajectoryMessagePartialTrajectoryMessage
      Message IDPartialTrajectoryMessage
      object [PartialTrajectoryMessage]

      Partial Trajectory Message

      Current section of the route the given train is on with a TrackerTrajectory GeoJSON Feature as the content. This message is sent in response to either a BBoxCommand or to a GetPartialTrajectoryCommand.

      The source field is either trajectory for messages originating from a BBoxCommand or has the form trajectory_<train_id>[_gen<gen_level>] when originating from a GET command with the same value as an argument.

      The content is null if this message is a response to a GET command with a failed lookup.

      client_reference is an empty string if originating from a BBoxCommand or the client reference set in the GET command if originating from a GET command.

      • #message
      • #buffer

      Examples

    • #3FullTrajectoryMessageFullTrajectoryMessage
      Message IDFullTrajectoryMessage
      object [FullTrajectoryMessage]

      Full Trajectory Message

      All trajectories for the journeys of a train with a FullTrajectoryCollection GeoJSON FeatureCollection as the content. This message is sent in response to a GetFullTrajectoryCommand.

      The source field has the form full_trajectory_<train_id>[_gen<gen_level>] which corresponds to the argument of the GET command.

      The content is null if the lookup of the GET command failed.

      • #message

      Examples

    • #4StopSequenceMessageStopSequenceMessage
      Message IDStopSequenceMessage
      object [StopSequenceMessage]

      Stop Sequence Message

      Information about the stops along the journeys of a train. This message is sent in response to a GetStopSequenceCommand or a SubStopSequenceCommand.

      The source field has the form stopsequence_<train_id> which corresponds to the argument of the GET or SUB command.

      The content is null if the lookup of the GET / SUB command failed.

      • #message

      Examples

    • #5DeletedVehicleMessageDeletedVehicleMessage
      Message IDDeletedVehicleMessage
      object [DeletedVehicleMessage]

      Deleted Vehicle Message

      This message is informing about deletion of a train.

      The content is the train id.

      • #message
      • #buffer

      Examples

    • #6BufferMessageBufferMessage
      Message IDBufferMessage
      object [BufferMessage]

      Buffer Message

      A wrapper combining multiple messages. Buffering is activated by the BufferCommand.

      The content is an array of wrapped messages. Only messages tagged as buffer will potentially be wrapped up. The initial messge from a buffered BBoxCommand is always terminated with a null message. See also BufferCommand and BBoxCommand.

      • #message

      Examples

    • #7LogMessageLogMessage
      Message IDLogMessage
      object [LogMessage]

      Log Message

      A message with technical information or a warning regarding the channel or received commands.

      Note that more than one field of the content can be set (see examples).

      • #message

      Examples

Schemas

  • BBoxCommand
    string
    must match: ^BBOX .*$

    BBox Command

    Subscribe to PartialTrajectoryMessages for a given bounding box and zoom level with optional additional filters. The form of the command is

    BBOX <left> <bottom> <right> <top> <zoom> [<tenant>] [<has_realtime>] [<gen>] [<mots>]
    

    The bounding box is in web mercator epsg:3857 units. The zoom level is a mapbox zoom level. Arguments can also be passed by name (see examples). Subscribing will also trigger sending the initial content once. If buffering is enabled (see BufferCommand), the last message in the buffer array of the initial content will always be a null message.

    Optional Filter Arguments:

    • tenant: filter on a specific data source (tenant)
    • has_realtime: filter on GTFS tenants with GTFS-RT
    • gen:preferred generalization level (5, 10, 30, 100, 150). So far, only effective for tenant sbb.
    • mots: comma separated list of modes of transport (MOT) to filter on. Possible MOTs:
      • tram
      • subway
      • rail
      • bus
      • ferry
      • cablecar
      • gondola
      • funicular
      • coach

    A new BBoxCommand will always abort all previous running or queued BBoxCommands.

  • BufferCommand
    string
    must match: BUFFER(?:\s+[0-9]+){1,2}

    Buffer Command

    Request that messages tagged as buffer should be sent in chunks via BufferMessage.

    The command has the form

    BUFFER <timeout> [<size>]
    

    The parameters are as follows:

    • timeout: the timeout for flushing the buffer in ms
    • size: the buffer size (defaults to the max buffer size of 500)

    Note that buffer settings cannot be changed unless after sending a ResetCommand. The channel default is to not use any buffering.

  • object [BufferMessage]

    Buffer Message

    A wrapper combining multiple messages. Buffering is activated by the BufferCommand.

    The content is an array of wrapped messages. Only messages tagged as buffer will potentially be wrapped up. The initial messge from a buffered BBoxCommand is always terminated with a null message. See also BufferCommand and BBoxCommand.

  • object [DeletedVehicleMessage]

    Deleted Vehicle Message

    This message is informing about deletion of a train.

    The content is the train id.

  • object [FullTrajectory]

    The trajectory for one of the journeys of a train as a GeoJSON Feature.

    The geometry is either a (Multi)LineString or a GeometryCollection of a (Multi)LineString and a MultiPoint. If the MultiPoint is delivered, the points correspond to stops projected onto the trajectory.

    MultiLineStrings can occur when the trajectory is discontinous at at least one of the stops.

  • object [FullTrajectoryCollection]

    All trajectories for the journeys of a train as a GeoJSON FeatureCollection.

  • object [FullTrajectoryCollectionProperties]
  • object [FullTrajectoryMessage]

    Full Trajectory Message

    All trajectories for the journeys of a train with a FullTrajectoryCollection GeoJSON FeatureCollection as the content. This message is sent in response to a GetFullTrajectoryCommand.

    The source field has the form full_trajectory_<train_id>[_gen<gen_level>] which corresponds to the argument of the GET command.

    The content is null if the lookup of the GET command failed.

  • object [FullTrajectoryProperties]
  • object [GeometryCollectionGeometry]

    Collection of MultiPoint, LineString and MultiLineString

    MultiPoint is a list of points of interest, i.e. stop points in this context. (Multi)LineStrings represent a trajectory.

  • GetFullTrajectoryCommand
    string
    must match: ^GET\s+full_trajectory_[a-z0-9_-]+_[0-9]+(?:_gen[0-9]+)?(?:\s+client_ref=\S*)?$

    Get Full Trajectory Command

    Get the full trajectories for all journeys of a given train. The command has the form

    GET full_trajectory_<train_id>[_gen<gen_level>][ client_ref=<client_ref>]
    

    The parameters are as follows:

    • train_id: the id of the train as found in a trajectory message
    • gen_level: the preferred generalization level (optional, see also BBoxCommand)
    • client_ref: optional client reference forwarded to the FullTrejectoryMessage

    The result will be a FullTrajectoryMessage with the source set according to the request.

  • GetPartialTrajectoryCommand
    string
    must match: ^GET\s+partial_trajectory_[a-z0-9_-]+_[0-9]+(?:_gen[0-9]+)?(?:\s+client_ref=\S*)?$

    Get Partial Trajectory Command

    Get the partial trajectory for a given train. The command has the form

    GET partial_trajectory_<train_id>[_gen<gen_level>][ client_ref=<client_ref>]
    

    The parameters are as follows:

    • train_id: the id of the train as found in a trajectory message
    • gen_level: the preferred generalization level (optional, see also BBoxCommand)
    • client_ref: optional client reference forwarded to the PartialTrejectoryMessage

    The result will be a PartialTrajectoryMessage with the source set according to the request.

  • GetStopSequenceCommand
    string
    must match: ^GET\s+stopsequence_[a-z0-9_-]+_[0-9]+(?:\s+client_ref=\S*)?$

    Get Stop Sequence Command

    Get the stop sequences for all journeys of a given train. The command has the form

    GET stopsequence_<train_id>[ client_ref=<client_ref>]
    

    The parameters are as follows:

    • train_id: the id of the train as found in a trajectory message
    • client_ref: optional client reference forwarded to the StopSequenceMessage

    The result will be a StopSequenceMessage with the source set according to the request.

  • object [JourneyExtraData]
  • object [Line]
  • object [LineStringGeometry]
  • object [LogContent]
  • object [LogMessage]

    Log Message

    A message with technical information or a warning regarding the channel or received commands.

    Note that more than one field of the content can be set (see examples).

  • object [MultiLineStringGeometry]
  • object [MultiPointGeometry]
  • object [PartialTrajectoryMessage]

    Partial Trajectory Message

    Current section of the route the given train is on with a TrackerTrajectory GeoJSON Feature as the content. This message is sent in response to either a BBoxCommand or to a GetPartialTrajectoryCommand.

    The source field is either trajectory for messages originating from a BBoxCommand or has the form trajectory_<train_id>[_gen<gen_level>] when originating from a GET command with the same value as an argument.

    The content is null if this message is a response to a GET command with a failed lookup.

    client_reference is an empty string if originating from a BBoxCommand or the client reference set in the GET command if originating from a GET command.

  • PingCommand
    string

    Application-Layer Ping Command

    Application-Layer ping command for clients not supporting websocket ping/pong frames. Send this (periodically) to avoid connection timeouts or to validate the connection. If the connection is alive, the application will respond with a PongMessage. Not needed if your client supports websocket native ping/pong frames (browsers usually don't).

    The form of the command is

    PING
    
    Const:"PING"
      Allowed values:
    • "PING"
  • object [PongMessage]

    Application-Layer Pong Message

    Response to an application-layer PING command.

  • ResetCommand
    string

    Reset Command

    Reset all settings and cancel all subscriptions to get back to a websocket channel state as before sending any commands.

    The form of the command is

    RESET
    
    Const:"RESET"
      Allowed values:
    • "RESET"
  • object [SerializedCancellationChange]
  • object [Situation]
  • object [StatusContent]
  • object [StatusMessage]

    Status Message

    When the channel is ready to receive commands, a status open message is sent.

  • object [StopSequence]
  • object [StopSequenceCall]
  • object [StopSequenceMessage]

    Stop Sequence Message

    Information about the stops along the journeys of a train. This message is sent in response to a GetStopSequenceCommand or a SubStopSequenceCommand.

    The source field has the form stopsequence_<train_id> which corresponds to the argument of the GET or SUB command.

    The content is null if the lookup of the GET / SUB command failed.

  • SubStopSequenceCommand
    string
    must match: ^SUB\s+stopsequence_[a-z0-9_-]+_[0-9]+$

    Sub Stop Sequence Command

    Subscribe to the stop sequences for all journeys of a given train. The command has the form

    SUB stopsequence_<train_id>
    

    The parameters are as follows:

    • train_id: the id of the train as found in a trajectory message

    The result will be StopSequenceMessages with the source set according to the request. This command will only subscribe to updates. Use the according GET command first to get the current state.

    Note that trains without any realtime information will not receive stop sequence updates for performance reasons. Instead, the client is responsible for calculating the current call based on time. This is indicated by "state": "TIME_BASED" in the stations field.

  • object [TrackerTrajectory]

    Current section of the route the given train is on as a GeoJSON Feature.

    The geometry contains the LineString between two stops.

    The time_intervals property contains a list of [timestamp, fraction, direction] tuples.

    Each time_intervals item contains the fraction of the geometry where the vehicle is at the given timestamp. If present the direction is the current rotation of the vehicle relative to the horizontal axis as radian.

    The current location of the vehicle can be calculated by linear interpolation from the fraction of the first item where the timestamp is smaller then the current time to the fraction of the next item.

    If the last timestamp is in the past, the trajectory should not be visualized by a client.

  • object [TrackerTrajectoryProperties]