Instagram Private Replies API: Send a DM to a Commenter

By Nick ReyesPublished 6 min read

The short answer

The Instagram private replies API sends one DM to someone who commented on your post, reel, story, Live or ad. POST to /<IG_ID>/messages with the comment's ID as recipient.comment_id, within 7 days of the comment. You get one message per comment, and can write again only after the person responds. Adeli exposes it as one call with recipient.commentId.

The Instagram private replies API lets an Instagram professional account send one direct message to a person who commented on its post, reel, story, Live or ad. You call POST /<IG_ID>/messages with the comment's ID as the recipient, within 7 days of the comment, and Instagram delivers it to the commenter's inbox or message requests. It's the API behind comment-to-DM flows ("comment GUIDE and I'll send it to you").

Sending that first message is the easy part. The questions developers post are about what comes next:

"I was able to build an auto responder for IG, but still struggling how to send a DM after."

— @Juan_Carlos_Aguirre on the Make Community, August 2025

This guide covers the setup, the request, how to keep the conversation going, and the errors Meta returns when you break a rule.

What do you need before you start?

You need an Instagram professional account connected to your app, a token with the comment and messaging permissions, and a webhook subscription to comments. The token, host and permissions depend on which Instagram API setup your app uses. This table follows Meta's private replies guide:

Unified Login Instagram Login Facebook Login for Business
Token Business Integration System User Access Token Instagram User access token Facebook Page access token
Host graph.facebook.com graph.instagram.com graph.facebook.com
Send to /<IG_ID>/messages /<IG_ID>/messages /<PAGE_ID>/messages
Permissions instagram_basic, instagram_manage_comments, and instagram_manage_messages instagram_business_basic, instagram_business_manage_comments instagram_basic, instagram_manage_comments, pages_read_engagement
Webhook fields comments, live_comments comments, live_comments comments, live_comments

Unified Login needs the messaging permission too. Meta's requirements table says a Unified Login app "also needs instagram_manage_messages" to send private replies. If you're picking a setup, new Meta apps can't add Instagram Login any more; our Instagram API with Unified Login guide explains the three.

Two account settings matter. The account must be Business or Creator, and Allow access to messages has to be on in its Instagram settings, or messaging calls fail with error #200.

Step 1: Subscribe the account to comment webhooks

Subscribe each connected Instagram account to the comments field, so Meta tells your server when someone comments. Add messages and messaging_postbacks now if you plan to send buttons, because those fields carry the person's response. Meta's migration guide lists messages and messaging_postbacks under instagram_manage_messages, and comments and live_comments under instagram_manage_comments.

For a Unified Login account:

curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/subscribed_apps?subscribed_fields=comments,messages,messaging_postbacks" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

You also need a webhook callback URL verified for the Instagram object in the App Dashboard. Meta's webhooks setup guide covers the verify handshake and signature check.

Step 2: Read the comment ID from the webhook

Each comments webhook carries the comment's ID, the commenter's Instagram-scoped ID and username, the comment text, and the media ID. The comment ID is what you reply to. Meta's webhook examples show this shape for the value:

{
  "id": "<COMMENT_ID>",
  "from": {
    "id": "<INSTAGRAM_SCOPED_USER_ID>",
    "username": "<USERNAME>"
  },
  "text": "<COMMENT_TEXT>",
  "media": {
    "id": "<MEDIA_ID>",
    "media_product_type": "<MEDIA_PRODUCT_TYPE>"
  }
}

Before you reply, run your own checks:

  • Match the trigger. Compare text against your keyword ("GUIDE", "link") and skip everything else.
  • Skip your own comments. The account's replies under its own post arrive as comments too.
  • Dedupe by comment ID. Meta can deliver the same comment more than once, and a comment gets only one private reply.

Step 3: Send the private reply

Send the private reply with a POST to /<IG_ID>/messages, putting the comment ID in recipient.comment_id. On Unified Login:

curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/messages" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -d '{
    "recipient": { "comment_id": "<COMMENT_ID>" },
    "message": { "text": "Thanks for the comment! Here is the guide." }
  }'

A successful call returns two IDs:

{
  "recipient_id": "526...",
  "message_id": "aWdfZ..."
}

recipient_id is the commenter's Instagram-scoped ID (IGSID). It matched the webhook's from.id in our testing. Store it: it's the ID you'll message once the person responds.

Where it lands. Meta delivers the reply to the person's Inbox if they follow the account, and to their message Requests if they don't. That second case trips people up:

"Whenever we send the first message from someone not following us when they comment on a post, it asks for permission to the user to accept the request."

— @Madhav_Soni on the Make Community, May 2025

Write the first message so it makes sense as a request from a stranger: say which post it's about and what they asked for.

Step 4: Keep the conversation going with a button

After a private reply, your app can message the person again only once they respond, and then within 24 hours. A button gives them an easy way to respond. Meta's button template allows up to three buttons, and a postback button sends your payload back in a messaging_postbacks webhook.

