Working with Webhooks

Have Surfact push readings to your systems as they arrive, instead of polling the API.

Webhooks

Surfact can push data to your systems the moment it arrives. Instead of polling GET /variables/{id}/values/ on a timer, you give us an endpoint and we POST each new reading to it — the pattern we recommend for integration partners feeding a fleet management or transport management system.

Two ways to receive data

You wantUse
Every reading from your devices as it lands — a live feed into your own systemA streaming webhook, set up by the Surfact team (this page)
Only readings that cross a threshold — an alert, not a feedA web-hook action on an event, which you configure yourself

The rest of this page covers streaming webhooks.

How it works

Whenever one of your devices reports, Surfact sends an HTTP POST to your endpoint. Delivery is per variable: a tracker that reports temperature, humidity and battery in one packet produces three requests, one for each reading. You receive every variable the device reports — filter for the ones you need when you receive them.

Your endpoint should respond with a 2xx to acknowledge receipt.

Example: temperature into a transport management system

A reefer trailer reports a new temperature sample. Your TMS receives:

{
  "device": {
    "name": "Reefer Trailer 21",
    "id": "6a7c777c1da2efbc51f62ba9",
    "label": "reefer-trailer-21",
    "properties": {
      "device-serial": "18e-9e1-242",
      "destination": "Bergen Cold Hub",
      "max-temp-threshold": "-15",
      "min-temp-threshold": "-22"
    },
    "data": {
      "temperature": {
        "value": "-18.4",
        "context": {},
        "timestamp": "1788377538000"
      }
    }
  }
}
FieldDescription
device.labelThe device's API label — the same key you use on /devices/~{label}
device.propertiesThe device's properties as they stand when the reading arrives. device-serial is the serial printed on the tracker, usually the key you already hold in your TMS
device.dataExactly one key — the label of the variable that just reported: temperature, humidity, battery, position, …
data.<label>.valueThe reading, as a string — parse it as a number on your side
data.<label>.timestampWhen the device took the sample, POSIX milliseconds, as a string. Order on this — a device that was out of coverage delivers its backlog late
data.<label>.contextExtra keys on the reading. For position this carries lat and lng; see Device Position

Match on device.properties["device-serial"], read the single key under device.data, and write its value against its timestamp. That is a live temperature trace per shipment with no polling.

❗️

Numbers arrive as strings

value and timestamp are JSON strings, not numbers. A typed deserialiser expecting a float will reject the payload — coerce them explicitly.

📘

The payload shape is fixed

Every webhook delivers this structure. If your system needs a different one, transform it on receipt.

Limits

  • 4 requests per second per webhook. If your devices produce more than four readings in the same second, the excess is dropped, not queued.
  • Every variable fires. A webhook is scoped to devices, not variables — when a device in scope reports, you receive one request for each variable in that packet, and there is no way to subscribe to only some of them. An Emma tracker typically reports ten or more variables per packet, so two trackers reporting in the same second already exceed the limit. Tell us the size of the fleet and what you need the data for, and we will advise on how to scope the webhook — for example, one webhook per device group — so it stays within the limit. Filter to the variables you need on your side.
  • Don't treat the webhook as your only copy. Every reading also remains available through the API, so a periodic reconciliation pull is good practice for anything you depend on — it covers a dropped request or a period when your endpoint was unreachable.

Setting one up

Webhooks are configured by the Surfact team. Send [email protected]:

  1. Endpoint URL — HTTPS, reachable from the public internet.
  2. HTTP method — normally POST.
  3. Headers we should send — typically an Authorization header or API key your endpoint expects.
  4. Which devices — all of your devices, or a named organization or device group. This is the only scoping available; all variables on those devices will be delivered.

We configure it, send a test reading to your endpoint with you on the line, and switch it live once you confirm it landed.


Did this page help you?