Webhook Handling
A single webhook endpoint handles all Meta events. Facebook and Instagram share the same URL — the handler dispatches based on the object field in the payload.
Endpoints
Section titled “Endpoints”Hub Verification
Section titled “Hub Verification”GET /integrations/meta-messaging/webhookFacebook sends this during webhook subscription to verify ownership.
Query params:
| Param | Value |
|---|---|
hub.mode | "subscribe" |
hub.verify_token | Must match meta_messaging_verify_token from core_conf |
hub.challenge | Echo back on success |
Returns the hub.challenge as plain text, or 403 if the token doesn’t match.
Event Handler
Section titled “Event Handler”POST /integrations/meta-messaging/webhookSignature verification: Every request includes an X-Hub-Signature-256 header (sha256=<hex>). The handler computes HMAC-SHA256 of the raw body using meta_messaging_app_secret and performs a constant-time comparison. Returns 403 on mismatch.
Response: Always 200 OK — Meta requires fast acknowledgment. All processing happens asynchronously.
Event Dispatch
Section titled “Event Dispatch”The payload’s object field determines routing:
match payload.object.as_str() { "page" => handle_messenger_events(), // Facebook Messenger "instagram" => handle_instagram_events(), // Instagram DM _ => log and ignore,}Event Types
Section titled “Event Types”Each entry contains a list of messaging events. The handler processes three types:
Message Events
Section titled “Message Events”Inbound text or media from a user. The handler:
- Resolves the organization by Page ID or IG account ID
- Resolves or creates a contact (
resolve_contact_by_facebook/resolve_contact_by_instagram) - Creates a
messagerecord withdirection = Inbound,status = Received - Spawns background tasks for contact enrichment and attachment downloads
- Publishes the message via WebSocket (
EVT_MESSAGE_NEW)
Delivery Events
Section titled “Delivery Events”Meta sends a delivery.watermark timestamp (milliseconds since epoch). All outbound messages sent before this timestamp are marked Delivered.
Read Events
Section titled “Read Events”Same as delivery, but marks messages as Read.
Contact Resolution
Section titled “Contact Resolution”When an inbound message arrives from an unknown sender:
- Query
contact_facebook(orcontact_instagram) by PSID/IGSID and org - If not found: create a stub contact and platform record in a transaction
- Spawn background enrichment — fetch profile via Graph API:
- Messenger:
GET /{psid}?fields=first_name,last_name,profile_pic - Instagram:
GET /{igsid}?fields=name,username
- Messenger:
Watermark-Based Status Updates
Section titled “Watermark-Based Status Updates”Meta doesn’t send per-message delivery confirmations. Instead, it sends a watermark — a timestamp indicating all messages before that point were delivered/read.
update_message_status_by_watermark in update_message_status_by_watermark_service.rs:
- Convert watermark (ms) to
DateTime<Utc> - Query messages where
from_address = <page_or_ig_id>ANDcreated_at < watermarkANDstatus != Read - Batch-update status and publish changes via WebSocket