Inbox

Read and send Instagram direct messages through Onepostly.

Read and send Instagram DMs on a connected Business or Creator account.

List Conversations

import { Configuration, InboxApi } from "@onepostly/sdk";

const inboxApi = new InboxApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await inboxApi.listInboxConversations({
  accountId: "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  limit: 50,
});
console.log(response);
{
  "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  "convos": [
    {
      "id": "conv_a3f9c1d2",
      "members": [
        {
          "id": "17841400987654321",
          "username": "buyer",
          "displayName": "Buyer"
        }
      ],
      "muted": false,
      "unreadCount": 2,
      "lastMessage": {
        "id": "mid_abc123",
        "text": "Hi, is this available?",
        "sentAt": "2026-09-08T12:00:00.000Z"
      }
    }
  ],
  "cursor": null
}

Read Messages

Newest first. A conversation id returned by create (a bare user id before the first message) reads as empty until someone writes in it. Media messages carry text: null plus an attachments entry (image, video, audio, file, or other with a direct URL).

import { Configuration, InboxApi } from "@onepostly/sdk";

const inboxApi = new InboxApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await inboxApi.listInboxMessages({
  convoId: "conv_a3f9c1d2",
  accountId: "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  limit: 50,
});
console.log(response);
{
  "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  "convoId": "conv_a3f9c1d2",
  "messages": [
    {
      "id": "mid_abc123",
      "text": "Hi, is this available?",
      "senderId": "17841400987654321",
      "sentAt": "2026-09-08T12:00:00.000Z",
      "attachments": []
    },
    {
      "id": "mid_abc124",
      "text": null,
      "senderId": "17841400987654321",
      "sentAt": "2026-09-08T12:01:00.000Z",
      "attachments": [
        {
          "type": "image",
          "url": "https://cdn.example.com/size-chart.jpg"
        }
      ]
    }
  ],
  "cursor": null
}

Start a Conversation

Accepts a username (leading @ optional) or a numeric user id. Pass the numeric id to skip the lookup. Returns a conversation shell. The first sent message opens the thread on Instagram.

import { Configuration, InboxApi } from "@onepostly/sdk";

const inboxApi = new InboxApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await inboxApi.createInboxConversation({
  createInboxConversationBody: {
    "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
    "recipient": "buyer"
  },
});
console.log(response);
{
  "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  "convo": {
    "id": "17841400987654321",
    "members": [
      {
        "id": "17841400987654321",
        "username": "buyer",
        "displayName": null
      }
    ],
    "muted": false,
    "unreadCount": 0,
    "lastMessage": null
  }
}

Send a Message

Text is limited to 1,000 characters. Attach an image, video, audio file, or PDF with attachmentUrl (public HTTPS URL).

import { Configuration, InboxApi } from "@onepostly/sdk";

const inboxApi = new InboxApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await inboxApi.sendInboxMessage({
  sendInboxMessageBody: {
    "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
    "convoId": "conv_a3f9c1d2",
    "text": "Yes, it is in stock!"
  },
});
console.log(response);
{
  "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  "message": {
    "id": "mid_def456",
    "text": "Yes, it is in stock!",
    "senderId": "17841400008460056",
    "sentAt": "2026-09-08T12:00:00.000Z",
    "attachments": []
  }
}

Rich Messages

Add quickReplies (max 13 tappable replies) to any text message. Add buttons (max 3, web_url or postback) for a button template, or templateElements (max 10) for a generic carousel. Attachments cannot be combined with buttons or carousel elements:

import { Configuration, InboxApi } from "@onepostly/sdk";

const inboxApi = new InboxApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await inboxApi.sendInboxMessage({
  sendInboxMessageBody: {
    "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
    "convoId": "conv_a3f9c1d2",
    "text": "Pick a color:",
    "quickReplies": [
      {
        "title": "Red",
        "payload": "PICK_RED"
      },
      {
        "title": "Green",
        "payload": "PICK_GREEN"
      }
    ]
  },
});
console.log(response);
{
  "accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
  "message": {
    "id": "3k7y...",
    "text": "Hey, loved your latest post!",
    "senderId": "did:plc:alice",
    "sentAt": "2026-09-08T12:00:00.000Z",
    "attachments": [
      {
        "type": "image",
        "url": "https://cdn.example.com/photo.jpg"
      }
    ]
  }
}

Private Replies

Answer a post comment with a DM instead of a public reply. One per comment, same 7-day window:

import { Configuration, CommentsApi } from "@onepostly/sdk";

const commentsApi = new CommentsApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);

const response = await commentsApi.createPrivateReply({
  body: {
    "post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
    "commentId": "17890123456789012",
    "text": "Thanks! Check your DMs."
  },
});
console.log(response);
{
  "reply": {
    "postId": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
    "destinationId": "d9e8f7a6-5b4c-4a3d-8e2f-1a2b3c4d5e6f7",
    "platform": "instagram",
    "commentId": "17890123456789012",
    "reply": {
      "id": "mid_def456",
      "text": "Thanks! Check your DMs.",
      "timestamp": "2026-09-08T12:00:00.000Z"
    }
  }
}

Webhooks

Inbound messages also arrive as inbox webhooks.

Errors

CodeCauseFix
INBOX_PERMISSIONConnection lacks messaging accessReconnect with messaging scope; check Website permissions
RECIPIENT_NOT_FOUNDUsername or id could not be resolvedUse a valid username or numeric id
TEXT_TOO_LONGOver 1,000 charactersTrim the text
INVALID_ATTACHMENTattachmentUrl is not a public HTTPS URLUse a direct HTTPS media URL
INVALID_QUICK_REPLIESMore than 13 quick repliesKeep at most 13
INVALID_TEMPLATEToo many buttons/elements, missing button url/payload, or attachment combined with a templateMax 3 buttons, 10 elements; web_url needs url, postback needs payload
MESSAGE_WINDOW_EXPIRED24-hour window lapsedWait for the customer to message again
TOKEN_INVALIDConnection token expired or revokedReconnect the account

See Also