WhatsApp Channel
Receive WhatsApp messages as webhook events and send free-form text or approved templates through the shared Send API. This page covers the WhatsApp-specific details; the shared envelope, signing, and core actions live on the Webhook & Send API page.
Add-on · $29/month · Requires Professional+ planOverview
ChatGenius routes WhatsApp through Meta's Cloud API directly (not Twilio). Meta is the WhatsApp transport sub-processor on this channel. Once provisioned, both inbound forwarding and the outbound Send API work alongside SMS, Facebook DM, and Instagram DM.
Requirements: Professional or higher tier (WhatsApp is included), a connected WhatsApp Business Account with a verified phone number, and the Webhook & Send API add-on active. The whatsapp.message_received checkbox is disabled until a business number is connected.
Capabilities
| Capability | Support |
|---|---|
| Inbound forwarding | Text, image, audio, video, document, sticker, location, contacts, and button replies forwarded as whatsapp.message_received events |
| Outbound free-form text | send_message with message_text — within the 24-hour customer-care window |
| Outbound templates | Approved templates sendable any time via template_name + template_language + template_components |
| Pure-relay mode | Turn off the WhatsApp AI Assistant (or enable Global External Reply Mode) — inbound still forwards, no AI reply |
Inbound Payload
Inbound WhatsApp events use the standard envelope plus a WhatsApp-specific message.whatsapp sub-block. source.channel is always whatsapp_cloud.
{
"event_id": "f8e7d6c5b4a3021918273645ded0c9ba",
"event_type": "whatsapp.message_received",
"occurred_at": "2026-05-05T18:30:00Z",
"source": {
"platform": "whatsapp",
"channel": "whatsapp_cloud"
},
"conversation": {
"id": 4982
},
"customer": {
"platform_user_id": "15551234567",
"phone": "15551234567",
"profile_name": "Jane Doe"
},
"message": {
"id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBJCRkE5...",
"text_raw": "Yes, please confirm my order",
"attachments": [],
"whatsapp": {
"wa_id": "15551234567",
"phone_number": "+15551234567",
"business_phone_number_id": "108765432109876",
"profile_name": "Jane Doe",
"message_type": "text",
"context_message_id": null
}
},
"meta": {
"version": "v1",
"payload_profile": "full",
"generated_at": "2026-05-05T18:30:00Z"
}
}
WhatsApp-specific fields
| Field | Type | Description |
|---|---|---|
| customer.platform_user_id | string | WhatsApp wa_id (E.164 digits, no leading +). Always present. |
| customer.phone | string | Same value, mirrored for parity with SMS. Present in full profile only. |
| customer.profile_name | string|null | WhatsApp profile name from Meta (best-effort). |
| message.id | string | Meta wamid. Use for idempotent processing on your side. |
| message.whatsapp.business_phone_number_id | string | The recipient business phone number ID (yours). |
| message.whatsapp.message_type | string | One of text, image, audio, video, document, sticker, location, contacts, interactive, button, reaction. |
| message.whatsapp.context_message_id | string|null | The wamid this message replies to (button replies, threaded replies); null otherwise. |
| message.attachments | array | For media-type messages, populated with media_id, mime_type, filename, etc. Always an array. |
Sending WhatsApp Messages
Use the shared Send endpoint with the same authentication header. Set platform: "whatsapp" and to_phone in E.164 format (with or without leading +).
Free-form text (within the 24-hour window)
{
"idempotency_key": "wa_20260505_001",
"action": "send_message",
"platform": "whatsapp",
"to_phone": "+15551234567",
"message_text": "Thanks — your refill is ready for pickup."
}
Free-form text requires the recipient to have messaged you in the last 24 hours (Meta's customer-care window). Outside that window, use a template (below). Free-form body max: 4,096 characters. Each successful outbound request counts as 1 unit against your outbound counters.
WhatsApp Templates
Approved templates can be sent any time (no 24h window required). Templates must already be registered and approved on your WhatsApp Business Account. ChatGenius forwards your template_name + template_language + template_components directly to Meta's Cloud API. Template names must use Meta's lowercase letters/numbers/underscore format, and template_components must be a JSON array.
{
"idempotency_key": "wa_template_20260505_001",
"action": "send_message",
"platform": "whatsapp",
"to_phone": "+15551234567",
"template_name": "order_shipped",
"template_language": "en_US",
"template_components": [
{
"type": "body",
"parameters": [
{"type": "text", "text": "12345"},
{"type": "text", "text": "May 6"}
]
}
]
}
Template component shape
Pass through Meta's Cloud API components array structure as documented in Meta's WhatsApp template documentation. Common component types: header, body, button. Each component contains a parameters array of typed values.
Named vs. positional parameters
Meta supports two parameter styles, and the format your template was registered with determines the shape at send time.
Positional placeholders ({{1}}, {{2}}, ...) — older style, matched by order:
{
"type": "body",
"parameters": [
{"type": "text", "text": "12345"},
{"type": "text", "text": "May 6"}
]
}
Named placeholders ({{customer_name}}, ...) — newer style, each parameter must include a parameter_name field matching the placeholder name:
{
"type": "body",
"parameters": [
{"type": "text", "parameter_name": "customer_name", "text": "Jared"},
{"type": "text", "parameter_name": "order_number", "text": "SG4324"},
{"type": "text", "parameter_name": "business_name", "text": "SumGeniusAI"},
{"type": "text", "parameter_name": "order_status", "text": "Shipped"}
]
}
If you mix the two or omit parameter_name for a named-parameter template, Meta returns (#100) Invalid parameter with "Parameter name is missing or empty." Check your template definition in WhatsApp Manager to see which style it was registered with.
Errors
- (#100) Invalid parameter — usually the parameter shape doesn't match the template (positional vs named, or missing
parameter_name). - 132001 — Template does not exist (check name and language).
- 132000 — Number of parameters does not match the registered template.
- 132012 — Parameter format does not match (e.g. wrong type for a placeholder).
- 131047 — Re-engagement message error (24h window expired and no template used).
- 132015 — Template paused due to low quality.