Webhooks

Webhooks are automated messages that get sent over HTTP when a certain condition is met. Using webhooks allows you to automate processes and receive notifications automatically, without having to check manually.

Use webhooks when you need:

  • real-time one way communication, from our API to your webhook destination URL
  • a non-constant connection between two systems
  • to respond immediately to an event from a SaaS application that supports webhooks
  • to push updates to your webhook destination URL

With webhooks, the API and your server interact in the following way:

Webhook
API
Server
Application

What can you use webhooks for?

You can subscribe devices via the organizations/{orgId}/webhooks request to a partner's hosted webhook destination URL.

After a webhook destination URL is configured, a subscription is active and the Surfsight API sends messages containing GPS, events, or alarms metadata. This metadata is actionable in various ways, depending on the desired application integration.

Note

There can be up to three webhook destination URLs for each webhook type per device.

Example webhook data:

  • Alarm notifications will send data in real-time to the webhook destination URL:
Copy
Copied
{
    "type": "alarms",
    "data": {
      "id": 2522880,
      "imei": "868444050007385",
      "name": "7385d",
      "organizationId": 9,
      "organizationName": "Marketing",
      "details": "",
      "alarmDefinitionCode": "124",
      "createdAt": "2023-03-07T14:32:56.000Z",
      "alarmDefinitionId": 7,
      "alarmDefinition": {
        "id": 7,
        "severity": 50,
        "hierarchy": 80,
        "code": "124",
        "name": "Driver camera recording failure",
        "recommendation": "Check driver recording - the camera may not be recording the driver",
        "createdAt": "2021-03-17T11:27:04.000Z"
   }
  }
}
  • Event notifications will send data in real-time to the webhook destination URL:
Copy
Copied
{
    "type": "event",
    "data": {
        "id": 7306791,
        "serialNumber": "357660101039543",
        "eventType": "cell_phone_use",
        "time": 1634797394,
        "lat": 32.1763837,
        "lon": 34.92067202,
        "alt": 54.01348876953125,
        "speed": 32.580000686645505,
        "other": "",
        "files": [
            {
                "cameraId": 1,
                "file": 1634797394,
                "fileType": "video"
            },
            {
                "cameraId": 2,
                "file": 1634797394,
                "fileType": "video"
            }
        ]
    }
}
  • GPS data is sent

    • for the AI-12: in five-minute batches. The data contains the GPS coordinates that were collected in a frequency of five-second GPS sampling. The latitude and longitude parameters are returned to the 8th decimal point.
    • for the AI-14: every five seconds, as the GPS coordinates are collected. The latitude and longitude parameters are returned to the 15th decimal point.
Copy
Copied
{
    "type": "gps",
    "data": [
        {
            "id": 284785697,
            "serialNumber": "357660101039543",
            "time": 1634716391,
            "lat": 32.16421841,
            "lon": 34.90618128,
            "alt": 63.70391845703125,
            "speed": 7.340000152587891,
            "accuracy": 4.288000106811523
        },
        {
            "id": 284785698,
            "serialNumber": "357660101039543",
            "time": 1634716396,
            "lat": 32.16392719,
            "lon": 34.90603431,
            "alt": 63.2786865234375,
            "speed": 10.109999656677246,
            "accuracy": 4.288000106811523
        },        {
            "id": 284785715,
            "serialNumber": "357660101039543",
            "time": 1634716401,
            "lat": 32.16427726,
            "lon": 34.9046395,
            "alt": 64.57598876953125,
            "speed": 1.7200000286102295,
            "accuracy": 1.2160000801086426
        }
    ]
}

How do we ensure webhooks delivery?

When a webhook is delivered successfully, the webhook destination URL returns a 200, 201, or 202 success code.

If there is an error when a webhook is sent and the delivery fails, the webhook destination URL returns an error code of 400 and up. If the webhook destination URL does not respond at all within thirty seconds, we also consider this a failed delivery.

After a failed delivery, we send the webhook again up to six times, after:

  1. 25 seconds
  2. 2 minutes and 2 seconds
  3. 10 minutes and 24 seconds
  4. 52 minutes
  5. 4 hours and 20 minutes
  6. 21 hours and 42 minutes

Webhook retries are sent with the following headers:

  • X-Chain-Id = UUIDv4
  • X-Attempt-Number = int >= 1

The chain ID is the unique identifier of the webhook, and is the same for the original webhook and all retries. The attempt number indicates what delivery attempt is being sent. 1 is the original webhook delivery attempt, and 2 through 7 are the retries.

If there are 50 failed attempts to a specific webhook destination URL in one day, the Surfsight API stops sending retry attempts to that URL for 24 hours.

How are our webhooks secured?

Webhooks are secured through anonymity - every user gets a unique, random URL to which webhook messages are sent.

For extra security, all webhook messages sent by the Surfsight API to your application contain an additional header attribute: X-Surfsight-Signature. The signature is created using:

  • the destination URL for the webhook (webhookUrl)
  • the ssoSecret of your organization. This can be retrieved by using a partner token in the GET /organizations/{orgId} call (ssoSecret)
  • the webhook message (webhookResponse - type and data)

The signature should appear similar to: 29c4198c5e3da799887deaf0b0450bac8880efc0769cb79b97138ce9888a4308c7211415879152fdc4a14933c77cd4d531e71a29008214360ce340ccf49b87c8

To validate the signature, recreate it and compare it to the X-Surfsight-Signature in the header using the following:

const crypto = require('crypto);
const ssoSecret = "{ssoSecret}";
const webhookUrl = "{webhookUrl}";
const xSurfsightSignature = "{xSurfsightSignature}";
const webhookResponse = {
    "type": "{type}"
    "data": {
            {data}
            }
    }
signatureValidation = crypto.createHmac('sha512', ssoSecret).update(JSON.stringify(webhookResponse) + webhookUrl).digest('hex');
if(signatureValidation == xSurfsightSignature){
console.log("Your webhook signature is validated!")
}