# Instagram Private Replies API: Send a DM to a Commenter

How to send an Instagram private reply to a commenter with the API: webhooks, the comment_id request, the 7-day limit, buttons, permissions, and common errors.

Canonical page: https://www.tryadeli.com/blog/instagram-private-replies-api
Last updated: 2026-11-02

By Nick Reyes, Co-founder and CTO, Adeli. Published 2026-11-02.

## 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](https://community.make.com/t/send-private-dms-on-instagram-without-an-initial-client-message/81640/4), 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](https://developers.facebook.com/documentation/instagram-platform/private-replies):

| | 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](https://www.tryadeli.com/blog/instagram-api-unified-login) 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:

```bash
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](https://developers.facebook.com/documentation/instagram-platform/webhooks/setup) 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](https://developers.facebook.com/documentation/instagram-platform/webhooks/examples) show this shape for the `value`:

```json
{
  "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:

```bash
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:

```json
{
  "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](https://community.make.com/t/send-private-dms-on-instagram-without-an-initial-client-message/81640/2), 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](https://developers.facebook.com/documentation/instagram-platform/instagram-api-with-instagram-login/messaging-api/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:

```bash
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`:

```bash
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](https://www.tryadeli.com/blog/instagram-messaging-api) 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](https://developers.facebook.com/documentation/instagram-platform/instagram-api-with-unified-login/eligibility-and-troubleshooting).

**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](https://www.tryadeli.com/docs/api/messages/send-instagram-message) with `recipient: { commentId }`:

```bash
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](https://www.tryadeli.com/product/instagram) handles for you, as its docs describe:

- **The comment event.** A [webhook](https://www.tryadeli.com/docs/api/webhooks) 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](https://www.tryadeli.com/social-media-messaging-api) covers the inboxes it supports, and the [Instagram API comments guide](https://www.tryadeli.com/blog/instagram-api-comments) covers reading and moderating comments.

## 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.

## Related Adeli pages

- [Social Media Messaging API](https://www.tryadeli.com/social-media-messaging-api.md): Read Instagram, Facebook, and WhatsApp messages and reply to Instagram and Facebook DMs through the same API you publish with. No outbound or unsolicited messaging.
- [Instagram API for Developers](https://www.tryadeli.com/product/instagram.md): Publish, schedule, and read analytics for Instagram through one API. Adeli owns the Instagram developer app, token refresh, and Meta review. Free to start.
- [All posts on the Adeli blog](https://www.tryadeli.com/blog.md)

## About the author

Nick Reyes is the CTO behind Adeli and builds its API, its platform integrations, and the docs. He is a product engineer with 10 years of experience at Phantom, Airbnb, and Google.
