> For the complete documentation index, see [llms.txt](https://help.blotato.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.blotato.com/start-with-an-ai-agent/llm/messages.md).

# Message requests

Resolve Instagram or Facebook message recipients, respect messaging windows, and verify an authorized send without duplicates.

Compact reference for agents making REST requests. All endpoint paths below are relative to `https://backend.blotato.com/v2`. For task instructions, read the [workflow guide](/agent-workflows/agent-workflows/messages.md). For tool calls, use the [MCP reference](/start-with-an-ai-agent/mcp/tools.md).

## Manage private messages

Read the conversation and incoming message before sending. Match the account, platform, recipient, and Facebook Page to the user's request. Stop if the recipient ID is unavailable. A request to draft a reply does not authorize sending it.

```
Messages are private, direct messages sent through the platform inbox (DMs). Read conversations and messages, and send a direct message or a private
reply to a comment.

Supported platforms: instagram, facebook

Notes:
- Blotato does not backfill direct messages. It captures new messages received after the account connects with the required permissions.
- Refresh the Inbox after a new message arrives.
- Messages are retained for up to 45 days.
- Standard DMs reply to people who messaged you. Private replies answer a comment.
  No cold outreach.
- Platforms apply strict messaging windows. Review "MESSAGING WINDOWS" before sending messages.
- Reaching a new contact counts toward the monthly active-contacts limit.
  More messages to the same active contact do not add another contact that month.
  Read contacts and contactsLimit from GET /users/me/usage for the current limit.

List conversations:
GET /conversations?limit=20&cursor=OPTIONAL_CURSOR&accountId=OPTIONAL_ACCOUNT_ID&platform=OPTIONAL_PLATFORM
Response: { "items": [ <Conversation>, ... ], "cursor": "..." }

Get a conversation:
GET /conversations/:conversationId
Response: a <Conversation> object

<Conversation>:
{
  "id": "cnv_abc123",
  "accountId": "98434",
  "platform": "instagram",
  "participants": [
    { "id": "1784000000", "name": "Jamie", "username": "jamie", "profileImageUrl": null }
  ],
  "createdAt": "2026-07-01T12:00:00Z",
  "updatedAt": "2026-07-02T09:30:00Z"
}

List messages:
GET /messages?limit=20&cursor=OPTIONAL_CURSOR&conversationId=OPTIONAL_CONVERSATION_ID&platform=OPTIONAL_PLATFORM
Response: { "items": [ <Message>, ... ], "cursor": "..." }

Send a message only when sending is authorized:
POST /messages
{
  "accountId": "required-account-id",
  "recipientId": "id-of-contact-to-send-message-to",
  "text": "Thanks for reaching out!",
  "target": { "targetType": "instagram" }
}
Response: a <Message> object. Save response.id and inspect response.status.
An accepted message is not proof of sending, delivery, or reading.

PLATFORM-SPECIFIC FIELDS:

instagram:
  text limit: 1000 bytes
  Direct message, reply to a contact within the 24-hour window:
    recipientId: the incoming message's senderId
    target.targetType: "instagram"
  Private reply to a comment, once, within 7 days of the comment:
    recipientId: the comment's authorId
    target.targetType: "instagram"
    target.commentId: "Blotato-comment-id-not-platformCommentId"
facebook:
  text limit: 2000 characters
  target.pageId (the Facebook Page to send from) is required on every Facebook message
  Direct message, reply to a contact within the 24-hour window:
    recipientId: the incoming message's senderId
    target.targetType: "facebook"
    target.pageId: "id-of-page-to-send-from"
  Private reply to a comment, once, within 7 days of the comment:
    recipientId: the comment's authorId
    target.targetType: "facebook"
    target.pageId: "id-of-page-to-send-from"
    target.commentId: "Blotato-comment-id-not-platformCommentId"

Poll: GET /messages/:messageId
Status values: "queued" | "processing" | "sent" | "delivered" | "failed"
- sent: an outgoing message was sent, not proof the recipient read it
- delivered: an incoming message was received
- failed: stop and inspect errorMessage and errorCode
- queued or processing: check the saved ID within a bounded wait
When the wait budget ends, report the saved ID and pending state. Do not send again.
If no ID was received, inspect existing messages and report the uncertain outcome
before repeating a write.

<Message>:
{
  "id": "msg_abc123",
  "conversationId": "cnv_abc123",        // null when not linked to a conversation
  "platform": "instagram",
  "direction": "incoming",               // "incoming" received, "outgoing" you sent
  "senderId": "1784000000",              // null if unknown
  "recipientId": "17841400000000000",
  "text": "Hi! Is this available?",
  "payload": null,                       // rich content, see BUTTONS AND QUICK REPLIES
  "status": "delivered",
  "errorCode": null,
  "errorMessage": null,
  "createdAt": "2026-07-02T09:30:00Z"
}

BUTTONS AND QUICK REPLIES (instagram, facebook):
Set on target. Mutually exclusive - send buttons OR quickReplies, never both (422).

Buttons (1-3, pinned under the message):
  "target": {
    "targetType": "instagram",
    "attachment": {
      "type": "button",
      "buttons": [
        { "type": "web_url",  "title": "View pricing",  "url": "https://example.com" },
        { "type": "postback", "title": "Talk to sales", "payload": "SALES" }
      ]
    }
  }
  - type: "web_url" (opens a link) or "postback" (reports the tap back). No phone buttons.
  - title: 1-20 characters
  - url: required for web_url, starts with https://
  - payload: required for postback, 1-1000 characters
  - text is REQUIRED and capped at 640 characters when buttons are set
  - INSTAGRAM: buttons render in the Instagram mobile app only. A recipient reading
    the conversation on instagram.com in a desktop browser sees the text with no
    buttons. Send an attachment OR a URL inside text, never both - a message carrying
    both leaves the URL in text unclickable on desktop. For a desktop audience, drop
    the attachment and put the URL in text.

Quick replies (1-13 tappable chips, disappear after a tap or a typed reply):
  "target": {
    "targetType": "instagram",
    "quickReplies": [
      { "title": "Small", "payload": "SIZE_S" },
      { "title": "Large", "payload": "SIZE_L" }
    ]
  }
  - title: 1-20 characters
  - payload: 1-1000 characters
  - text is REQUIRED and non-empty

Reading a tap: both chip taps and postback taps arrive as the next INCOMING
message carrying payload.selection, but they reach you differently:
  - Quick reply: the tap sends a REAL TEXT MESSAGE. text holds the chip label,
    and payload.selection is attached alongside it.
      { "text": "Large",
        "payload": { "selection": { "type": "quick-reply", "payload": "SIZE_L" } } }
  - Postback: NO text message is sent. The tap is recorded as an incoming
    message with text set to the button label, plus payload.selection.
      { "text": "Talk to sales",
        "payload": { "selection": { "type": "postback", "payload": "SALES" } } }
  - Branch on selection.payload, NOT on text. Two chips sharing a label are
    distinguishable only by payload.
  - selection.payload is the string returned with the incoming tap. It is nullable
    when the platform webhook supplies no payload. When creating a postback button
    through POST /messages, payload is required and must contain 1-1000 characters.
  - web_url buttons produce NO selection
  - Blotato subscribes your account to the postback webhook when you connect it.
    If you connected your account before buttons were launched, reconnect in
    Accounts to start receiving postback events. Quick replies
    need no reconnect.

Outgoing messages you sent echo their own payload.attachment / payload.quickReplies.

MESSAGING WINDOWS:
- Standard DM: reply within 24 hours of the person's last message.
- Private reply to a comment: set target.commentId. Allowed once, within 7 days of the
  comment. After it, message the person again only after they open a new 24-hour window.
```

Return to the [agent reference index](/start-with-an-ai-agent/llm.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.blotato.com/start-with-an-ai-agent/llm/messages.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