You can send the button template as the private reply itself:

curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/messages" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -d '{
    "recipient": { "comment_id": "<COMMENT_ID>" },
    "message": {
      "attachment": {
        "type": "template",
        "payload": {
          "template_type": "button",
          "text": "Want the guide? Tap below and I will send it.",
          "buttons": [
            { "type": "postback", "title": "Send it", "payload": "guide-42" }
          ]
        }
      }
    }
  }'

When the person taps Send it, the postback webhook arrives with their IGSID and guide-42. Now the standard 24-hour window is open, so send the follow-up to recipient.id:

curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/messages" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -d '{
    "recipient": { "id": "<IGSID>" },
    "message": { "text": "Here you go: https://example.com/guide" }
  }'

The Instagram messaging API guide covers the 24-hour window and the human agent tag in more depth.

What are the limits on Instagram private replies?

Meta allows one private reply per comment, within 7 days of the comment, and nothing more until the person responds. The full set of rules from Meta's guide:

Rule Limit
Messages per comment One
Time to reply 7 days from the comment's creation time
Instagram Live comments Only during the broadcast
Follow-up messages Only after the person responds, within 24 hours of their response
Where it can be used Comments on posts, reels, stories, Live and ad posts
Delivery Inbox if they follow the account, Requests if not

Design for the limits. Don't queue private replies for comments older than a week, and don't send a "thanks" reply and then a separate "here's the link" reply to the same comment. Put everything, or a button, in the one message.

What errors does the private replies API return?

Most private reply failures come from the one-per-comment rule, the closed messaging window, a missing permission, or an account setting. These are the messages Meta returns:

Error When What to do
error_subcode 2534023: "The comment you are trying to reply to, already has a reply." A second private reply to the same comment Treat it as done. Dedupe by comment ID before sending.
code 10, error_subcode 2534022: "This message is sent outside of allowed window." A DM to the commenter before they responded Wait for a reply or a button tap, then send.
(#10) App is missing the instagram_manage_messages permission to access Instagram user information. Token lacks the messaging permission Add instagram_manage_messages to the configuration and have the client connect again.
(#200) The account owner has disabled access to Instagram Direct Messaging Outside of Instagram App. Allow access to messages is off The account owner turns it on in Instagram's settings.
(#10) Access is denied because the instagram account type is not business or creator. Personal account Switch to Business or Creator, then reconnect.

The first two are the responses we got from Graph API v25.0 while building Adeli's comment-to-DM support in October 2026. The last three come from Meta's Unified Login troubleshooting page.

A failed attempt doesn't use up the comment's reply. If your call fails on a permission or a network error, fix the cause and send again. The 7-day limit still applies.

Is there a faster way to send Instagram private replies?

Yes: Adeli sends an Instagram private reply in one API call, buttons included, and takes care of the webhooks and the Meta login. You call Send Instagram message with recipient: { commentId }:

curl -X POST https://app.tryadeli.com/api/v1/messages/instagram \
  -H "Authorization: Bearer $ADELI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "<ACCOUNT_ID>",
    "recipient": { "commentId": "17966240925214757" },
    "text": "Thanks for the comment! Tap below and I will send you the guide.",
    "buttons": [{ "type": "postback", "title": "Send it", "payload": "guide-request-42" }]
  }'

What Adeli's Instagram API handles for you, as its docs describe:

  • The comment event. A webhook you register gets a signed comment.created event for every new comment, with the commenter's ID in from.id.
  • The button tap. A message.postback event carries the person's ID and your payload, so you can send the follow-up with recipient: { id }.
  • Plain error codes. A second reply returns 409 private_reply_already_sent, and a DM before the person responds returns 409 window_closed.
  • The login. Customers connect Instagram through Meta's Unified Login with one button, and Adeli holds the token.

One limit to know: an account connected before Unified Login through a Facebook Page can't send private replies until it's reconnected. If DMs are only part of what you need, Adeli's social media messaging API covers the inboxes it supports, and the Instagram API comments guide covers reading and moderating comments.

faq

Frequently asked questions

Does a private reply open the 24-hour messaging window?

No. Sending a private reply doesn't let you message the person again. The 24-hour window opens only when they respond, for example by replying or tapping a button in your message. Until then, a second message is refused.

Where does an Instagram private reply show up?

In the commenter's Inbox if they follow the Instagram professional account, and in their message Requests folder if they don't, according to Meta's private replies guide. The message includes a link to the post they commented on.

Can I send private replies to old comments?

Only to comments made in the last 7 days. Meta counts the 7 days from the comment's creation time, so a backlog job that replies to older comments fails. Comments on Instagram Live can only get a private reply while the broadcast is still running.

Power your next project
with one ads & social media API

Give your users publishing, scheduling, and analytics through one integration your team can actually maintain.

Try with agents

Start with free credits. No credit card required.