webhooks
Subscribe to events, fire test deliveries, and rotate signing secrets.
rogeriq webhooks
bashrogeriq webhooks listrogeriq webhooks get wh_xxx
bashrogeriq webhooks create \ --url https://example.com/rogeriq-hook \ --events 'conversation.*,message.created'
Returns the webhook record with the secret populated. Store the secret — it is not retrievable later.
bashrogeriq webhooks update wh_xxx --status disabledrogeriq webhooks update wh_xxx --url https://new-url/hook --events '*'
bashrogeriq webhooks test wh_xxx
Fires a webhook.test event immediately. Returns delivery status,
HTTP status code, and duration. Test events skip the long-tail retry
workflow.
bashrogeriq webhooks deliveries wh_xxx
Last 50 delivery attempts with status code, duration, attempt number, and status (delivered / failed).
bashrogeriq webhooks rotate-secret wh_xxx
Returns a new secret. The old secret stops working immediately, so update your receiver first.
bashrogeriq webhooks delete wh_xxx
Events
| Event | Fired when |
|---|---|
conversation.created | A new conversation is opened |
conversation.updated | Status, priority, assignee, tags, or subject change |
conversation.resolved | Conversation transitions to resolved |
message.created | New customer / agent / AI message posted |
contact.created | New contact created (via API, widget, or form) |
contact.updated | Existing contact fields changed |
agent.escalated | AI agent escalates to a human |
agent.action_executed | Agent performs an automation action |
form.submitted | A public form receives a submission |
webhook.test | Sent by webhooks test |
Wildcards supported: * (all) and conversation.* (prefix).
Delivery semantics
Inline retries: 1s, 5s, 30s on transient failure (5xx, 408, 425, 429, network error). Permanent 4xx (except 408/425/429) bails out immediately.
Long-tail retries: a Cloudflare Workflow re-attempts at 1m, 5m, 30m, 2h, 12h. The workflow re-fetches the webhook row each time, so disabling / rotating mid-retry behaves correctly.
After 10 consecutive failures the webhook is auto-disabled.
Verifying signatures
Use @rogeriq/sdk for verifyWebhookSignature. Works
in Node, Cloudflare Workers, Deno, browsers — uses the Web Crypto API.
Or verify manually:
tsimport crypto from "node:crypto";const signature = req.headers["x-rogeriq-signature"]; // "sha256=..."const expected = "sha256=" + crypto .createHmac("sha256", process.env.WEBHOOK_SECRET!) .update(rawBody) .digest("hex");if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return new Response("invalid signature", { status: 401 });}
Headers on every delivery: X-RogerIQ-Event, X-RogerIQ-Delivery,
X-RogerIQ-Signature, X-RogerIQ-Timestamp, X-RogerIQ-Attempt.