Skip to content

Webhooks

CloudWA receives webhooks from Meta’s WhatsApp Business API and processes them automatically. You can also configure your own webhook endpoints to receive notifications about message events.

CloudWA exposes webhook endpoints that you configure in your Meta App settings:

Terminal window
GET /api/webhook

Meta sends a verification request when setting up webhooks:

ParameterDescription
hub.modeAlways “subscribe”
hub.verify_tokenYour configured verify token
hub.challengeChallenge string to return
Terminal window
POST /api/webhook

All WhatsApp events are sent to this endpoint.

Triggered when a new message is received.

{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "1234567890",
"phone_number_id": "PHONE_NUMBER_ID"
},
"contacts": [
{
"profile": {
"name": "John Doe"
},
"wa_id": "1234567890"
}
],
"messages": [
{
"from": "1234567890",
"id": "wamid.xxx",
"timestamp": "1234567890",
"type": "text",
"text": {
"body": "Hello!"
}
}
]
},
"field": "messages"
}
]
}
]
}

Triggered when a message status changes.

{
"object": "whatsapp_business_account",
"entry": [
{
"changes": [
{
"value": {
"statuses": [
{
"id": "wamid.xxx",
"status": "delivered",
"timestamp": "1234567890",
"recipient_id": "1234567890"
}
]
},
"field": "messages"
}
]
}
]
}
StatusDescription
sentMessage sent to WhatsApp servers
deliveredMessage delivered to recipient
readMessage read by recipient
failedMessage failed to deliver

For real-time updates in your frontend, connect to the WebSocket endpoint. Note that authentication must be performed after connection setup by sending an auth message within 5 seconds:

const ws = new WebSocket('wss://dashboard.cloudwa.net/ws');
ws.onopen = () => {
// Must authenticate within 5 seconds of connection
ws.send(JSON.stringify({
type: 'auth',
payload: {
token: 'YOUR_JWT_TOKEN'
}
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Event:', data.type, data.payload);
};
EventDescription
message:newNew message received
message:statusMessage status updated
contact:newNew contact created
contact:updatedContact information updated
{
"type": "message:new",
"payload": {
"id": "uuid",
"contact_id": "uuid",
"direction": "incoming",
"type": "text",
"content": {
"text": "Hello!"
},
"timestamp": "2024-01-01T12:00:00Z"
}
}

Always verify webhook requests are from Meta:

  1. Check the X-Hub-Signature-256 header
  2. Compute HMAC-SHA256 of the request body using your app secret
  3. Compare with the signature in the header

CloudWA handles this verification automatically.

Meta may send webhooks at high volumes during campaigns. CloudWA:

  • Processes webhooks asynchronously
  • Queues events in Redis for processing
  • Handles duplicate events gracefully

Manage webhook subscriptions to receive CloudWA events at your own external endpoints.

Get all configured webhooks for your organization.

Terminal window
GET /api/webhooks
ParameterTypeDescription
searchstringFilter by name or URL (case-insensitive)
pageintegerPage number for pagination (default: 1)
limitintegerItems per page (default: 50)
{
"status": "success",
"data": {
"webhooks": [
{
"id": "uuid",
"name": "My Endpoint",
"url": "https://api.my-app.com/webhooks/whatsapp",
"events": ["message:incoming", "contact:created"],
"headers": {
"Authorization": "Bearer token123"
},
"is_active": true,
"has_secret": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
],
"available_events": [
{
"value": "message:incoming",
"label": "Message Incoming",
"description": "When a new message is received from a contact"
},
{
"value": "message:sent",
"label": "Message Sent",
"description": "When an agent sends a message"
},
{
"value": "contact:created",
"label": "Contact Created",
"description": "When a new contact is created"
},
{
"value": "transfer:created",
"label": "Transfer Created",
"description": "When a transfer to human agent is requested"
},
{
"value": "transfer:assigned",
"label": "Transfer Assigned",
"description": "When a transfer is assigned to an agent"
},
{
"value": "transfer:resumed",
"label": "Transfer Resumed",
"description": "When chatbot is resumed (transfer closed)"
}
],
"total": 1,
"page": 1,
"limit": 50
}
}

Register a new webhook subscription.

Terminal window
POST /api/webhooks
{
"name": "My Endpoint",
"url": "https://api.my-app.com/webhooks/whatsapp",
"events": ["message:incoming", "contact:created"],
"headers": {
"Authorization": "Bearer token123"
},
"secret": "my-hmac-secret-key",
"is_active": true
}
FieldTypeRequiredDescription
namestringYesFriendly name for the webhook
urlstringYesThe URL that will receive the webhook POST payloads
eventsarrayYesList of events to subscribe to (e.g. message:incoming, contact:created)
headersobjectNoCustom HTTP headers sent with the webhook request
secretstringNoHMAC-SHA256 verification secret (auto-generated if omitted)
is_activebooleanNoActive status of the webhook subscription
{
"status": "success",
"data": {
"id": "uuid",
"name": "My Endpoint",
"url": "https://api.my-app.com/webhooks/whatsapp",
"events": ["message:incoming", "contact:created"],
"headers": {
"Authorization": "Bearer token123"
},
"is_active": true,
"has_secret": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
}

Get details of a webhook subscription.

Terminal window
GET /api/webhooks/{id}
ParameterTypeDescription
idstringThe unique UUID of the webhook
{
"status": "success",
"data": {
"id": "uuid",
"name": "My Endpoint",
"url": "https://api.my-app.com/webhooks/whatsapp",
"events": ["message:incoming", "contact:created"],
"headers": {
"Authorization": "Bearer token123"
},
"is_active": true,
"has_secret": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
}

Update an existing webhook subscription.

Terminal window
PUT /api/webhooks/{id}
ParameterTypeDescription
idstringThe unique UUID of the webhook
{
"name": "Updated Endpoint Name",
"is_active": false
}
{
"status": "success",
"data": {
"id": "uuid",
"name": "Updated Endpoint Name",
"url": "https://api.my-app.com/webhooks/whatsapp",
"events": ["message:incoming", "contact:created"],
"headers": {
"Authorization": "Bearer token123"
},
"is_active": false,
"has_secret": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
}

Send a synchronous test event to verify your webhook endpoint is responding correctly.

Terminal window
POST /api/webhooks/{id}/test
ParameterTypeDescription
idstringThe unique UUID of the webhook
{
"status": "success",
"data": {
"message": "Test webhook sent successfully"
}
}

Remove a webhook subscription.

Terminal window
DELETE /api/webhooks/{id}
ParameterTypeDescription
idstringThe unique UUID of the webhook
{
"status": "success",
"data": {
"message": "Webhook deleted successfully"
}
}