Journey Feed

Service and feed requirements:

  • HTTPS (from publicly verifiable certificate)

  • HTTP 1.1 GET and POST requests

  • URL is publicly accessible over the internet

  • Mime type must be set to application/json

  • Authentication: none, basic or client certificate

  • All content is always encoded in UTF-8

  • Service endpoint is up 24/7

    • Operational availability will be monitored

Requirements to response time:

  • Generally feeds should have a response time of less than two seconds

Requirements for access point/AP identification:

  • APs must be identifiable through their main MAC address (typically also the serial number)

    • The format of these MAC addresses as regex is exactly: [A-F0-9]{12}

Content requirements:

  • Content must be valid JSON

    • numeric values must be represented as numeric values, not as strings

    • boolean values must be represented as boolean values, not as strings

    • string values must be represented as string values using double quotes

  • All properties are case sensitive

  • At a minimum texts in the default language of the portal page must be provided

Feed types

Currently the Unwired Cloud journey information supports two feed request types:

  • GET request based feeds

  • POST request based feeds

GET request based feeds are typically implemented by providing one feed URL per line or customer. Examples URLs:

POST request based feeds receive a list of AP MAC addresses within the POST data as a JSON array, and respond only with data for the requested devices. Example URLs:

Language and i18n support

Feeds are required to return data in all supported or customer relevant languages within each response. Typically the set of provided languages maps to the list of languages enabled on the customer’s portal page. All fields have generic i18n support implemented through JSON language mappings from ISO 639-1 codes to content. Example:

{
  "de": "Heute kein Halt in Wien Hbf.",
  "en": "Train will not stop in Wien Hbf. today"
}

This format name is defined in the document to be called TranslatedString. All language codes have to be lowercase only. All property values of a TranslatedString must be non-null.

Interaction with the portal page:

  • the portal page has a default language and a list of supported languages

  • the feed should as a minimum provide data in the default language of the target portal page

    • all other languages will fall back to that default language if not provided

    • all other languages don’t need to be provided, but it is recommended to provide all languages for best user experience

Feed request

Feeds can be requested through a GET or a POST request. The request format for those is different, but the response is the same.

Implementation recommendation

It is recommended to implement at least the POST request based feed format. Implementing both request formats will provide better support for staged or testing splashpages.

Feed request format for GET

Unwired Network’s cloud-based feed fetching infrastructure will regularly fetch the feed using an HTTP 1.1 GET request. The request has no other additional parameters other than those specified through the feed URL. All existing provider-specific parameters (e.g. line or customer identifier) will be preserved unmodified.

The resulting response is exactly the JSON response described below.

The configuration URI scheme prefix for GET-based journey feeds is: unwired-journey-v1-get+

Full example URL:

unwired-journey-v1-get+https://some-rbl-provider/unwired-feed?line=38A

Feed request format for POST

Unwired Network’s cloud-based feed fetching infrastructure will regularly fetch the feed using an HTTP 1.1 POST request. The POST request sends JSON data using the application/json content type to the configured URL. The POST data contains:

  • requested languages (the feed is allowed to return data in more or less than the requested languages)

  • requested deviceIds (the feed must return data for all the requested deviceIds)

The resulting response is exactly the JSON response described below.

The configuration URI scheme prefix for POST-based journey feeds is: unwired-journey-v1-post+

Full example URL:

unwired-journey-v1-post+https://some-rbl-provider/unwired-feed?line=38A

Example POST content

{
  "languages": ["de", "en"],
  "deviceIds": ["AABBCCDDEEFF", "001122334455"]
}

Feed response

Feed response requirements

The feed response must have these requirements:

  • content-type: application/json

Feed response content

In the response AP MACs are grouped into similar information/lines and returned as such.

