Sign In

Webhooks

Beamvia POSTs events to your URL as they happen. Respond with any 2xx within 10 seconds.

eventWhen
MESSAGE_CREATEDA message was received or sent
MESSAGE_UPDATEDA message status changed (sent, delivered, read, failed)
CONVERSATION_UPDATEDStatus, handler, priority or tags changed
CONTACT_UPDATEDA contact's profile or identities changed
Payload
{
  "id": "3b0b8f2e-6a1c-4f7e-9d0e-0b1c2d3e4f50",
  "createdAt": "2026-10-20T08:00:00.000Z",
  "workspaceId": "6650f0c2a1b2c3d4e5f60000",
  "event": {
    "type": "MESSAGE_CREATED",
    "message": {
      "id": "6650f0c2a1b2c3d4e5f60718",
      "conversationId": "6650f0c2a1b2c3d4e5f60700",
      "direction": "INBOUND",
      "author": {
        "type": "CONTACT",
        "contactId": "6650f0c2a1b2c3d4e5f60690"
      },
      "content": {
        "type": "TEXT",
        "text": "Is my order shipped?"
      },
      "status": "SENT"
    }
  }
}

Verify the signature

Each delivery carries X-Beamvia-Timestamp and X-Beamvia-Signature. The signature is sha256= + HMAC-SHA256 of timestamp.body with your webhook secret. Reject old timestamps.

Retries

Non-2xx responses and timeouts are retried 5 times with backoff. After 50 consecutive failures the webhook is switched off.

Verify
import crypto from "crypto";

// ** Express: use the raw body, not the parsed JSON
app.post("/beamvia", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.header("X-Beamvia-Timestamp");
  const signature = req.header("X-Beamvia-Signature");
  const expected = "sha256=" + crypto.createHmac("sha256", process.env.BEAMVIA_WEBHOOK_SECRET).update(`${timestamp}.${req.body}`).digest("hex");

  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
  if (!fresh || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) return res.sendStatus(401);

  const { event } = JSON.parse(req.body);
  // ** handle event.type …
  res.sendStatus(200);
});

Create a webhook

Requires the webhook:manage scope. The response contains the signing secret.

Scopewebhook:manage
urlstringrequired
HTTPS URL that receives the events.
eventsstring[]required
Events to deliver, e.g. ["MESSAGE_CREATED"].
POSThttps://www.beamvia.com/api/v1/webhook
Create
curl -X POST "https://www.beamvia.com/api/v1/webhook" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/beamvia",
    "events": [
      "MESSAGE_CREATED",
      "MESSAGE_UPDATED"
    ]
  }'
201 Created
{
  "status": true,
  "message": "OK",
  "data": {
    "webhook": {
      "id": "6650f0c2a1b2c3d4e5f60900",
      "url": "https://example.com/beamvia",
      "secret": "whsec_…",
      "events": [
        "MESSAGE_CREATED",
        "MESSAGE_UPDATED"
      ],
      "isActive": true,
      "failures": 0,
      "delivery": {
        "last": null
      }
    }
  }
}

Delete a webhook

Stops deliveries immediately.

Scopewebhook:manage
DELETEhttps://www.beamvia.com/api/v1/webhook?id=:webhookId
Delete
curl -X DELETE "https://www.beamvia.com/api/v1/webhook?id=6650f0c2a1b2c3d4e5f60900" \
  -H "Authorization: Bearer YOUR_API_KEY"
200 OK
{
  "status": true,
  "message": "Deleted",
  "data": null
}