ChatGenius Developer Meta DM (Facebook & Instagram) Markdown

Meta DM (Facebook & Instagram)

Receive Facebook Messenger and Instagram direct messages, plus comments, as webhook events; reply, react, or show typing through the Send API. This page covers only what is specific to Meta DM: the shared envelope and signature verification live on Receiving Webhooks, the full field reference on Webhook Events, and API keys on Authentication.

Add-on · $29/month · Requires Creator+ plan

Overview

Facebook Messenger and Instagram DMs share one transport (Meta's Messenger Platform) and one source.channel value: meta_dm. They are the default channel: subscribe to message.received and events begin flowing the moment a page is connected, with no further configuration.

Inbound event types

  • message.received

    A customer sends a DM on Facebook or Instagram.

  • message.reel_shared · message.post_shared

    A customer shares a reel or a regular post into a DM thread. Same envelope as message.received; the shared media arrives in message.attachments.

  • comment.received

    A customer comments on one of your posts or reels, independent of comment triggers. See Comment payload.

Supported send actions

  • send_message · react · unreact · typing_on

    Meta DM supports all four Send API actions, and it is the only channel that supports react and unreact.

ℹ️

Requirements: a connected Facebook Page and/or Instagram professional account (Settings → Connections) and the Webhook & Send API add-on active. No extra tier beyond Creator+ is required.

Source block on every Meta DM event
"source": {
  "platform": "instagram",  // or "facebook"
  "channel":  "meta_dm"
}

Inbound payload

A DM event uses the standard envelope (field reference). source.platform tells you which surface the message came from; everything else reads the same on both.

Meta-specific fields

  • source.platformstring

    facebook or instagram.

  • customer.platform_user_idstring

    The platform-assigned user ID (PSID). Pass this as platform_user_id to the Send API. Always present.

  • customer.platform_user_namestring|null

    Display name. Present in full profile only.

  • customer.platform_user_usernamestring|null

    Instagram @handle (no @). null for Facebook. Present in full profile only.

  • message.idstring

    Platform message ID. Use as target_message_id when adding a reaction.

  • message.attachmentsarray

    Media the customer sent. See attachment fields. Reel and post shares arrive as message.reel_shared / message.post_shared with the same envelope.

message.received · full profile
{
  "event_id":    "a3f8e1c2d4b567890abcdef012345678",
  "event_type":  "message.received",
  "occurred_at": "2026-02-20T08:15:00Z",
  "source": {
    "platform": "instagram",
    "channel":  "meta_dm"
  },
  "conversation": {
    "id": 10482
  },
  "customer": {
    "platform_user_id":       "17841400123456789",
    "platform_user_name":     "Jane Doe",
    "platform_user_username": "janedoe"
  },
  "message": {
    "id":          "mid.1234567890abcdef",
    "text_raw":    "Hi, do you have availability next Tuesday?",
    "attachments": []
  },
  "meta": {
    "version":         "v1",
    "payload_profile": "full",
    "generated_at":   "2026-02-20T08:15:00Z"
  }
}

Comment payload

A comment.received event fires for every comment on your Instagram or Facebook posts and reels; you don't need a ChatGenius comment trigger configured. It replaces the message object with a source_post object (the post the comment was left on) and a comment object. Use source_post.id as the stable attribution join key.

When the comment also matched one of your comment triggers, comment.trigger_id, comment.trigger_name, comment.matched_keyword, and source_post.url are populated; otherwise those fields are null.

Fields

  • conversation.idinteger|null

    Always null for comments (no conversation yet). The follow-up DM arrives as a separate message.received event with a populated id.

  • source_post.idstring

    ID of the post/reel the comment was left on. Always present; the attribution join key.

  • source_post.urlstring|null

    Permalink. Populated only when the comment matched a trigger targeting a specific post; null otherwise.

  • comment.idstring

    Platform comment ID.

  • comment.matched_keywordstring|null

    The trigger keyword matched, or null when no trigger matched.

  • comment.trigger_id · comment.trigger_nameinteger / string | null

    The matched comment trigger, or null.

  • comment.source_typestring

    comment, story, live, or both: the surface the trigger fired on.

comment.received · full profile
{
  "event_id":    "b7c2e1a4f9d063518adef0129876dcba",
  "event_type":  "comment.received",
  "occurred_at": "2026-02-20T08:15:00Z",
  "source": {
    "platform": "instagram",
    "channel":  "meta_dm"
  },
  "conversation": {
    "id": null
  },
  "customer": {
    "platform_user_id":       "17841400123456789",
    "platform_user_name":     null,
    "platform_user_username": "janedoe"
  },
  "source_post": {
    "id":  "17912345678901234",
    "url": "https://www.instagram.com/p/CtExAmple/"
  },
  "comment": {
    "id":              "17987654321098765",
    "text_raw":        "PRICE",
    "matched_keyword": "price",
    "trigger_id":      42,
    "trigger_name":    "Pricing DM",
    "source_type":     "comment"
  },
  "meta": {
    "version":         "v1",
    "payload_profile": "full",
    "generated_at":   "2026-02-20T08:15:00Z"
  }
}

Sending on Meta DM

Route by conversation_id, or by platform (facebook / instagram) plus platform_user_id (the customer's PSID). Request bodies, idempotency, response format, and errors are on the Send API reference: send_message, react, unreact, typing_on.

Channel limits

  • instagram1,000 chars
  • facebook2,000 chars

Examples on this page use the Send API. New integrations should prefer POST /v1/messages, which accepts the same body and returns the v1 envelope.

Endpoint
POST https://sumgenius.ai/api/meta/webhook-send.php
curl · reply to a DM
curl -X POST https://sumgenius.ai/api/meta/webhook-send.php \
  -H "X-SumGenius-Api-Key: sgwh_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "confirm-appt-10482-001",
    "conversation_id": 10482,
    "message_text":    "Your appointment is confirmed for Tuesday at 2pm."
  }'

The messaging window

Meta restricts when a business can message a customer. This is a platform rule, enforced by Meta, not a ChatGenius limit.

  • Standard 24-hour window

    After a customer's last message, you have 24 hours to reply freely.

  • 7-day human-agent extension

    When a human agent needs more time, Meta's human-agent tag extends the window to 7 days. ChatGenius applies this tag automatically when appropriate, so agent replies within 7 days go through without extra work on your side.

  • Outside the window

    A send is rejected as a permanent failure and is not retried. If you subscribe to message.send_failed you receive an event so your system can reconcile.

ℹ️

Reactions and typing indicators are Meta-only capabilities; no other channel supports them. Typing indicators skip the window check, since Meta allows sender_action outside the window.

Rejected outside the window
// one of:
{
  "success": false,
  "status":  "error",
  "error":   "Meta 7-day window expired."
}
{
  "success": false,
  "status":  "error",
  "error":   "Cannot send: customer has not initiated a valid messaging window."
}