Example for response grouping:

  • request deviceIds: ["AABBCCDDEEFF","001122334455","AABBCC334455"]

  • response (in this example, one has no currently active information, and two others share the same line):

    • The first group only contains 001122334455 and has a statusCode of no_course

    • The second group contains AABBCCDDEEFF and AABBCC334455, has a statusCode of successand contains a course` property with course details, stops and other information

The feed response must contain an array of groups/object. Any number of groups can be provided in a feed response. The formal definition is: [Group]

Each Group object contains these fields:

  • apiVersion: must be set to 1 (numeric)

  • statusCode: can be:

    • success: this means a valid course property is provided for this group of AP MACs

    • no_course: this means that for all of the AP MACs in this group, no journey information is available (the AP MAC is known, but is not actively moving along a course)

    • unknown_device: this means that the journey feed source does not know the device and thus cannot provide data

      • this is used for support/delivery to see which devices are properly configured

    • error: means that some error occurred for all AP MACs in this group

      • must provide “error” property (see below)

      • can list all requested AP MACs if some generic error occurred

  • deviceIds: an array of AP MACs that this group refers to

    • AP MACs must be all uppercase and not use any colon-characters (:)

    • Regex: [0-9A-F]{12}

    • Example: "deviceIds": ["AABBCCDDEEFF"]

  • error: only if statusCode is error, contains an internal error message.

    • This message will not be presented to the user and is purely for operational purposes.

    • This property must have a valid string value, or not be included at all

  • currentDFIMessage (DEPRECATED): a TranslatedString message that is important and will be shown to the user

    • this property has been deprecated, the recommended implementation is to use the message property

  • message (TranslatedString, optional): a TranslatedString message that is important and will be shown to the user

If the statusCode is success an additional set of properties must be included:

  • languages: an array of supported languages as ISO 639-1 codes in the response

  • course: the object with all the course information

    • course.id (string, mandatory): a string id property that uniquely (for the feed) identifies that course

    • course.line (string, optional): a string line name (e.g. 38A)

    • course.origin (string, mandatory): a TranslatedString with the origin name

    • course.destination (string, mandatory): a TranslatedString with the destination name

    • course.stops (array, mandatory): an array of Stop objects (see below)

Stop objects contain:

  • id (mandatory): a property that uniquely identifies a stop. This can be the IBNR or DS100.

    • For POI feeds this is used to match text content to the journey data (see unwired splash page text feeds spec 1.2+ for details)

  • ibnr (string, optional): the IBNR of the stop

  • ds100 (string, optional): the DS100 of the stop

  • name (TranslatedString, mandatory): the name of the stop

  • departureDelay (numeric, mandatory if not last stop): the departure delay of the stop in minutes

  • departurePlanned (string, mandatory if not last stop): the ISO 8601 string of the planned departure time and date of the stop (including time zone)

  • arrivalDelay (numeric, mandatory if not first stop): the arrival delay of the stop in minutes

  • arrivalPlanned (string, mandatory if not first stop): the ISO 8601 string of the planned arrival time and date of the stop (including time zone)

  • cancelled (boolean, mandatory): true if this stop has been cancelled and should not be shown as the next stop in the progress indicator

  • platformDeparture (string, optional): the platform name at departure

  • platformArrival (string, optional): the platform name at arrival

  • track (Track object, optional): for future use, please leave out for now or provide an empty array []

  • connections (array of Connection objects, mandatory): if not used please provide empty array []

  • message (TranslatedString, optional): a TranslatedString message that is important and will be shown to the user

Connection objects contain:

  • id (string, mandatory): a unique ID for the connection, this is not user-visible

  • line (string, optional): the name of the connecting line

  • destination (TranslatedString, mandatory): the destination name

  • departurePlanned (string, mandatory): an ISO 8601 string with the planned departure time and date (including time zone)

  • departureDelay (numeric, mandatory): the departure delay of that connection

  • platformDeparture (string, optional): an optional departure platform

  • message (TranslatedString, optional): a TranslatedString message that is important and will be shown to the user

Feed response schema validation

A JSON schema validation file called schema-json-unwired.json can be provided to perform automatic content validation. The schema validation file is based on the ajv schema validator.

The schema definition is also a useful resource to see field formats and verification patterns (e.g. for strings, ISO 639-1 language codes and ISO 8601 date/time formats).

Feed response example

This is a full and complete example of journey data. It contains three groups:

  • first group contains one AP, that has no journey/course

  • second group contains one AP, that had an error retrieving the data and thus provides an error message

  • third group contains two APs, that share the same course

[
  {
    "statusCode": "no_course",
    "apiVersion": 1,
    "deviceIds": ["001122334455"]
  },
  {
    "statusCode": "error",
    "apiVersion": 1,
    "error": "Internal error while fetching data (1234)",
    "deviceIds": ["001122334456"]
  },
  {
    "statusCode": "success",
    "apiVersion": 1,
    "languages": ["de"],
    "deviceIds": ["001122334457", "001122334458"],
    "message": {
      "de": "Heute kein Halt am Schwedenplatz"
    },
    "course": {
      "origin": {
        "de": "Gonzagagasse"
      },
      "destination": {
        "de": "Praterstern"
      },
      "id": "12345",
      "line": "1",
      "stops": [
        {
          "id": "UW_1001",
          "ibnr": "UW_1001",
          "ds100": "UW_GG",
          "departureDelay": 0,
          "departurePlanned": "2018-03-25T13:11:00+00:00",
          "platformDeparture": "3",
          "name": {
            "de": "Gonzagagasse"
          },
          "cancelled": false,
          "message": {
            "de": "Keine Umsteigemöglichkeit zur S-Bahn"
          },
          "track": [],
          "connections": [
            {
              "line": "20A",
              "destination": {
                "de": "Kahlenberg"
              },
              "message": {
                "de": "Schienenersatzverkehr zwischen Döbling und Neuwaldegg"
              },
              "id": "74712",
              "departureDelay": 4,
              "departurePlanned": "2018-03-25T13:13:00+00:00"
            },
            {
              "line": "9",
              "destination": {
                "de": "Schottentor"
              },
              "id": "74715",
              "departureDelay": 0,
              "departurePlanned": "2018-03-25T13:14:00+00:00"
            },
            {
              "line": "9",
              "destination": {
                "de": "Universität"
              },
              "id": "74714",
              "departureDelay": 1,
              "departurePlanned": "2018-03-25T13:15:00+00:00"
            }
          ]
        },
        {
          "id": "UW_1002",
          "ibnr": "UW_1002",
          "ds100": "UW_SR",
          "arrivalDelay": 3,
          "arrivalPlanned": "2018-03-25T13:18:00+00:00",
          "departureDelay": 0,
          "departurePlanned": "2018-03-25T13:19:00+00:00",
          "platformArrival": "2",
          "platformDeparture": "2",
          "name": {
            "de": "Schottenring"
          },
          "cancelled": false,
          "track": [],
          "connections": [
            {
              "line": "U2",
              "destination": {
                "de": "Heiligenstadt"
              },
              "id": "747141",
              "departureDelay": 0,
              "departurePlanned": "2018-03-25T13:21:00+00:00",
              "platformDeparture": "3"
            },
            {
              "line": "U2",
              "destination": {
                "de": "Hütteldorf"
              },
              "id": "747142",
              "departureDelay": 0,
              "departurePlanned": "2018-03-25T13:29:00+00:00",
              "platformDeparture": "4"
            }
          ]
        },
        {
          "id": "UW_1003",
          "ibnr": "UW_1003",
          "ds100": "UW_TS",
          "arrivalDelay": 0,
          "arrivalPlanned": "2018-03-25T13:36:00+00:00",
          "departurePlanned": "2018-03-25T13:38:00+00:00",
          "platformDeparture": "4",
          "name": {
            "de": "Taborstraße"
          },
          "cancelled": false,
          "platformArrival": "4",
          "track": [],
          "connections": []
        },
        {
          "id": "UW_1004",
          "ibnr": "UW_1004",
          "ds100": "UW_PS",
          "arrivalPlanned": "2018-03-25T13:51:00+00:00",
          "departureDelay": 1,
          "departurePlanned": "2018-03-25T13:54:00+00:00",
          "platformArrival": "2",
          "platformDeparture": "2",
          "name": {
            "de": "Praterstraße"
          },
          "cancelled": false,
          "track": [],
          "connections": []
        },
        {
          "id": "UW_1005",
          "ibnr": "UW_1005",
          "ds100": "UW_PRASTERN",
          "arrivalDelay": 0,
          "arrivalPlanned": "2018-03-25T14:20:00+00:00",
          "name": {
            "de": "Praterstern"
          },
          "cancelled": false,
          "platformArrival": "2",
          "track": [],
          "connections": []
        }
      ]
    }
  }
]

Content revisions

Revision

Published date

Changes

1.0

2018-11-01

initial release

1.1

2018-11-08

added information about language fallback and currentDFIMessage

1.2

2018-11-09

normalized all language identifiers to lowercase

1.3

2019-03-25

added statusCode “unknown_device”
rename error_message to error
added more individual details to the request formats

1.4

2019-07-24

replace property currentDFIMessage with message
added message properties for stops and connections
added implementation recommendation for feed request format

1.5

made connection.line optional, clarified course properties if mandatory/optional

1.6

2023-08-31

moved to public docs