Webhooks▾

Webhooks

How Sendport delivers inbound messages, delivery receipts and template review results to your server.

Everything that happens asynchronously reaches you as a webhook: a customer replies, a message is delivered or read, a template clears review, a number's quality rating moves. Polling the API for these is the wrong shape — subscribe instead.

The envelope

POST body
{
  "id": "evt_01JZQ6F5H7K9M1P3R5T7V9XZBD",
  "object": "event",
  "type": "message.received",
  "created_at": "2026-09-06T09:41:02.114Z",
  "api_version": "2026-09-01",
  "data": { }
}
  • id is stable across retries — use it to deduplicate.
  • type is the event name. New types are added over time; ignore what you do not handle.
  • data holds the resource, in the same shape the REST API returns it.

Responding

Answer 2xx within 5 seconds. Anything else — a timeout, a 4xx, a 5xx — is a failure and the event is retried. Do the work asynchronously: acknowledge first, enqueue second.

Node
app.post("/hooks/sendport", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["sendport-signature"])) {
    return res.status(400).send("bad signature");
  }

  // Acknowledge immediately, then process off the request path.
  res.sendStatus(200);
  queue.push(JSON.parse(req.body.toString()));
});

Event catalogue

EventFires when
message.receivedA contact sends you a message
message.sentWhatsApp accepted an outbound message
message.deliveredIt reached the recipient's device
message.readThe recipient opened it
message.failedDelivery failed permanently
template.status_updatedMeta approved, rejected or paused a template
template.quality_updatedA template's quality rating moved
number.quality_updatedA number's quality rating or messaging tier moved
conversation.assignedA thread was assigned to an agent