Overview
Webhooks allow you to receive real-time HTTP notifications when events occur in your Chatwoot account. Use webhooks to integrate Chatwoot with external systems and automate workflows.
List All Webhooks
Retrieve all webhooks configured in your account.
GET /api/v1/accounts/{account_id}/webhooks
Path Parameters
Response
URL where webhook events will be sent
Array of event types this webhook is subscribed to
Inbox ID (if webhook is inbox-specific)
Example Request
curl -X GET https://app.chatwoot.com/api/v1/accounts/1/webhooks \
-H "api_access_token: YOUR_ACCESS_TOKEN"
Example Response
[
{
"id": 1,
"url": "https://example.com/webhooks/chatwoot",
"name": "Main Webhook",
"subscriptions": [
"conversation_created",
"conversation_status_changed",
"message_created"
],
"account_id": 1,
"inbox_id": null
},
{
"id": 2,
"url": "https://example.com/webhooks/support",
"name": "Support Inbox Webhook",
"subscriptions": [
"message_created",
"message_updated"
],
"account_id": 1,
"inbox_id": 1
}
]
Create Webhook
Create a new webhook to receive event notifications.
POST /api/v1/accounts/{account_id}/webhooks
Path Parameters
Request Body
URL endpoint to receive webhook events (must be HTTPS)
Descriptive name for the webhook
Array of event types to subscribe to
Inbox ID (optional, for inbox-specific webhooks)
Example Request
curl -X POST https://app.chatwoot.com/api/v1/accounts/1/webhooks \
-H "api_access_token: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhook": {
"url": "https://example.com/webhooks/chatwoot",
"name": "Production Webhook",
"subscriptions": [
"conversation_created",
"conversation_status_changed",
"conversation_updated",
"message_created",
"message_updated",
"contact_created",
"contact_updated"
]
}
}'
Example Response
{
"id": 3,
"url": "https://example.com/webhooks/chatwoot",
"name": "Production Webhook",
"subscriptions": [
"conversation_created",
"conversation_status_changed",
"conversation_updated",
"message_created",
"message_updated",
"contact_created",
"contact_updated"
],
"account_id": 1,
"inbox_id": null
}
Update Webhook
Update an existing webhook configuration.
PATCH /api/v1/accounts/{account_id}/webhooks/{id}
Path Parameters
The ID of the webhook to update
Request Body
Accepts the same parameters as Create Webhook.
Example Request
curl -X PATCH https://app.chatwoot.com/api/v1/accounts/1/webhooks/3 \
-H "api_access_token: YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhook": {
"name": "Updated Webhook Name",
"subscriptions": [
"conversation_created",
"message_created"
]
}
}'
Delete Webhook
Delete a webhook from your account.
DELETE /api/v1/accounts/{account_id}/webhooks/{id}
Path Parameters
The ID of the webhook to delete
Example Request
curl -X DELETE https://app.chatwoot.com/api/v1/accounts/1/webhooks/3 \
-H "api_access_token: YOUR_ACCESS_TOKEN"
Response
Returns 200 OK with no body.
Webhook Events
Available webhook event types:
Conversation Events
Message Events
Webhook Payload
Webhook events are sent as HTTP POST requests to your configured URL.
Content-Type: application/json
User-Agent: Chatwoot
Payload Structure
{
"event": "message_created",
"id": 12345,
"account": {
"id": 1,
"name": "Acme Corporation"
},
"inbox": {
"id": 1,
"name": "Website Widget"
},
"conversation": {
"id": 1,
"display_id": 1,
"status": "open",
"priority": "high",
"assignee": {
"id": 1,
"name": "John Doe",
"email": "[email protected]"
},
"contact": {
"id": 1,
"name": "Customer Name",
"email": "[email protected]"
}
},
"message": {
"id": 100,
"content": "Hello, I need help with my order",
"message_type": "incoming",
"content_type": "text",
"created_at": 1704067200,
"sender": {
"id": 1,
"name": "Customer Name",
"type": "Contact"
}
}
}
Event-Specific Payloads
conversation_created
{
"event": "conversation_created",
"id": 1,
"account": { ... },
"inbox": { ... },
"conversation": { ... }
}
conversation_status_changed
{
"event": "conversation_status_changed",
"id": 1,
"account": { ... },
"conversation": {
"id": 1,
"status": "resolved",
"previous_status": "open"
}
}
message_created
{
"event": "message_created",
"id": 100,
"account": { ... },
"conversation": { ... },
"message": { ... }
}
{
"event": "contact_created",
"id": 1,
"account": { ... },
"contact": {
"id": 1,
"name": "New Contact",
"email": "[email protected]",
"phone_number": "+1234567890"
}
}
Webhook Security
HTTPS Required
Webhook URLs must use HTTPS for security. HTTP URLs will be rejected.
Verify Webhook Signatures
Chatwoot includes a signature in webhook requests that you can verify:
- Extract the signature from the request header
- Compute HMAC-SHA256 of the payload using your webhook secret
- Compare the computed signature with the received signature
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
computed_signature = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, computed_signature)
IP Allowlisting
Consider allowlisting Chatwoot’s IP addresses in your firewall for additional security.
Handling Webhook Events
Best Practices
- Respond Quickly: Return a
200 OK response immediately
- Process Asynchronously: Queue events for background processing
- Handle Duplicates: Use event IDs to detect and skip duplicate events
- Implement Retries: Handle temporary failures gracefully
- Monitor Failures: Track webhook delivery failures
Example Handler (Node.js)
const express = require('express');
const app = express();
app.post('/webhooks/chatwoot', express.json(), (req, res) => {
const event = req.body;
// Respond immediately
res.status(200).send('OK');
// Process event asynchronously
processWebhookEvent(event).catch(err => {
console.error('Webhook processing error:', err);
});
});
async function processWebhookEvent(event) {
switch (event.event) {
case 'message_created':
await handleNewMessage(event.message);
break;
case 'conversation_created':
await handleNewConversation(event.conversation);
break;
// Handle other events...
}
}
Webhook Delivery
Retry Policy
Chatwoot will retry failed webhook deliveries:
- Initial retry after 1 minute
- Subsequent retries with exponential backoff
- Maximum of 3 retry attempts
Timeouts
Webhook requests timeout after 10 seconds. Ensure your endpoint responds quickly.
Failed Deliveries
Webhooks that consistently fail may be automatically disabled. Monitor your webhook endpoint for errors.
Testing Webhooks
Local Development
Use tools like ngrok to expose your local server:
Use the ngrok URL as your webhook URL:
https://abc123.ngrok.io/webhooks/chatwoot
Common Issues
Webhook Not Receiving Events
Troubleshooting:
- Verify URL is correct and accessible
- Check webhook subscriptions include the event type
- Ensure endpoint returns
200 OK quickly
- Check firewall and security settings
Duplicate Events
Solution: Use event IDs to detect and skip duplicates:
const processedEvents = new Set();
function handleWebhook(event) {
if (processedEvents.has(event.id)) {
return; // Skip duplicate
}
processedEvents.add(event.id);
// Process event...
}
Timeout Errors
Solution: Return 200 OK immediately and process events asynchronously.
Error Responses
Webhook Not Found
{
"error": "Webhook not found"
}
Invalid URL
{
"error": "Webhook URL must use HTTPS"
}
Invalid Subscriptions
{
"error": "Invalid subscription event type"
}