Skip to main content
client.events.subscribe() returns an async iterable of every event Meta sends for your business account — inbound messages and delivery status updates. The stream reconnects automatically on failure and buffers missed events while you’re offline.

The event stream

Every event carries a cursor string. The cursor advances with each event — save the most recent one and pass it back on restart to pick up where you left off:

Subscribe options

Inbound messages

When event.type === "message", the event carries an . Narrow on content.type before reading content-specific fields:

Inbound content variants

Replying to an incoming message

Thread your reply with replyTo: message.id:

Status updates

When event.type === "status", the event carries a . The status field progresses through sent → delivered → read (or played for voice notes, or failed):
status.bizOpaqueCallbackData echoes whatever you passed on the original send() call — use it to correlate the status back to your own order/ticket/session ID.

Reconnection

subscribe() reconnects automatically. Tune the backoff via options.reconnect:
On reconnect, the stream internally calls fetchMissedEvents with the last cursor it saw, so you don’t lose events that arrived while you were offline.

Fetching missed events manually

If your client crashed without draining the stream, fetch missed events on startup before resubscribing:
Missed events are verified against your app_secret server-side before being returned — payloads that fail verification are dropped.

Message context, referrals, errors

Every InboundMessage can also carry:
  • context — reply-to metadata if the user replied to one of your earlier messages.
  • referral — set when the user arrived via a Click-to-WhatsApp ad.
  • errors — non-empty when Meta returned a partial error alongside the message.
  • contact — the sender’s display name (when available).