Message Types Reference
This page documents every message_type you may encounter in message.received and message.sent webhook events. Each type includes the exact payload structure, which platforms support it, and whether it's inbound-only, outbound-only, or bidirectional.
For the webhook envelope structure and event lifecycle, see Webhook Events Reference.
Direction Matrix
| message_type | Inbound | Outbound | Platforms |
|---|---|---|---|
text | ✅ | ✅ | All |
image | ✅ | ✅ | All |
video | ✅ | ✅ | All |
audio | ✅ | ✅ | All |
document | ✅ | ✅ | WhatsApp, Telegram (inbound); All (outbound) |
sticker | ✅ | ✅ | All (inbound); WhatsApp (outbound) |
location | ✅ | ❌ | |
contact (inbound) / contacts (outbound) | ✅ | ✅ | |
interactive | ✅ | ✅ | |
button | ✅ | ❌ | WhatsApp (template quick-reply buttons) |
reaction | ✅ | ✅ | WhatsApp, Telegram, Messenger, Instagram, Live Chat |
template | ❌ | ✅ | |
carousel | ❌ | ✅ | WhatsApp, Messenger |
File-Based Attachments
Messages of type image, video, audio, document, and sticker include an attachments array with enriched download data:
{
"id": "att_abc123",
"type": "image",
"filename": "whatsapp_image_abc123.jpg",
"content_type": "image/jpeg",
"file_size": 245000,
"url": "https://api.sendseven.com/api/v1/attachments/att_abc123/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
| Field | Description |
|---|---|
url | Stable API endpoint — requires authentication, never expires |
signed_url | Pre-signed GCS URL — no auth required, expires 2 hours after the event was created |
If SendSeven could not download the media from the platform, the raw platform data is passed through with "source": "platform" added to each attachment object. Check for this field to detect unprocessed attachments.
Inbound Message Types
text
The most common message type. Supported on all platforms.
{
"message_type": "text",
"text": "Hello, I need help with my order",
"attachments": null
}
image
Photo messages with optional caption. Includes Telegram GIFs/animations.
{
"message_type": "image",
"text": "Check out this photo",
"attachments": [
{
"id": "att_img_001",
"type": "image",
"filename": "whatsapp_image_abc123.jpg",
"content_type": "image/jpeg",
"file_size": 245000,
"url": "https://api.sendseven.com/api/v1/attachments/att_img_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
text contains the caption if provided, otherwise "".
video
Video messages with optional caption. Includes Telegram round video notes.
{
"message_type": "video",
"text": "",
"attachments": [
{
"id": "att_vid_001",
"type": "video",
"filename": "video_message.mp4",
"content_type": "video/mp4",
"file_size": 5242880,
"url": "https://api.sendseven.com/api/v1/attachments/att_vid_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
audio
Voice messages and audio files.
{
"message_type": "audio",
"text": "",
"attachments": [
{
"id": "att_aud_001",
"type": "audio",
"filename": "voice_note.ogg",
"content_type": "audio/ogg",
"file_size": 128000,
"url": "https://api.sendseven.com/api/v1/attachments/att_aud_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
document
File attachments with optional caption. WhatsApp and Telegram inbound.
{
"message_type": "document",
"text": "Here's the contract",
"attachments": [
{
"id": "att_doc_001",
"type": "document",
"filename": "contract_2026.pdf",
"content_type": "application/pdf",
"file_size": 184320,
"url": "https://api.sendseven.com/api/v1/attachments/att_doc_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
sticker
Sticker messages from all platforms. WhatsApp sets text to "[Sticker]", other platforms use "".
{
"message_type": "sticker",
"text": "[Sticker]",
"attachments": [
{
"id": "att_stk_001",
"type": "sticker",
"filename": "sticker.webp",
"content_type": "image/webp",
"file_size": 32000,
"url": "https://api.sendseven.com/api/v1/attachments/att_stk_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
location
Location pins shared by contacts. WhatsApp only, inbound only.
{
"message_type": "location",
"text": "Location: Eiffel Tower",
"attachments": [
{
"type": "location",
"latitude": 48.8566,
"longitude": 2.3522,
"name": "Eiffel Tower",
"address": "Champ de Mars, 75007 Paris"
}
]
}
Location attachments are not file-based — they contain coordinate data directly. The name and address fields are optional and depend on what the contact shared.
contact
Contact cards shared via WhatsApp.
{
"message_type": "contact",
"text": "Shared contacts: John Doe, Jane Smith",
"attachments": [
{
"type": "contact",
"contacts": [
{
"name": {
"formatted_name": "John Doe",
"first_name": "John",
"last_name": "Doe"
},
"phones": [
{ "phone": "+491234567890", "type": "CELL" }
],
"emails": [
{ "email": "[email protected]", "type": "WORK" }
]
}
]
}
]
}
WhatsApp sends contact cards with the plural type contacts; SendSeven normalizes inbound messages to the singular contact (both message_type and the attachment type). Outbound contact-card sends use the plural contacts type (see contacts (outbound)). Contact card attachments are not file-based.
interactive — Button Reply
When a contact taps a button from a previously sent interactive message. WhatsApp only.
{
"message_type": "interactive",
"text": "Yes, confirm order",
"attachments": [
{
"type": "button_reply",
"button_id": "btn_confirm",
"button_title": "Yes, confirm order"
}
]
}
The text field contains the button title for convenience, and a meta.button object ({ id, payload, text }) is also included — see Button Clicks Across Channels.
interactive — List Reply
When a contact selects an item from a list menu. WhatsApp only.
{
"message_type": "interactive",
"text": "Express Shipping\n2-3 business days",
"attachments": [
{
"type": "list_reply",
"list_id": "shipping_express",
"list_title": "Express Shipping",
"list_description": "2-3 business days"
}
],
"meta": {
"button": {
"id": "shipping_express",
"payload": "shipping_express",
"text": "Express Shipping",
"list_title": "Express Shipping",
"list_description": "2-3 business days"
}
}
}
text mirrors what the contact sees in WhatsApp: the selected row's title, and — when the row has a description — the description on the next line ("{list_title}\n{list_description}"). The meta.button object carries { id, payload, text } (with text = the list title) plus list_title and list_description for list replies (these two extra keys are present only for list replies; a plain button reply's meta.button stays { id, payload, text }).
interactive — Flow Response (NFM Reply)
When a contact completes a WhatsApp Flow. WhatsApp only.
{
"message_type": "interactive",
"text": "Flow completed\nSatisfaction: 5_Very_Happy\nTopics:\n- Billing\n- Delivery\nComments: Great service!",
"attachments": [
{
"type": "flow_response",
"flow_name": "flow",
"flow_token": "token_abc123",
"response_data": {
"screen_0_Satisfaction_0": "5_Very_Happy",
"screen_0_Topics_1": ["Billing", "Delivery"],
"screen_1_Comments_0": "Great service!",
"flow_token": "token_abc123"
}
}
],
"meta": {
"flow_response": {
"flow_token": "token_abc123",
"response_data": {
"screen_0_Satisfaction_0": "5_Very_Happy",
"screen_0_Topics_1": ["Billing", "Delivery"],
"screen_1_Comments_0": "Great service!"
},
"reply_to_external_id": "wamid.HBgM...",
"flow_id": "1234567890123456"
}
}
}
text is a plain-text summary (no markdown). It starts with Flow completed, followed by one Label: value line per answer. Labels come from the field names: the screen_<n>_ prefix and the _<i> suffix added by WhatsApp's Flow Builder are removed, and other underscores become spaces. Values are shown exactly as submitted (true/false as Yes/No); a list answer becomes a Label: line followed by one - value line per item. Do not parse text; use response_data.
The flow_response attachment holds the raw answers in response_data, exactly as WhatsApp delivered them (including flow_token). flow_name is always "flow" (WhatsApp does not send the flow's name).
meta.flow_response carries the same answers in a structured form:
| Field | Description |
|---|---|
flow_token | The token the flow was sent with. |
response_data | The answers, without flow_token. |
reply_to_external_id | The WhatsApp message id of the flow message this submission answers. |
flow_id | The WhatsApp flow id, when SendSeven could match the reply to the flow message it sent. null otherwise. |
For flows built in SendSeven, answers of fields marked sensitive are masked as •••• in response_data and in text. See Responses and Webhooks.
If the contact uploaded photos or documents in the Flow, the flow_response attachment (and meta.flow_response) also has a media object next to response_data, keyed by input name. Each file carries attachment_id, file_name, mime_type, size, status, and when stored a permanent url (API key with messages:read) plus a 2-hour signed_url with signed_url_expires_at. Inside response_data, photo and document answers are reduced to media_id, file_name and mime_type; WhatsApp's download and decryption details are never sent. See Uploaded files.
reaction
Emoji reactions to messages. Supported on WhatsApp, Telegram, Messenger, Instagram, and Live Chat, both inbound (a contact reacts to your message) and outbound (an agent reacts via the reaction endpoint). Telegram only accepts emojis from its fixed reaction set; the other channels accept any emoji.
{
"message_type": "reaction",
"text": "Reacted 👍 to message",
"attachments": [
{
"type": "reaction",
"emoji": "👍",
"message_id": "wamid.HBgNNDkx..."
}
]
}
The message_id references the platform message ID that was reacted to.
Reactions are free — a reaction is never counted as a billable message.
To be notified when a reaction is added or removed (rather than parsing it out of an inbound message), subscribe to the dedicated message.reaction webhook event, whose data.reaction.action field distinguishes "added" from "removed".
button
When a contact taps a quick-reply button on a WhatsApp template message (as opposed to a standalone interactive message), the click arrives as message_type: "button". WhatsApp only, inbound only.
{
"message_type": "button",
"text": "Yes, confirm",
"attachments": null,
"meta": {
"button": {
"id": "OPT_YES",
"payload": "OPT_YES",
"text": "Yes, confirm"
}
}
}
The clicked button caption populates the text field, and the structured meta.button object carries { id, payload, text }. For template quick-reply buttons, WhatsApp does not send a distinct button ID, so id and payload both contain the button payload.
This is distinct from interactive button replies. Template quick-reply buttons (attached to a template message) arrive as message_type: "button"; buttons on a standalone interactive message arrive as message_type: "interactive" with a button_reply attachment. Both populate text with the caption and include meta.button.
Button Clicks Across Channels
Every channel that supports buttons forwards the clicked caption in the message text field and populates a structured meta.button object so you can react to the click without parsing the caption:
"meta": {
"button": {
"id": "OPT_YES",
"payload": "OPT_YES",
"text": "Yes, confirm"
}
}
| Field | Type | Description |
|---|---|---|
id | string | Button/option identifier |
payload | string | Developer-defined payload sent back on click (equals id when the channel has no separate payload) |
text | string | The button caption the contact saw (also mirrored into the message text) |
This applies to:
| Channel | Button source | message_type |
|---|---|---|
| Template quick-reply button | button | |
Interactive button_reply | interactive | |
Interactive list_reply | interactive | |
| Telegram | Inline keyboard callback | text |
| Messenger | Postback button | text |
| Messenger | Quick reply | text |
| Postback button | text | |
| Quick reply | text | |
| Live Chat | Widget button | text |
The existing channel-specific attachment objects (button_reply, list_reply) are still included for WhatsApp interactive messages — meta.button is provided in addition to them. For WhatsApp list replies, meta.button also carries list_title and list_description (the row's title and description); text remains the list title.
Outbound Message Types
These appear in message.sent webhook events.
text
{
"message_type": "text",
"text": "Hi John! Let me look into your order right away.",
"attachments": null
}
image / video / audio / document
Same as inbound — includes enriched attachments array:
{
"message_type": "image",
"text": "Here's the receipt",
"attachments": [
{
"id": "att_out_001",
"type": "image",
"filename": "receipt.jpg",
"content_type": "image/jpeg",
"file_size": 245000,
"url": "https://api.sendseven.com/api/v1/attachments/att_out_001/download",
"signed_url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}
]
}
interactive (outbound)
Interactive messages with buttons or list menus. WhatsApp only. Metadata includes the full interactive structure:
{
"message_type": "interactive",
"text": "How would you like to proceed?",
"attachments": null,
"meta": {
"interactive_type": "buttons",
"body": "How would you like to proceed?",
"header": { "type": "text", "text": "Order #12345" },
"footer": "Reply within 24 hours",
"buttons": [
{ "id": "btn_confirm", "title": "Confirm" },
{ "id": "btn_cancel", "title": "Cancel" }
]
}
}
For list-type interactive messages:
{
"meta": {
"interactive_type": "list",
"body": "Choose a shipping option:",
"sections": [
{
"title": "Shipping",
"rows": [
{ "id": "ship_standard", "title": "Standard", "description": "5-7 days" },
{ "id": "ship_express", "title": "Express", "description": "2-3 days" }
]
}
]
}
}
template
WhatsApp template messages. Outbound only.
{
"message_type": "template",
"text": "Hi John, your order #12345 has shipped! Track it here: https://track.example.com/12345",
"attachments": null,
"meta": {
"whatsapp_template": true,
"template_id": "tmpl_abc123",
"template_name": "order_shipped",
"template_language": "en",
"header_type": "text",
"header_text": "Order Update",
"footer_text": "Thank you for your purchase",
"buttons": [
{ "type": "URL", "text": "Track Order", "url": "https://track.example.com/12345" }
]
}
}
The text field contains the template body with parameters already substituted.
contacts (outbound)
Contact cards sent via WhatsApp.
{
"message_type": "contacts",
"text": "[Contact Cards]",
"attachments": null,
"meta": {
"content_type": "contacts",
"contacts_count": 1,
"contacts_data": [
{
"name": { "formatted_name": "Support Team", "first_name": "Support" },
"phones": [{ "phone": "+491781660323", "type": "WORK" }]
}
]
}
}
sticker (outbound)
Sticker sent via WhatsApp.
{
"message_type": "sticker",
"text": "[Sticker]",
"attachments": null,
"meta": {
"content_type": "sticker",
"sticker_id": "whatsapp_media_id",
"sticker_url": "https://example.com/sticker.webp"
}
}
carousel
Rich card carousels. WhatsApp and Messenger.
WhatsApp carousel:
{
"message_type": "carousel",
"text": "[Carousel: product_showcase] 3 cards",
"attachments": null,
"meta": {
"content_type": "carousel",
"cards_count": 3,
"platform": "whatsapp",
"template_name": "product_showcase",
"language": "en"
}
}
Messenger carousel:
{
"message_type": "carousel",
"text": "[Carousel] Sneakers, Jacket, Backpack",
"attachments": null,
"meta": {
"content_type": "carousel",
"cards_count": 3,
"platform": "messenger",
"elements": [
{
"title": "Sneakers",
"subtitle": "Running shoes — $89",
"image_url": "https://shop.example.com/img/sneakers.jpg",
"buttons": [
{ "type": "web_url", "url": "https://shop.example.com/sneakers", "title": "View" }
]
}
]
}
}
Platform-Specific Notes
WhatsApp
- Supports all message types listed above.
contactsuses plural form (matching WhatsApp API convention).- Template quick-reply button clicks arrive as
message_type: "button"with the caption intextand ameta.buttonobject (see button). - Interactive replies (button, list, flow) arrive as
message_type: "interactive"— differentiate by checkingattachments[0].type. Button and list replies also populatemeta.buttonwith{ id, payload, text }. - Reactions are
message_type: "reaction"(not in the standard enum, but stored and delivered).
Telegram
- GIFs/animations arrive as
message_type: "image". - Round video notes arrive as
message_type: "video". - Both voice messages and audio files arrive as
message_type: "audio". - Inline button clicks arrive as
message_type: "text"withmeta.is_callback_query: trueandmeta.callback_query_id. The clicked caption is forwarded intextand ameta.buttonobject ({ id, payload, text }) is included.
Messenger
- Stickers are detected via
sticker_idand delivered asmessage_type: "sticker"(Facebook sends them as image type). - Postback buttons and quick replies arrive as
message_type: "text"with the payload inmeta.quick_reply. The clicked caption is forwarded intextand ameta.buttonobject ({ id, payload, text }) is included. - Deep link referrals (
m.melinks) create a syntheticmessage_type: "referral"withmeta.ref_parameter.
Instagram
- Supports text, image, video, audio, and sticker.
- Story replies include
meta.is_story_reply: trueandmeta.story_id. - Postback buttons and quick replies arrive as
message_type: "text"with the caption intextand ameta.buttonobject ({ id, payload, text }). - No profile data is included in
contact_info(Instagram webhook limitation).
Live Chat
- Widget button clicks arrive as
message_type: "text"with the caption intextand ameta.buttonobject ({ id, payload, text }).
Next Steps
- Webhook Events Reference — event types and full payload envelope
- Signature Verification — secure your webhook endpoint
- Send Media Messages — sending attachments via the API