Skip to content

Guides

Webhooks

Get an HMAC-signed callback the moment an ETA moves or a box is discharged, instead of polling.

Polling is fine for a first integration, but it wastes calls and adds lag. TrackingMCP fires a webhook the instant something changes, so your systems hear about a delay when we do.

What fires

A webhook is sent when a tracked container changes in a way worth acting on:

  • an ETA moves,
  • a box is discharged,
  • a hold or exception appears,
  • a demurrage free-time clock crosses a threshold.

The payload

Each delivery is a JSON body with the event and the container it belongs to.

{
  "event": "eta.changed",
  "container": {
    "id": "ctr_9Fk2mQ",
    "reference": "MEDU1234562",
    "eta": "2026-07-05",
    "eta_basis": "predicted",
    "previous_eta": "2026-07-03"
  },
  "sent_at": "2026-08-04T09:12:00Z"
}

Verifying the signature

Every delivery is signed with HMAC so you can trust it came from us and was not altered. The signature rides in a header. Recompute it over the raw request body with your signing secret and compare.

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, signature, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature);
  return a.length === b.length && timingSafeEqual(a, b);
}

Verify against the raw bytes, before any JSON parsing reserialises them. A mismatch means you reject the delivery.

Responding

Return 2xx quickly. Do the real work asynchronously, so a slow handler never blocks or times out a delivery. If you return an error or time out, we retry with backoff.