Inbox messages
Read direct message conversations on Facebook, Instagram, Bluesky and Mastodon, send replies within each platform's rules and mark conversations done.
https://post.adaptlypost.com/post/api/v1/inbox/conversationsReturns direct message conversations, the one with the latest message first. Answers { conversations, total, hasMore, nextCursor }.
Every role holds inbox.read, so any valid key can read the inbox.
Query parameters
| Parameter | Type | Description |
|---|---|---|
accountIds | string[] | Only these accounts, by the id from GET /social-accounts. Repeat the key or separate values with commas. Up to 50 |
platforms | PlatformType[] | Only these platforms. Repeat the key or separate values with commas |
statuses | InboxStatus[] | Only items in these states: UNREAD, READ or DONE. Repeat the key or separate values with commas |
since | string (ISO 8601) | Only items created on the platform at or after this date-time |
search | string | Text to search for |
limit | number | Items per page, 1 to 100. Default 25 |
cursor | string | The nextCursor of the previous page. nextCursor is null on the last page |
About 10 minutes, not real time
AdaptlyPost reads each connected account every 10 minutes and keeps what it finds. The lists answer from that copy, so a new comment, mention, message or review shows up within about 10 minutes. POST /api/v1/inbox/refresh asks for a read now. Webhook events come from the same reads.Channels that need a reconnect
Every channel is open to the API. When a connection lacks the platform permission for a channel or action, including permissions the platform is still reviewing for AdaptlyPost, GET /api/v1/inbox/summary shows the channel as RECONNECT_REQUIRED and every write on it answers 403 inbox_reconnect_required. An expired token answers the same. Ask the user to reconnect the account in AdaptlyPost; retrying does not help.Conversation fields
| Field | Description |
|---|---|
id | Conversation id. Use it with the endpoints below |
accountId | The account the item belongs to: its id from GET /social-accounts |
platform | The platform, as a PlatformType |
accountName | Display name of that account |
participant | The other person: id, name, username and avatarUrl |
lastMessageText | Text of the latest message |
lastMessageAt | When the latest message was sent |
lastMessageIsOwn | True when your account sent the latest message |
status | UNREAD, READ or DONE. A conversation turns UNREAD when the other person writes and nobody has answered since, so a reply sent from the platform's own app keeps it read |
repliedAt | When your account last replied, or null |
replyWindowEndsAt | Facebook and Instagram: when the 24-hour reply window closes, counted from the last message AdaptlyPost read. null on other platforms |
maxMessageLength | The longest message the platform accepts in this conversation |
capabilities | canReply: false once the reply window has closed or the platform does not let the account send |
Read a conversation
https://post.adaptlypost.com/post/api/v1/inbox/conversations/:idReturns { conversation, messages }: the conversation and the messages AdaptlyPost has read from it. An unknown id answers 404 inbox_item_not_found. Each message has these fields:
| Field | Description |
|---|---|
id | Message id |
isOwn | True when your account sent it |
text | The message text |
hasAttachments | True when the message carries images or files. The API returns the text only |
createdAt | When it was sent |
Send a message
https://post.adaptlypost.com/post/api/v1/inbox/conversations/:id/messagesSends a message from the account in the conversation and answers 201 { conversation, message }.
Writes need inbox.reply (Admin and Editor) and an active AdaptlyPost plan. Without the plan they answer 403 subscription_required.
Body parameters
| Parameter | Type | Description |
|---|---|---|
textREQUIRED | string | The message, up to maxMessageLength of the conversation |
The 24-hour window on Facebook and Instagram
Facebook and Instagram let a business answer only within 24 hours of the person's last message. The send still goes to the platform after replyWindowEndsAt, because the person may have written since the last read; when the platform refuses it, the call answers 400 inbox_messaging_window_closed. Bluesky messages need an app password with direct message access.Mark as read or done
https://post.adaptlypost.com/post/api/v1/inbox/conversations/statusSets the status of up to 100 conversations and answers { conversations, unreadCount }.
Body parameters
| Parameter | Type | Description |
|---|---|---|
idsREQUIRED | string[] | 1 to 100 ids from the list |
statusREQUIRED | InboxStatus | UNREAD, READ or DONE |
Refusals
A refused call answers { statusCode, error, code, message }. Branch on code. message explains the refusal in words.
| Code | Status | When, and what to do |
|---|---|---|
inbox_item_not_found | 404 | The id does not exist or belongs to another workspace. Stop |
inbox_action_unsupported | 400 | The platform, or this item, does not allow this hide, delete or like. capabilities says what applies. Stop |
inbox_reconnect_required | 403 | The connection lacks the permission for this channel or action, including one still in platform review, or its token expired. Ask the user to reconnect the account in AdaptlyPost. Do not retry |
inbox_reply_invalid | 400 | The text is empty or over the limit. The message names the limit. Fix the text |
inbox_messaging_window_closed | 400 | Facebook or Instagram: the 24-hour reply window has passed. Stop |
inbox_rate_limited | 429 | The platform rate limited AdaptlyPost. Retry after a while |
inbox_platform_error | 503 | The platform failed. Retry later |
permission_denied | 403 | The key's role lacks inbox.read or inbox.reply. Do not retry |
subscription_required | 403 | A write without an active AdaptlyPost plan. Do not retry |
curl --request GET \
--url 'https://post.adaptlypost.com/post/api/v1/inbox/conversations?statuses=UNREAD' \
--header 'Authorization: Bearer <api-key>'curl --request GET \
--url https://post.adaptlypost.com/post/api/v1/inbox/conversations/cnv_5d0e7a19 \
--header 'Authorization: Bearer <api-key>'
200
{
"conversation": { "id": "cnv_5d0e7a19", "...": "..." },
"messages": [
{
"id": "msg_a1f20c33",
"isOwn": false,
"text": "Hi, do you ship to Portugal?",
"hasAttachments": false,
"createdAt": "2026-11-08T08:55:02.000Z"
}
]
}curl --request POST \
--url https://post.adaptlypost.com/post/api/v1/inbox/conversations/cnv_5d0e7a19/messages \
--header 'Authorization: Bearer <api-key>' \
--header 'Content-Type: application/json' \
--data '{ "text": "Yes, delivery to Portugal takes 3 to 5 days." }'curl --request POST \
--url https://post.adaptlypost.com/post/api/v1/inbox/conversations/status \
--header 'Authorization: Bearer <api-key>' \
--header 'Content-Type: application/json' \
--data '{ "ids": ["cnv_5d0e7a19"], "status": "DONE" }'{
"conversations": [
{
"id": "cnv_5d0e7a19",
"accountId": "conn_fb_page_001",
"platform": "FACEBOOK",
"accountName": "AdaptlyPost",
"participant": {
"id": "7230011122233344",
"name": "João Silva",
"username": null,
"avatarUrl": null
},
"lastMessageText": "Hi, do you ship to Portugal?",
"lastMessageAt": "2026-11-08T08:55:02.000Z",
"lastMessageIsOwn": false,
"status": "UNREAD",
"repliedAt": null,
"replyWindowEndsAt": "2026-11-09T08:55:02.000Z",
"maxMessageLength": 2000,
"capabilities": { "canReply": true }
}
],
"total": 2,
"hasMore": false,
"nextCursor": null
}