CRM handoff
Create or update a CRM conversation when a customer sends a new WhatsApp message.
Practical webhook receiver examples and use cases for CRM, delivery tracking, and template operations.
Practical webhook receiver examples and use cases for CRM, delivery tracking, and template operations.
These examples show how teams usually connect Whats91 Webhooks v2 to application workflows after creating a destination.
Create or update a CRM conversation when a customer sends a new WhatsApp message.
Update order, invoice, or campaign timelines when Whats91 receives message status events.
Notify operations teams when a template is approved, rejected, paused, or needs review.
This receiver validates the custom verification header, parses the event, shows how to respond with 200 quickly, and then routes the work asynchronously.
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.raw({ type: 'application/json' }));
const signingSecret = process.env.WHATS91_WEBHOOK_SIGNING_SECRET;
const verificationToken = process.env.WHATS91_WEBHOOK_VERIFICATION_TOKEN;
function verifySignature(rawBody, signature) {
if (!signingSecret || !signature) return false;
const expected = crypto
.createHmac('sha256', signingSecret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
app.post('/webhooks/whats91', async (req, res) => {
const customToken = req.header('X-CRM-Webhook-Token');
if (verificationToken && customToken !== verificationToken) {
return res.sendStatus(401);
}
const signature = req.header('X-Whats91-Signature');
if (!verifySignature(req.body, signature)) {
return res.sendStatus(401);
}
const payload = JSON.parse(req.body.toString('utf8'));
res.sendStatus(200);
queueWebhookWork(payload);
});Keep the request handler fast. Acknowledge the webhook first, then process CRM writes, notifications, and analytics updates in a queue or background job.
async function handleWebhook(payload) {
if (payload.event !== 'message.inbound.text') return;
await crm.conversations.upsert({
phone: payload.data.from,
source: 'whats91',
lastMessage: payload.data.text,
externalMessageId: payload.data.messageId,
receivedAt: payload.data.timestamp,
});
}async function syncDeliveryStatus(payload) {
if (!payload.event.startsWith('message.status.')) return;
await messageReports.updateByMetaMessageId(payload.data.messageId, {
status: payload.data.status,
recipient: payload.data.recipient,
updatedAt: payload.data.timestamp,
});
}async function notifyTemplateReview(payload) {
if (payload.event !== 'template.status_update') return;
await notifications.send({
channel: 'template-ops',
title: 'Template status changed',
message: payload.data.templateName + ' is now ' + payload.data.status,
});
}Create and manage Whats91 Webhooks v2 event destinations with the canonical public API route.
Webhook management requests, responses, and event payload samples for common Whats91 webhook flows.
Send Whats91-specific free-form chat text messages inside the customer service window.
Retrieve the latest status and lifecycle events for one message.