Live Chat Webhooks
Webhooks let onWebChat push events to your own server in real time. Whenever something happens in a chat: a new conversation starts, a message is sent, a chat is closed, rated, or an offline message is left, we send an HTTP POST with a JSON body to a URL you choose.
This is the easiest way to sync chat transcripts into your CRM or CMS, trigger follow-up emails, build custom reports, or notify another system, with no polling required.
Webhooks are available on all paid plans. Each delivery is signed so you can verify it really came from onWebChat.
POST https://your-server.com/onwebchat-webhook
Content-Type: application/json
X-OWC-Event: chat.closed
X-OWC-Delivery: 9381
X-OWC-Signature: sha256=4f1c...c2a9
{ "event": "chat.closed", "siteid": 1234, ... }
Setting Up Webhooks
Open your dashboard and go to Settings → Webhooks. Click "Add endpoint", paste the URL that should receive events, choose which events you want (or select "All events"), and save.
When you create an endpoint we generate a signing secret for it. You will use this secret to verify incoming requests (see Verifying Signatures below). You can regenerate the secret at any time.
You can add multiple endpoints per website and review recent deliveries, including the HTTP status, number of attempts and any error, directly in the dashboard.
/* Dashboard → Settings → Webhooks */
URL : https://your-server.com/onwebchat-webhook
Events : chat.closed, message.created
Secret : whsec_3f9a... (used to verify requests)
Status : Enabled
Event Types
Subscribe to any combination of the events below. Each message is tagged with an "author" of visitor, agent, ai or trigger, so the same message.created event covers conversations handled by your team and by the AI chatbot.
| Event | Sent when |
|---|---|
chat.created | A new chat (dialog) is started by a visitor, a trigger, the AI chatbot, or an agent. |
chat.assigned | An agent takes ownership of a chat: picks it up, takes over from the AI bot, or accepts a transfer. |
message.created | A new message is sent in a chat. Includes messages from the visitor, an agent, and the AI chatbot. |
chat.closed | A chat ends. The payload includes the full transcript, visitor details and labels. |
chat.rated | A visitor rates a chat. |
offline_message.created | A visitor submits the offline / contact form while no agent is available. |
visitor.updated | An agent updates the visitor's name, email, phone or notes from the chat dashboard. |
visitor.banned | An agent blocks a visitor from the chat dashboard. |
visitor.unbanned | An agent unblocks a previously blocked visitor from the chat dashboard. |
Payload Format
Every webhook is a JSON object with the same envelope: the event name, your siteid, an ISO-8601 timestamp, and a data object whose shape depends on the event.
The example shows a chat.closed payload, which carries the whole conversation. Smaller events such as message.created or chat.rated include just the relevant fields.
{
"event": "chat.closed",
"siteid": 1234,
"created_at": "2026-06-22T07:40:52.322Z",
"data": {
"chat_id": 1206836,
"started_at": "22-06-2026 10:40",
"closed_at": "2026-06-22T07:40:52.322Z",
"visitor": {
"name": "Sarah Chen",
"email": "sarah@example.com",
"phone": "",
"country": "United States",
"os": "Windows 10",
"browser": "Chrome 149.0"
},
"agents": ["Alex"],
"labels": [{ "name": "sales", "color": "#4caf50" }],
"messages": [
{ "author": "visitor", "text": "pricing info please", "time": "10:40" },
{ "author": "ai", "text": "Here is a quick overview...", "time": "10:40" }
]
}
}
Verifying Signatures
Every request includes an X-OWC-Signature header containing an HMAC-SHA256 hash of the exact raw request body, computed with your endpoint's signing secret.
To verify a request, compute the HMAC-SHA256 of the raw body using your secret and compare it to the header value (the part after "sha256="). Use a constant-time comparison and always hash the raw body, not a re-serialized version.
You also receive X-OWC-Event (the event name) and X-OWC-Delivery (a unique delivery id you can use for idempotency / de-duplication).
// Node.js / Express
const crypto = require('crypto');
app.post('/onwebchat-webhook',
express.raw({ type: '*/*' }), (req, res) => {
const secret = 'whsec_your_secret';
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(req.body) // raw Buffer
.digest('hex');
const got = req.headers['x-owc-signature'] || '';
// constant-time compare; guard length first (timingSafeEqual throws on mismatch)
const a = Buffer.from(got), b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return res.status(401).end();
const payload = JSON.parse(req.body.toString());
// ... handle payload.event ...
res.sendStatus(200);
});
Verifying in PHP
The same check in PHP: read the raw request body, recompute the HMAC with your secret, and compare with hash_equals().
<?php
$secret = 'whsec_your_secret';
$payload = file_get_contents('php://input');
$got = $_SERVER['HTTP_X_OWC_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $got)) {
http_response_code(401);
exit;
}
$event = json_decode($payload, true);
// ... handle $event['event'] ...
http_response_code(200);
Retries & Auto-disable
Your endpoint should respond with a 2xx status as quickly as possible. Any non-2xx response, a timeout, or a connection error is treated as a failure.
Failed deliveries are retried with an increasing delay: after 1 minute, 5 minutes, 20 minutes, 1 hour and 2 hours.
If an endpoint keeps failing (5 consecutive failures), it is automatically disabled and the site owner is notified. Re-enable it from the dashboard once the issue is fixed. Returning HTTP 410 disables the endpoint immediately.
Attempt 1 → immediately
Attempt 2 → after 1 minute
Attempt 3 → after 5 minutes
Attempt 4 → after 20 minutes
Attempt 5 → after 1 hour
Attempt 6 → after 2 hours
5 failures in a row → endpoint disabled
Best Practices
- Always verify the X-OWC-Signature before trusting a payload.
- Respond 2xx fast, then do heavy work asynchronously (queue it) so you do not time out.
- Use X-OWC-Delivery to de-duplicate, because the same delivery may be retried after a transient failure.
- Serve your endpoint over HTTPS.
- Ignore unknown event types so new events we add later do not break your integration.
Ready to start? See plans or open Settings → Webhooks in your dashboard.