WhatsApp Webhook Format Reference β
v1.6.0+Complete technical reference for WhatsApp webhook payloads forwarded by WhatsMarkSaaS to external endpoints like N8N, Zapier, and Make.com.
Overview β
This document provides the complete specification for WhatsApp webhook payloads in N8N format. All webhooks follow a consistent structure regardless of event type.
Audience
This reference is for developers building custom integrations. If you're using N8N, Zapier, or Make.com, see the WhatsApp Webhook Forwarding Guide instead.
Base Payload Structure β
All WhatsApp webhooks follow this standard structure:
interface WhatsAppWebhookPayload {
event: EventObject;
tenant: TenantObject;
data: DataObject;
whatsapp: WhatsAppObject;
metadata: MetadataObject;
}Complete Schema β
{
"event": {
"id": "string", // Format: evt_{timestamp}_{random}
"type": "string", // Event type (see Event Types section)
"timestamp": "string", // ISO 8601 datetime
"version": "string" // Format version (currently "1.0")
},
"tenant": {
"id": number, // Tenant ID
"name": "string" // Tenant/company name
},
"data": {
"resource": {
"type": "string", // Resource type: message, status, account, etc.
"id": "string|null", // Resource identifier (message ID, etc.)
"attributes": object // Resource-specific attributes
},
"relationships": object // Related entities (contact, metadata, etc.)
},
"whatsapp": {
"original_payload": object // Complete original WhatsApp webhook
},
"metadata": {
"source": "whatsapp_webhook_forward",
"environment": "string", // production, staging, etc.
"request_id": "string" // UUID for request tracing
}
}Event Object β
Contains event metadata and identification.
interface EventObject {
id: string; // Unique event identifier
type: string; // Event type (see Event Types)
timestamp: string; // ISO 8601 timestamp
version: string; // Payload format version
}Event ID Format β
evt_{unix_timestamp}_{random_string}
Example: evt_1767263928_7KGQvXqbFFEvent Types β
All possible event types:
type WhatsAppEventType =
// Message Events
| 'whatsapp.message.received'
| 'whatsapp.message.sent'
| 'whatsapp.message.delivered'
| 'whatsapp.message.read'
| 'whatsapp.message.failed'
// Status Events
| 'whatsapp.status.updated'
// Account Events
| 'whatsapp.account.alert'
| 'whatsapp.account.review_updated'
| 'whatsapp.account.updated'
// Business Events
| 'whatsapp.business.capability_updated'
| 'whatsapp.business.status_updated'
// Template Events
| 'whatsapp.template.status_updated'
| 'whatsapp.template.quality_updated'
// Phone Events
| 'whatsapp.phone.quality_updated'
| 'whatsapp.phone.name_updated'
// Other Events
| 'whatsapp.call.received'
| 'whatsapp.flow.event';Tenant Object β
Multi-tenancy context information.
interface TenantObject {
id: number; // Tenant identifier
name: string; // Tenant/company name
}Example:
{
"id": 3,
"name": "Acme Corporation"
}Data Object β
Contains the actual event data and relationships.
interface DataObject {
resource: ResourceObject;
relationships: RelationshipsObject;
}Resource Object β
interface ResourceObject {
type: string; // Resource type
id: string | null; // Resource identifier
attributes: object; // Resource-specific data
}Relationships Object β
Related entities vary by resource type. Common relationships:
interface RelationshipsObject {
contact?: ContactRelationship;
metadata?: MetadataRelationship;
[key: string]: any;
}WhatsApp Object β
Contains the complete original WhatsApp webhook payload.
interface WhatsAppObject {
original_payload: {
object: string;
entry: Array<{
id: string;
changes: Array<{
value: object;
field: string;
}>;
}>;
};
}Metadata Object β
Request tracking and environment information.
interface MetadataObject {
source: 'whatsapp_webhook_forward';
environment: string; // production, staging, development
request_id: string; // UUID for tracing
}Event Type Details β
Message Events β
whatsapp.message.received β
Incoming message from customer.
Payload Example:
{
"event": {
"id": "evt_1767263928_abc123",
"type": "whatsapp.message.received",
"timestamp": "2026-01-01T10:38:48+00:00",
"version": "1.0"
},
"tenant": {
"id": 3,
"name": "Acme Corp"
},
"data": {
"resource": {
"type": "message",
"id": "wamid.HBgMOTE5OTI1MTE5Mjg0FQIAEhgWM0VCMDE1NDRCMTFBMDQ1RTlFM0NFMwA=",
"attributes": {
"message_id": "wamid.HBgMOTE5OTI1MTE5Mjg0FQIAEhgWM0VCMDE1NDRCMTFBMDQ1RTlFM0NFMwA=",
"from": "919876543210",
"timestamp": "1767263926",
"type": "text",
"text": "Hello, I need help!",
"context": null
}
},
"relationships": {
"contact": {
"wa_id": "919876543210",
"name": "John Doe"
},
"metadata": {
"phone_number_id": "339141689277134",
"display_phone_number": "919428735270"
}
}
},
"whatsapp": {
"original_payload": {
/* Full WhatsApp payload */
}
},
"metadata": {
"source": "whatsapp_webhook_forward",
"environment": "production",
"request_id": "595bbcf8-93bf-418b-8209-3343c76ad852"
}
}Message Types:
text- Plain text messageimage- Image with optional captionvideo- Video with optional captionaudio- Audio/voice messagedocument- Document/filelocation- Location coordinatescontacts- Contact cardsticker- Stickerinteractive- Button/list responsesbutton- Quick reply buttonorder- Order message
**Text Message Attributes:
{
message_id: string;
from: string; // Phone number with country code
timestamp: string; // Unix timestamp
type: "text";
text: string; // Message text
context: { // Reply context (if replying)
from: string;
id: string;
} | null;
}Image Message Attributes:
{
message_id: string;
from: string;
timestamp: string;
type: "image";
image: {
id: string; // Media ID
mime_type: string;
sha256: string;
caption?: string;
};
context: object | null;
}Document Message Attributes:
{
message_id: string;
from: string;
timestamp: string;
type: "document";
document: {
id: string;
filename: string;
mime_type: string;
sha256: string;
caption?: string;
};
context: object | null;
}Location Message Attributes:
{
message_id: string;
from: string;
timestamp: string;
type: "location";
location: {
latitude: number;
longitude: number;
name?: string;
address?: string;
};
context: object | null;
}whatsapp.message.sent β
Message sent by your business (echo event).
Payload Structure: Same as message.received but triggered when your business sends a message.
Note: The from field will be your business phone number.
whatsapp.message.delivered β
Message delivered to customer's device.
Payload Example:
{
"event": {
"type": "whatsapp.message.delivered",
"timestamp": "2026-01-01T10:39:00+00:00"
},
"data": {
"resource": {
"type": "status",
"id": "wamid.xxx",
"attributes": {
"status": "delivered",
"timestamp": "1767264000",
"recipient_id": "919876543210",
"conversation": {
"id": "conv_id",
"origin": {
"type": "user_initiated"
}
}
}
}
}
}Status Values:
sent- Message sent from your serverdelivered- Delivered to customer's deviceread- Customer read the messagefailed- Delivery failed
whatsapp.message.read β
Customer read your message (blue checkmarks).
Payload Structure: Similar to message.delivered with status: "read".
whatsapp.message.failed β
Message delivery failed.
Payload Example:
{
"event": {
"type": "whatsapp.message.failed"
},
"data": {
"resource": {
"type": "status",
"attributes": {
"status": "failed",
"timestamp": "1767264000",
"recipient_id": "919876543210",
"errors": [
{
"code": 131047,
"title": "Re-engagement message",
"message": "Re-engagement message is outside the customer service window."
}
]
}
}
}
}Template Events β
whatsapp.template.status_updated β
Message template approval status changed.
Payload Example:
{
"event": {
"type": "whatsapp.template.status_updated"
},
"data": {
"resource": {
"type": "template",
"id": null,
"attributes": {
"event": "APPROVED",
"message_template_id": "1234567890",
"message_template_name": "welcome_message",
"message_template_language": "en",
"reason": null
}
}
}
}Status Values:
APPROVED- Template approved and activeREJECTED- Template rejectedPENDING- Under reviewPAUSED- Template pausedDISABLED- Template disabled
Rejection Reasons: When status is REJECTED, reason field contains explanation.
whatsapp.template.quality_updated β
Template quality score changed.
Payload Example:
{
"event": {
"type": "whatsapp.template.quality_updated"
},
"data": {
"resource": {
"type": "template_quality",
"attributes": {
"message_template_id": "1234567890",
"message_template_name": "welcome_message",
"message_template_language": "en",
"quality_score": "GREEN",
"previous_quality_score": "YELLOW"
}
}
}
}Quality Scores:
GREEN- High qualityYELLOW- Medium qualityRED- Low quality (at risk)UNKNOWN- Not enough data
Account Events β
whatsapp.account.alert β
Account alert or warning.
Payload Example:
{
"event": {
"type": "whatsapp.account.alert"
},
"data": {
"resource": {
"type": "account_alert",
"attributes": {
"alert_type": "ACCOUNT_UPDATE",
"description": "Your phone number quality is low",
"severity": "WARNING"
}
}
}
}Alert Types:
ACCOUNT_UPDATE- Account information updatedACCOUNT_REVIEW- Account under reviewBUSINESS_CAPABILITY_UPDATE- Capability changedTEMPLATE_QUALITY_UPDATE- Template quality alert
Severity Levels:
INFO- InformationalWARNING- WarningCRITICAL- Critical issue
whatsapp.account.review_updated β
Account review status changed.
Payload Example:
{
"event": {
"type": "whatsapp.account.review_updated"
},
"data": {
"resource": {
"type": "account_review",
"attributes": {
"review_status": "APPROVED",
"previous_status": "PENDING"
}
}
}
}whatsapp.business.capability_updated β
Business account capabilities changed.
Payload Example:
{
"event": {
"type": "whatsapp.business.capability_updated"
},
"data": {
"resource": {
"type": "business_capability",
"attributes": {
"capability": "MESSAGE_TEMPLATES",
"status": "AVAILABLE",
"previous_status": "RESTRICTED"
}
}
}
}Capabilities:
MESSAGE_TEMPLATES- Template messagingBUSINESS_INITIATED_CONVERSATIONS- Initiate conversationsUNLIMITED_CONVERSATIONS- No conversation limits
Phone Events β
whatsapp.phone.quality_updated β
Phone number quality rating changed.
Payload Example:
{
"event": {
"type": "whatsapp.phone.quality_updated"
},
"data": {
"resource": {
"type": "phone_quality",
"attributes": {
"phone_number": "919428735270",
"quality_score": "GREEN",
"previous_quality_score": "YELLOW"
}
}
}
}Quality Scores:
GREEN- High quality (good)YELLOW- Medium quality (warning)RED- Low quality (at risk)UNKNOWN- Not determined
whatsapp.phone.name_updated β
Display name updated.
Payload Example:
{
"event": {
"type": "whatsapp.phone.name_updated"
},
"data": {
"resource": {
"type": "phone_name",
"attributes": {
"phone_number": "919428735270",
"display_name": "Acme Corp Support",
"previous_name": "Acme Support"
}
}
}
}Other Events β
whatsapp.call.received β
Incoming WhatsApp call.
Payload Example:
{
"event": {
"type": "whatsapp.call.received"
},
"data": {
"resource": {
"type": "call",
"id": "call_id_xxx",
"attributes": {
"from": "919876543210",
"timestamp": "1767264000"
}
},
"relationships": {
"contact": {
"wa_id": "919876543210",
"name": "John Doe"
}
}
}
}HTTP Headers β
All webhook requests include these headers:
Content-Type: application/json
Accept: application/json
User-Agent: whatsmark-Webhook/1.0
X-Webhook-Signature: <hmac-sha256-signature>
X-Webhook-Event: <event-type>
X-Webhook-Timestamp: <iso-8601-timestamp>
X-Webhook-Format: n8nHeader Details β
| Header | Description | Example |
|---|---|---|
X-Webhook-Signature | HMAC-SHA256 signature | a1b2c3... |
X-Webhook-Event | Event type | whatsapp.message.received |
X-Webhook-Timestamp | Event timestamp | 2026-01-01T10:38:48+00:00 |
X-Webhook-Format | Payload format | n8n |
Signature Verification β
Algorithm β
signature = HMAC-SHA256(payload_json, secret_key)Node.js Implementation β
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Usage
const payload = req.body;
const signature = req.headers['x-webhook-signature'];
const secret = process.env.WEBHOOK_SECRET;
if (!verifyWebhookSignature(payload, signature, secret)) {
return res.status(403).json({ error: 'Invalid signature' });
}PHP Implementation β
<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$expectedSignature = hash_hmac(
'sha256',
json_encode($payload),
$secret
);
return hash_equals($signature, $expectedSignature);
}
// Usage
$payload = json_decode(file_get_contents('php://input'), true);
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$secret = getenv('WEBHOOK_SECRET');
if (!verifyWebhookSignature($payload, $signature, $secret)) {
http_response_code(403);
echo json_encode(['error' => 'Invalid signature']);
exit;
}Testing β
Sample Payloads β
Text Message:
{
"event": {
"id": "evt_test_12345",
"type": "whatsapp.message.received",
"timestamp": "2026-01-01T10:00:00Z",
"version": "1.0"
},
"tenant": {
"id": 1,
"name": "Test Company"
},
"data": {
"resource": {
"type": "message",
"id": "wamid.test123",
"attributes": {
"message_id": "wamid.test123",
"from": "1234567890",
"timestamp": "1735728000",
"type": "text",
"text": "Test message",
"context": null
}
},
"relationships": {
"contact": {
"wa_id": "1234567890",
"name": "Test User"
},
"metadata": {
"phone_number_id": "1111111111",
"display_phone_number": "1234567890"
}
}
},
"whatsapp": {
"original_payload": {}
},
"metadata": {
"source": "whatsapp_webhook_forward",
"environment": "test",
"request_id": "test-request-id"
}
}cURL Test Command β
curl -X POST https://your-endpoint.com/webhook \
-H "Content-Type: application/json" \
-H "X-Webhook-Event: whatsapp.message.received" \
-H "X-Webhook-Timestamp: 2026-01-01T10:00:00Z" \
-H "X-Webhook-Format: n8n" \
-d '{
"event": {
"id": "evt_test_12345",
"type": "whatsapp.message.received",
"timestamp": "2026-01-01T10:00:00Z",
"version": "1.0"
},
"tenant": {"id": 1, "name": "Test"},
"data": {
"resource": {
"type": "message",
"attributes": {
"text": "Test message"
}
}
}
}'Related Documentation β
- WhatsApp Webhook Forwarding Guide - User guide
- N8N Webhook Integration - Tenant events
- Webhook Format Reference - Tenant webhook format