Outbound webhooks
Create an outbound webhook in your workspace to receive events at your own HTTPS endpoint. Each webhook subscribes to one or more events, is scoped to a channel or the whole workspace, and is signed with a secret shown once at creation.
Payload
Section titled “Payload”A message.created delivery looks like this (fields under conversation and
message.direction are present for support channels):
{ "event": "message.created", "channel": { "id": "chn_…", "name": "Website", "kind": "support" }, "message": { "id": "msg_…", "content_type": "text", "created_at": "2026-07-13T12:00:00+00:00", "direction": "visitor" }, "conversation": { "id": "cnv_…", "external_reference": "order-1234", "external_user_id": "user-42" }}direction is visitor, agent, or system.
Message content (opt-in)
Section titled “Message content (opt-in)”By default the payload carries no message text — only metadata. If the webhook opts into content, the payload adds:
"message": { "content": "How can I help?", "content_language": "en"}The content is the completed translation in the webhook’s preferred
content_language when it’s ready, otherwise the original text — so an
integration receives every crossing message already in its language.
Verify the signature
Section titled “Verify the signature”Every delivery carries:
X-Rosetta-Signature: t=<unix>,v1=<hmac_sha256("<t>.<body>", secret)>Recompute the HMAC over "<t>.<rawBody>" with your webhook secret and compare
in constant time. Reject deliveries whose timestamp is too old (a 5-minute
window is a good default) to guard against replays.
// Node.js (Express raw body)import crypto from 'node:crypto';
function verify(rawBody, header, secret) { const parts = Object.fromEntries( header.split(',').map((kv) => kv.split('=')), ); const t = parts.t; if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; const expected = crypto .createHmac('sha256', secret) .update(`${t}.${rawBody}`) .digest('hex'); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));}Delivery log & retry
Section titled “Delivery log & retry”Every delivery is recorded — status, response code, attempts — so you can debug integrations. Failed deliveries are retried with backoff, and you can manually retry a delivery from the webhook’s delivery log in workspace settings.