Webhooks at EchoCue
How EchoCue uses webhooks to integrate with Meta's WhatsApp Cloud API today, what we do with each event, and what's planned for forwarding those events to your own URL.
Where webhooks fit today
EchoCue is currently an inbound webhook consumer - Meta posts events to us when something happens on a linked WhatsApp Business Account, and we update your dashboard, message threads, template list, and opt-out registry in response. Forwarding those events to a URL you control is on the roadmap (see Coming soon below).
Events EchoCue receives from Meta
Meta posts to our public callback (POST /v1/whatsapp/webhook) for every linked WhatsApp Business Account. We parse five event categories and translate each into dashboard state, message-thread updates, or template lifecycle changes you can observe via the API.
A contact texts your WhatsApp number
EchoCue stores the message on the matching thread, opens the 24-hour conversation window so freeform replies are allowed, and updates the inbox. Visible via /api/thread/{thread_id}/messages.
Meta confirms sent / delivered / read / failed
EchoCue updates the message row's delivery state. Visible via /api/notification/{notification_id} and on the broadcast detail page.
Meta approves, rejects, pauses, or flags a WhatsApp template
EchoCue mirrors all eleven Meta states (approved, pending, rejected, paused, flagged, in_appeal, pending_deletion, limit_exceeded, disabled, deleted, draft) on each local template row. Visible via /api/template/list.
Meta downgrades a template's quality score
EchoCue persists the new score (GREEN / YELLOW / RED) so you can pull it via /api/template/{template_id} and react before Meta auto-pauses.
Recipient sends STOP / UNSUBSCRIBE
EchoCue marks the contact as opted-out across all channels, suppresses future broadcasts to that number, and records the event on the conversation thread.
What changes when an event lands
Each Meta event drives a specific state change you can observe via the REST API. If you're polling today, these are the fields to watch.
| Meta event | State changes EchoCue applies | API surface that exposes the change |
|---|---|---|
message.inbound |
New row in ec_message; thread's last_message_at + 24h conversation window updated; inbox unread count bumps |
/api/thread/list, /api/thread/{id}/messages, /api/whatsapp/window |
message.status |
Message row's delivery_status moves through sent → delivered → read (or to failed with an error code) |
/api/notification/{id} |
template.status |
Template row's whatsapp_status column updated; if pending → approved, the template becomes broadcastable |
/api/template/list, /api/template/{id} |
template.quality |
Template row's whatsapp_quality_rating column updated |
/api/template/{id} |
consent.event |
Contact's opted_out_at set; all pending broadcasts to that contact are skipped |
/api/contact/{contact_id} (look for opted_out_at) |
message.status → failed path (e.g. 131026, 132001) are documented on the Error codes page.
Connecting your WhatsApp Business Account
EchoCue acts as a Meta Tech Provider. You connect your WhatsApp Business Account once via the Embedded Signup flow, and Meta starts posting events to our callback automatically - no per-account configuration needed on your side.
- From your dashboard, open WhatsApp settings → Connect with Meta.
- Complete Meta's hosted onboarding popup. Pick the business + phone number to connect.
- EchoCue exchanges Meta's auth code for a long-lived system user token, registers the phone number on Cloud API, and subscribes our app to your WABA's webhooks. You'll see the device come online within a few seconds.
message, message_status, and template_* event to EchoCue. No webhook URL is configured on your side because there's nothing on your side to configure yet.
Coming soon: Outbound delivery to your URL
We're building outbound webhook delivery so each Meta event EchoCue receives can be forwarded to a URL you control. The design is locked in; the rollout is in progress.
Endpoint configuration
Register an HTTPS URL on your developer settings. The URL is stored per API key so different integrations can receive different subsets.
Payload signing
Each request will carry X-EchoCue-Signature: sha256=... - an HMAC of the raw body using your API secret - so you can verify the payload came from us before trusting it.
Delivery retries
Non-2xx responses or 10-second timeouts trigger automatic retries with backoff (30s → 2m → 10m → 1h → 6h, capped at five attempts). Failed deliveries surface in your developer dashboard.
Event coverage
Initial release covers message.inbound, message.status, template.status, template.quality, and consent.event - the same five categories above. Per-event subscriptions arrive in a follow-up.
What to do in the meantime
Until outbound webhooks ship, the REST API exposes everything Meta tells us. The endpoints below cover the same five event categories above; poll them on an interval that matches your traffic.
- Inbound messages - list threads with
/api/thread/list?since=<ISO timestamp>, then page through each thread's messages. - Delivery status -
/api/notification/list?status=sent,delivered,read,failedwith asincefilter. - Template status / quality -
/api/template/listexposes the currentwhatsapp_statusand quality score per template. - Opt-outs -
/api/contact/listreturns each contact'sopted_out_at.