Live Data API

The Live Data API can be used to receive live streamed boat data and is different from the GraphQL API.

Protocol

The Live Data API uses the WebSocket protocol exclusively. All messages (requests and responses) are send as JSON encoded objects.

Authentication

The Live Data API uses the same API tokens as the GraphQL API. For instructions on how to retrieve an API key, see Authentication. A valid API key must be used when subscribing to data (see below), and will only allow subscribing to data of boats that the user owning the API key has permissions for.

Endpoints

Njord operates multiple live data endpoints around the globe to ensure low latency between the boat and the live data endpoint. At the time of writing this, there are 3 endpoints, in Frankfurt (Germany), Northern Virginia (USA) and Sydney (Australia).

When set up correctly, boats will send live data to the nearest endpoint automatically. In order to receive live data via the API, you need to connect to the appropriate endpoint. There are two strategies that you can use.

Retrieve a Boat's Endpoint

To retrieve the live data endpoint WebSocket URL for a specific boat, access the liveDataStatus.WebSocketUrl2 field of that boat in any GraphQL query. For example, the following GraphQL query will return all boats that you have access to that have sent live data at some point, and their WebSocket URLs.

query {
  listBoats(filter: { hasLiveDataAfter: "2020-01-01T00:00Z" }) {
    boat {
      key
      name
      liveDataStatus {
        webSocketUrl2
      }
    }
  }
}

The response will look like:

{
  "data": {
    "listBoats": [
      {
        "boat": {
          "key": "Boat_abc",
          "name": "Live Boat",
          "liveDataStatus": {
            "websocketUrl2": "wss://live-eu-central-1.prod.sailnjord.com:5002/"
          }
        }
      }
    ]
  }
}

Connect to All Endpoints

You can also create separate connections to all live data endpoints at the same time. The advantage of this approach is that you will still receive data when a boat suddenly starts sending data to a different live data endpoint than the one you originally connected to. This can happen if the boat moves physically, or if there are changes in the boat's internet connection. You will need to subscribe to the desired boats on each connection / endpoint separately.

To retrieve all live data endpoints and their WebSocket URLs, use the following GraphQL query:

query {
  streamingGateways(onlyOnline: true) {
    webSocketUrl2
  }
}

The response will look like:

{
  "data": {
    "streamingGateways": [
      {
        "websocketUrl2": "wss://live-ap-southeast-2.prod.sailnjord.com:5002/"
      },
      {
        "websocketUrl2": "wss://live-eu-central-1.prod.sailnjord.com:5002/"
      },
      {
        "websocketUrl2": "wss://live-us-east-1.prod.sailnjord.com:5002/"
      }
    ]
  }
}

WebSocket URLs for each endpoint are designed to be stable, and we add or remove endpoints very infrequently.

Heartbeat - Ping/Pong

After connecting to the WebSocket URL, it is the client's responsibility to send a ping message once at least every 15 minutes. A shorter interval like 1 minute is recommended. If the server doesn't receive a ping message within that time interval, it may terminate the WebSocket connection.

A ping message is a JSON-formatted object like the following, where ping and requestId values are arbitrarily chosen by the client.

{ "requestId": "uuid-xxx-yyy-zzz", "ping": 1 }

The server will always respond with a pong message immediately, repeating both values. If you don't receive a pong message, consider reconnecting.

{ "requestId": "uuid-xxx-yyy-zzz", "pong": 1 }

Receiving Live Data

Send a subscription request, a JSON-formatted object like the following. The requestId value is optional and is arbitrarily chosen by the client, for authorization, insert a valid API token.

You can subscribe to:

  • one or more boats using the boatKeys field (array of boat keys), and/or
  • one or more wind stations using the windStationKeys field (array of wind station keys), and/or
  • one or more data sources using the dataSourceKeys field (array of data source keys)
{
  "requestId": "uuid-xxx-yyy-zzz",
  "subscriptionRequest": {
    "authorization": "...",
    "boatKeys": ["Boat_123", "Boat_456"]
  }
}

If the subscription was successful, the server will respond with:

{
  "requestId": "uuid-xxx-yyy-zzz",
  "subscriptionResponse": {
    "boatKeys": ["Boat_123", "Boat_456"],
    "subscribed": true
  }
}

Else, the response will look like this:

{
  "requestId": "uuid-xxx-yyy-zzz",
  "subscriptionResponse": {
    "boatKeys": ["Boat_123", "Boat_456"],
    "subscribed": false,
    "error": "Permission denied"
  }
}

Whenever live data is received from the boat, and until unsubscribed, the server will respond with a data message like this (sourceTimestamp is the time in UNIX epoch/milliseconds at which the the data originated at the source, and gatewayTimestamp is the timestamp when it was received by the Njord live data endpoint):

{
  "boatKey": "Boat_123",
  "sourceTimestamp": 1738866164000,
  "gatewayTimestamp": 1738866164100,
  "records": {
    "BoatSpeed": 8.2,
    "Heading": 270.0
  }
}

To unsubscribe, send a request like:

{
  "requestId": "uuid-xxx-yyy-zzz",
  "unsubscribeRequest": {
    "boatKeys": ["Boat_123", "Boat_456"]
  }
}

Sending Live Data

Sending live data to a live data endpoint does not use the Live Data API, as application-specific protocols are being used (NMEA 0183 and Expedition format via UDP, Igtimi data via their own protocol).

If you are interested in sending live data using a WebSocket connection in addition to receiving it via a WebSocket connection as described above, contact us.