Skip to content

Inbox

The Instagram side of a channel, handled by hand: its publications and the comments under them (read, reply, hide, delete), and the direct messages (the conversations, and sending one). What answers on its own — a template posed on a publication — is on Automations. These endpoints do not exist in the original project, and they are Instagram-only.

GET /inbox/media/{integrationId} recent posts
GET /inbox/stories/{integrationId} stories live right now
GET /inbox/comments/{integrationId}/{mediaId} live comments on a post
POST /inbox/comments/{commentId}/reply reply publicly
POST /inbox/comments/{integrationId}/{commentId}/hide hide or unhide
DELETE /inbox/comments/{integrationId}/{commentId} delete
GET /inbox/{integrationId} list conversations
GET /inbox/{integrationId}/{conversationId} read one
POST /inbox/{integrationId}/send send a message
POST /inbox/{integrationId}/poll read the inbox now
POST /inbox/{integrationId}/subscribe-webhook opt the account into Meta's webhook

GET /inbox/media/{integrationId} lists recent posts. Their id is what a pose stores as mediaId. GET /inbox/stories/{integrationId} lists the stories live right now — the only window in which a template can be posed on a story.

GET /inbox/comments/{integrationId}/{mediaId} reads the comments on a post.

POST /inbox/comments/{commentId}/reply answers publicly (201):

{ "integrationId": "instagram-123", "message": "Envoyé, check tes DM 📬" }

message is 1 to 2,200 characters, Instagram’s cap on a comment.

POST /inbox/comments/{integrationId}/{commentId}/hide hides a comment ({ "hide": true }) or shows it again ({ "hide": false }). A hidden comment stays visible to its author only; the list of live comments carries hidden: true on it. DELETE /inbox/comments/{integrationId}/{commentId} deletes it on Instagram, for good. Both answer { "success": true } (201 for the hide, 200 for the delete).

GET /inbox/{integrationId}?limit=25

limit defaults to 25; anything unparseable falls back to 25.

Conversations come back sorted by [box, last message from the person], which is what keeps an automatic message from pushing a real question down the list. The boxes are To reply, Conversations, Full auto and All, and they are ours: Instagram does not expose its own Primary / General / Requests folders through the API.

GET /inbox/{integrationId}/{conversationId}

Returns the thread: messages, attachments, the button templates the flows sent, and story replies.

POST /inbox/{integrationId}/send

Field Type Required Description
recipientId string Yes The person’s Instagram-scoped ID (IGSID)
text string Yes 1 to 1,000 characters
linkUrl string No Absolute URL. Sent as a button
linkButtonText string No ≤ 20 — Instagram’s cap
{
"recipientId": "17841400000000000",
"text": "Le voilà 👇🏻",
"linkUrl": "https://example.com/guide-malte",
"linkButtonText": "Le guide Malte"
}

POST /inbox/{integrationId}/poll reads the 25 most recent conversations now and hands any message a missed webhook would have delivered to the automations waiting on that person (a button tapped, an email typed). Nothing does this on a schedule: the webhook is the normal path, this is the catch-up.

It answers:

{ "conversations": 25, "handled": 1 }

conversations is how many were read from Meta, handled how many inbound messages reached a waiting automation.

POST /inbox/{integrationId}/subscribe-webhook opts the account into Meta’s webhook delivery for comments and messages. That webhook is what makes an automation fire in seconds; without it, nothing fires until a poll is run by hand. UseNadia does it itself when a channel connects, when a template is posed, and at every restart.