Skip to content

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:

typescript
interface WhatsAppWebhookPayload {
  event: EventObject;
  tenant: TenantObject;
  data: DataObject;
  whatsapp: WhatsAppObject;
  metadata: MetadataObject;
}

Complete Schema

json
{
  "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.

typescript
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_7KGQvXqbFF

Event Types

All possible event types:

typescript
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.

typescript
interface TenantObject {
  id: number; // Tenant identifier
  name: string; // Tenant/company name
}

Example:

json
{
  "id": 3,
  "name": "Acme Corporation"
}

Data Object

Contains the actual event data and relationships.

typescript
interface DataObject {
  resource: ResourceObject;
  relationships: RelationshipsObject;
}

Resource Object

typescript
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:

typescript
interface RelationshipsObject {
  contact?: ContactRelationship;
  metadata?: MetadataRelationship;
  [key: string]: any;
}

WhatsApp Object

Contains the complete original WhatsApp webhook payload.

typescript
interface WhatsAppObject {
  original_payload: {
    object: string;
    entry: Array<{
      id: string;
      changes: Array<{
        value: object;
        field: string;
      }>;
    }>;
  };
}

Metadata Object

Request tracking and environment information.

typescript
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:

json
{
  "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 message
  • image - Image with optional caption
  • video - Video with optional caption
  • audio - Audio/voice message
  • document - Document/file
  • location - Location coordinates
  • contacts - Contact card
  • sticker - Sticker
  • interactive - Button/list responses
  • button - Quick reply button
  • order - Order message

**Text Message Attributes:

typescript
{
  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:

typescript
{
  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:

typescript
{
  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:

typescript
{
  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:

json
{
  "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 server
  • delivered - Delivered to customer's device
  • read - Customer read the message
  • failed - 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:

json
{
  "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:

json
{
  "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 active
  • REJECTED - Template rejected
  • PENDING - Under review
  • PAUSED - Template paused
  • DISABLED - Template disabled

Rejection Reasons: When status is REJECTED, reason field contains explanation.

whatsapp.template.quality_updated

Template quality score changed.

Payload Example:

json
{
  "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 quality
  • YELLOW - Medium quality
  • RED - Low quality (at risk)
  • UNKNOWN - Not enough data

Account Events

whatsapp.account.alert

Account alert or warning.

Payload Example:

json
{
  "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 updated
  • ACCOUNT_REVIEW - Account under review
  • BUSINESS_CAPABILITY_UPDATE - Capability changed
  • TEMPLATE_QUALITY_UPDATE - Template quality alert

Severity Levels:

  • INFO - Informational
  • WARNING - Warning
  • CRITICAL - Critical issue

whatsapp.account.review_updated

Account review status changed.

Payload Example:

json
{
  "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:

json
{
  "event": {
    "type": "whatsapp.business.capability_updated"
  },
  "data": {
    "resource": {
      "type": "business_capability",
      "attributes": {
        "capability": "MESSAGE_TEMPLATES",
        "status": "AVAILABLE",
        "previous_status": "RESTRICTED"
      }
    }
  }
}

Capabilities:

  • MESSAGE_TEMPLATES - Template messaging
  • BUSINESS_INITIATED_CONVERSATIONS - Initiate conversations
  • UNLIMITED_CONVERSATIONS - No conversation limits

Phone Events

whatsapp.phone.quality_updated

Phone number quality rating changed.

Payload Example:

json
{
  "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:

json
{
  "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:

json
{
  "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: n8n

Header Details

HeaderDescriptionExample
X-Webhook-SignatureHMAC-SHA256 signaturea1b2c3...
X-Webhook-EventEvent typewhatsapp.message.received
X-Webhook-TimestampEvent timestamp2026-01-01T10:38:48+00:00
X-Webhook-FormatPayload formatn8n

Signature Verification

Algorithm

signature = HMAC-SHA256(payload_json, secret_key)

Node.js Implementation

javascript
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
<?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:

json
{
  "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

bash
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"
        }
      }
    }
  }'

© 2024 - Corbital Technologies. All rights reserved.