- Webhooks & events
- Expert
- Developers
Message Echoes Webhook
Also called: smb_message_echoes · SMB message echoes · Coexistence echo webhook
The smb_message_echoes webhook copies messages a business sends from the WhatsApp Business app on a coexistence number to the API, so CRM threads stay whole.
Reviewed
What is the message echoes webhook?
The message echoes webhook — the smb_message_echoes field — exists for coexistence, where one number works in the WhatsApp Business app and on the Cloud API at the same time. Whenever the business sends a message from the app or from a linked companion device, Meta posts a copy to the partner's webhook. Without it, a CRM on the API sees what customers write and what the API sent, but nothing the owner typed on their phone, and every thread has holes.
The payload follows the usual envelope. value holds messaging_product, metadata with display_phone_number and phone_number_id, and a message_echoes array. Each echo has from (the business number), to (the customer), id (the message's wamid), timestamp, type and an object named after the type. Meta's reference shows echoes of text and media messages such as text, image, video and document, plus edit (with original_message_id and the updated message) and revoke (with original_message_id) when the owner edits or deletes something already sent.
It is the mirror image of the messages webhook. A messages event carries what a user sent to the business, with from set to the user; an echo carries what the business sent from the app, with from set to the business and an extra to. Messages sent through the API never echo — you already hold their wamid and follow them through the statuses webhook. Two sibling fields complete coexistence: history handles message history sync, back-filling past chats once at connection, and smb_app_state_sync keeps the app's contacts in step.
Key takeaways
- The message echoes webhook (
smb_message_echoes) copies messages a coexistence number sends from the WhatsApp Business app to your API webhook. - An echo's
fromis the business number andtois the customer — the reverse of an inbound messages webhook. - Apply
editandrevokeechoes byoriginal_message_idso the CRM shows what the customer now sees. - Echoes cover sends from the app or a linked companion device; track Cloud API sends with statuses webhooks instead.
- Echoes stop silently if the coexistence link drops, which happens after about 14 days without using the app.
Interactive stop
Who sees what when the owner replies from the app?
- CustomerWhatsApp user
- Owner's phoneWhatsApp Business app
- WhatsAppCloud API
- Your CRMWebhook endpoint
Step 10 of 10Request
Your CRMWhatsApp
Agent replies via POST /messages
API sends do not echo; track them with statuses webhooks.
- Request — solid arrow — a call that expects an answer
- Response — dashed arrow — the answer coming back
- Event — dotted arrow — something happened and is pushed out
- Async — double head — fire-and-forget, nobody waits
Step 10 of 10: Your CRM to WhatsApp — Agent replies via POST /messages. API sends do not echo; track them with statuses webhooks.
Example: A Surat saree shop with two inboxes
The owner of a Surat saree shop answers customers from her phone, while two staff work the same number in a shared team inbox connected through the API. A customer asks whether a Banarasi silk saree comes in maroon. The owner replies from the app with a photo; the smb_message_echoes webhook drops that image into the inbox thread within seconds, so staff see the question is handled. She then edits a price typo in her follow-up text, and an edit echo updates the stored message by its original_message_id.
How does the message echoes webhook work?
Connect the number with coexistence
The business onboards its existing WhatsApp Business app number (app version 2.24.17 or later) through a partner's Embedded Signup flow, keeping the app working alongside the Cloud API.
Subscribe to the coexistence fields
Subscribe the app to the webhook fields
smb_message_echoes,historyandsmb_app_state_syncas well asmessages. Echoes are a supported override field, so they can go to a phone-number or WABA-level callback URL.File each echo as outbound
Find the thread by
metadata.phone_number_idandto, then store the echo as a business message sent from the app. Never feed it to the bot as if a customer had written it.Apply edits and deletions
For
type: edit, replace the stored message whose wamid equalsoriginal_message_id; fortype: revoke, mark it deleted, so the CRM shows what the customer now sees.Deduplicate and watch for silence
Skip echoes whose
idyou have already stored, because retries resend them. Alert if a busy number's echoes stop: the link drops when the app goes unused for about 14 days.
The message echoes webhook in code
export async function onEchoes(change) {if (change.field !== "smb_message_echoes") return;const v = change.value;for (const echo of v.message_echoes ?? []) {if (await seen(echo.id)) continue; // retries resend echoesconst thread = await threads.find(v.metadata.phone_number_id, echo.to);switch (echo.type) {case "edit":await thread.replace(echo.edit.original_message_id, echo.edit.message);break;case "revoke":await thread.markDeleted(echo.revoke.original_message_id);break;default: // text, image, video, documentawait thread.addOutbound({id: echo.id,via: "whatsapp_business_app", // never route this to the bottype: echo.type,content: echo[echo.type],at: Number(echo.timestamp) * 1000,});}}}
Echoes are business messages: file them as outbound, apply edits and revokes, and skip duplicates.
Common mistakes with the message echoes webhook
Treating echoes as inbound
An echo's
fromis your own business number. A handler that sends every message-like payload to the chatbot ends up answering the owner's replies, or looping. Routesmb_message_echoesto its own handler.Ignoring edit and revoke
If you only store
textand media echoes, the CRM keeps showing words the customer no longer sees. Applyeditandrevokebyoriginal_message_id, and keep the original in an audit trail if you need it.Assuming every message type echoes
Meta documents a specific list of echo types. Store unknown types as raw payloads with a placeholder in the thread instead of dropping them, and review them when Meta's reference expands.
Not noticing the link has dropped
If the app sits unused for about 14 days the coexistence link drops and echoes simply stop. Alert on silence, and watch
account_updateforPARTNER_REMOVEDwithdisconnection_info, whosereason(such asPRIMARY_INACTIVITYorCOMPANION_INACTIVITY) says why.
Why does the message echoes webhook matter?
Coexistence lets a shop owner keep chatting from their phone while a team or a bot works the same number through the API. That only works if both sides see the whole conversation. Echoes stop an agent from re-answering a question the owner already handled, give a bot the context of what was promised, and leave one complete record of every customer conversation for audits, disputes and reporting.
The message echoes webhook: key facts and limits
- Webhook field
- smb_message_echoes
- Applies to
- Coexistence numbers (Business app + Cloud API)
- Echo types in Meta's reference
- Text and media (image, video, document), edit, revoke
- Key fields
- from (business), to (customer), id, timestamp, type
- Back-fill
- history webhook: up to 180 days, media from the last 14 days
- Coexistence throughput
- 20 messages per second, in and out combined
- Callback override
- Supported at phone-number or WABA level
Message Echoes Webhook FAQs
Do messages sent through the Cloud API produce echoes?+
Are messages sent from the app charged?+
Will I receive older chats as echoes?+
Do I have to subscribe to smb_message_echoes separately?+
Best practices for the message echoes webhook
- Label app-sent messages in the inbox so agents can tell the owner's replies from their own.
- Key threads on phone_number_id plus the customer identifier, and normalise numbers before matching — Meta notes an echo's to may not always match the user's wa_id.
- Process history back-fill and live echoes through the same deduplication by wamid.
- Keep the owner's edit and delete history if your compliance policy needs the original wording.
* Per-message rates for India, ex-GST: marketing, utility and authentication effective 1 July 2026; service messages ₹0.145 since 1 October 2026 (they were ₹0 until 30 September 2026). Volume commitments earn discounts — final rate is confirmed on your account; applicable GST extra. Rates for other countries differ (see the international rate table on /pricing).
Talk to InfiQ
From definition to your first message
InfiQ is an official Meta Business Partner. Start a 7-day free trial — no card needed — and see this running on your own number.