Comments & inbox

Read, reply to and moderate comments, inbound events, and Instagram and Messenger direct messages.

Comments

MethodPathDescription
GET/posts/{id}/commentsComments on the published targets of a post
POST/comments/{id}/replyBody {platformPostId, text}: reply to a comment (Instagram, Facebook, Threads; X coming soon)
GET/inbox/comments?postId= or ?accountId=&platformPostId=; limit, after (Instagram, Facebook, Threads)
POST/inbox/commentsBody {accountId, platformPostId, text}: top-level comment as the account
POST/inbox/comments/{commentId}/replyBody {accountId, text}
POST/DELETE/inbox/comments/{commentId}/hideHide / unhide; {accountId} in body or query
POST/DELETE/inbox/comments/{commentId}/likeLike / unlike (Facebook only); {accountId}
DELETE/inbox/comments/{commentId}Delete a comment (Instagram, Facebook); ?accountId=
GET/inbox/eventsInbound Meta webhook events; ?kind=comment|mention|reply|feed|message|other&accountId&limit
GET/accounts/{id}/mentionsMedia the Instagram account was tagged in; ?limit= (default 25)

While approval applies to the key, organization or account, replies and moderation are queued for a person: the request answers 202 {id, status: "pending_approval"} and runs once a member approves it in the dashboard (see Approval; follow it with GET /actions/{id} or the action.* webhooks). New comments and mentions arrive as comment.received / mention.received webhooks once the account is subscribed to Meta webhooks (POST /accounts/{id}/webhook-subscription).

Direct messages

Instagram (Instagram API with Instagram Login) and Facebook Page Messenger conversations. The account needs instagram_business_manage_messages (Instagram) or pages_messaging (Facebook Pages); without it the endpoints that call Meta answer 403 missing_permission and accounts connected earlier must reconnect.

  • Inbound: Meta webhooks deliver new messages, echoes, reads, deliveries, reactions and postbacks. Postgale stores them as conversations and messages (deduplicated by Meta message id), as inbound events of kind message, and sends the message.* webhooks. The account must be subscribed to the messaging fields (POST /accounts/{id}/webhook-subscription).
  • Messaging window: Meta only lets the business reply to someone who wrote first. Free-form messages are allowed for 24 hours after the participant's last message. With tag: "HUMAN_AGENT" a person (not automation) can reply up to 7 days after it; the Meta app needs the Human Agent permission. Outside the window POST …/messages answers 409 outside_messaging_window before anything is sent. Every conversation reports messagingWindow {open, closesAt, humanAgentClosesAt}.
  • Sending: text (Instagram ≤1000, Messenger ≤2000 characters) or one attachment (mediaUrl, or mediaId of an upload; attachmentType image | video | audio | file), not both. It is a live message to a real person and cannot be edited or deleted. While approval applies it is queued for a person (202 pending_approval): a member approves it as is, edits the text or rejects it; the window is checked before queueing and again when it runs.
  • Read: POST …/read sets unreadCount to 0 and sends mark_seen to Meta (only while the window is open; failures come back as warnings). Archived conversations become active again on the next inbound message.
  • Sync: POST /inbox/conversations/sync backfills up to pages (default 3, max 10) × limit (default 25, max 100) conversations. Meta returns details only for the 20 most recent messages of each conversation, so older history is not available. Syncs are idempotent and emit no webhooks.
message.received
{
  "id": "cmdlv0a1b0001x2y3z4",
  "event": "message.received",
  "createdAt": "2026-10-18T09:15:02.481Z",
  "data": {
    "eventId": "cmdlv09zz0000x2y3z4",
    "platform": "instagram",
    "accountId": "acc_instagram",
    "externalId": "cust-1",
    "conversationId": "cmdluz8k70003a1b2c3",
    "messageId": "cmdlv0a0q0002x2y3z4",
    "platformMessageId": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlE",
    "platformMessageIds": [
      "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlE"
    ],
    "direction": "inbound",
    "participant": {
      "id": "1234567890123456",
      "username": "curious_shopper",
      "name": null
    },
    "text": "Hi! Do you ship to Canada?",
    "attachments": [],
    "postback": null,
    "reaction": null,
    "watermark": null,
    "sentAt": "2026-10-18T09:15:00.000Z",
    "receivedAt": "2026-10-18T09:15:02.470Z"
  }
}

Conversation endpoints

MethodPathDescription
GET/inbox/conversationsInstagram, Messenger and WhatsApp conversations, latest first; ?accountId&platform=instagram|facebook|whatsapp&status=active|archived&unread=true&limit&cursor
POST/inbox/conversations/syncBody {accountId, limit?, pages?}: backfill conversations and their latest messages from Meta
GET/inbox/conversations/{id}One conversation with its messagingWindow
PATCH/inbox/conversations/{id}Body {status: active | archived}
GET/inbox/conversations/{id}/messagesMessages, oldest to newest; ?limit&before (nextBefore of the previous page)
POST/inbox/conversations/{id}/messagesBody {text? | mediaUrl? | mediaId?, attachmentType?, tag?: HUMAN_AGENT}: send a live DM (201). WhatsApp also takes template, interactive, location, reaction, whatsappMediaId, replyTo
POST/inbox/conversations/{id}/readBody {platform?}: mark read, and seen on Meta unless platform is false
POST/inbox/conversations/{id}/syncBody {limit?}: fetch the latest messages of one conversation from Meta

WhatsApp conversations use the same endpoints; see the WhatsApp guide. X direct messages are coming soon; the planned API is in the X guide.

On this page