BookbagBookbag

Webhooks

Push Bookbag events to your own endpoints in real time. Covers the event catalog, the signed payload format, HMAC-SHA256 signature verification, and delivery behavior.

View as Markdown

Webhooks let Bookbag push events to your own systems the moment they happen. Register a URL, choose which events to subscribe to, and Bookbag POSTs a signed JSON payload to that URL whenever a matching event fires — no polling required.

Manage webhooks in your workspace

Webhooks are configured per workspace by an admin. Each webhook has a URL, a list of subscribed events, and a signing secret. The secret is shown when you create the webhook — store it safely.

Create a webhook

  1. 1
    Add an endpoint URL
    In your workspace integrations, add a webhook with the HTTPS URL Bookbag should POST to.
  2. 2
    Choose events
    Subscribe to specific events, or use the wildcard * to receive everything.
  3. 3
    Save the signing secret
    Bookbag generates a secret (or you can supply one). Use it to verify that incoming requests really came from Bookbag.

Events

Subscribe to the events your integration cares about. Subscribing to * delivers all events.

EventFires when
conversation.repliedThe agent posts a reply in a conversation.
conversation.endedA conversation is closed or resolved.
lead.createdA lead is captured via the collect-leads action.
action.runAn action (custom action, escalation, etc.) executes.
tip

Start narrow — subscribe only to the events you'll act on. You can always widen the subscription later.

Payload format

Every delivery is a POST with a JSON body containing the event name, a data object, and a millisecond timestamp:

POST body
{
  "event": "conversation.replied",
  "data": {
    "conversation_id": "conv_123",
    "agent_id": 42,
    "message": "Your order shipped today."
  },
  "ts": 1733155200000
}

Verifying signatures

Each request includes an X-Bookbag-Signature header so you can confirm it came from Bookbag and wasn't tampered with. The value is sha256= followed by the HMAC-SHA256 of the raw request body, keyed with your webhook secret.

Sign the raw body

Compute the HMAC over the exact bytes you received, before any JSON parsing or re-serialization. Re-stringifying the body can change whitespace and break the signature. Always compare using a constant-time equality check.

import crypto from 'node:crypto';

function verify(rawBody, header, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  const a = Buffer.from(header || '');
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express: use the raw body, not the parsed object.
app.post('/bookbag-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verify(req.body, req.get('X-Bookbag-Signature'), process.env.BOOKBAG_WEBHOOK_SECRET)) {
    return res.status(401).end();
  }
  const payload = JSON.parse(req.body.toString());
  // handle payload.event ...
  res.status(200).end();
});

Delivery behavior

  • Respond 2xx quickly. Acknowledge receipt fast and do heavy work asynchronously so deliveries don't time out.
  • Be idempotent. Design handlers so a duplicate delivery is harmless.
  • HTTPS only. Endpoints must be reachable public HTTPS URLs.
info

For event listeners on the front end (reacting to widget events in the browser) and the deeper developer webhook guide, see the developer docs.

What's next