What the Instagram Messaging API Is
The Instagram Messaging API is the part of Meta's Instagram Platform that lets an app send and receive direct messages for an Instagram professional account. A person messages your account, Meta sends a webhook notification to your server, and your app replies through a POST to the /messages endpoint. The same API can send a private reply to someone who commented on a post or Reel.
Two details shape everything else:
- It only works for professional accounts. Meta's documentation says app users need an Instagram professional account, which means a business or creator account. Personal accounts are out.
- It is a reply API, not a broadcast API. Meta's docs state that your app can only message an Instagram user after that user has sent your account a message. For commenters, the exception is a single private reply. There is no endpoint for messaging a list of people who never contacted you.
If you are building an Instagram comment-to-DM workflow or any DM automation, this is the API underneath it. Everything below was checked against Meta's developer documentation in October 2026, and Meta changes these pages often, so treat the linked docs as the source of truth.
Turn Instagram DMs into booked calls
AI that qualifies leads, handles objections, and follows up - so you don't have to.
Two Ways In: Instagram Login vs Facebook Login
Meta currently documents two configurations of the Instagram API. They differ in how users log in, which permissions you request, and which host you call.
| Instagram API with Instagram Login | Instagram API with Facebook Login | |
|---|---|---|
| Account login | Instagram credentials (Business Login for Instagram) | Facebook credentials (Facebook Login for Business) |
| Facebook Page required | No | Yes, linked to the Instagram account |
| Permissions | instagram_business_* family | instagram_* family plus Page permissions |
| API host | graph.instagram.com | graph.facebook.com |
| Messaging | Supported directly | Through the Messenger Platform |
| Access token | Instagram User access token | Facebook User or Page access token |
For a new messaging integration serving Instagram-only businesses, Instagram Login is the lighter route because the account owner does not need a Facebook Page. Facebook Login is the better fit when you already run Page-linked integrations or need features Meta lists only for that setup, such as hashtag search.
The rest of this guide uses Instagram Login and graph.instagram.com, because that is the simplest path to a working send.
What You Need Before You Start
An Instagram professional account. Business or creator. Switch a personal account to a professional one before you test. Our guide to switching a personal account to professional has the steps.
A Meta developer app. Register as a Meta developer, create an app in the App Dashboard, and add the Instagram product with "API setup with Instagram login". There you get your Instagram App ID and App Secret, and you configure Business Login.
The right permissions. For Instagram Login, the messaging-related ones are:
instagram_business_basicinstagram_business_manage_messages(send and receive DMs)instagram_business_manage_comments(needed for private replies to comments)
Meta also lists a Human Agent feature for responding after the standard window closes, covered below.
The right access level. This is where most projects stall.
- Standard Access is the default. It is meant for people who have a role on your app and for development. If your app only serves an Instagram account you own or manage, Standard Access is all you need.
- Advanced Access is required when your app serves Instagram professional accounts you do not own or manage, which is what any customer-facing product does. It requires App Review and Business Verification.
Meta's webhooks setup guide adds that your app must be set to Live to receive notifications for app users, and that Advanced Access and business verification are required for production access. Plan for review time before a launch date. App Review is how Meta checks that your app uses each permission in an approved manner.
A way to get tokens. The login flow works like this:
- Send the user to your embed URL with the scopes you need.
- Meta redirects back with an authorization code, valid for one hour and single use.
- Exchange the code for a short-lived Instagram User access token (valid for one hour) with a
POSTtoapi.instagram.com/oauth/access_token. - Exchange that for a long-lived token (valid for 60 days) with a server-side
GETtograph.instagram.com/access_tokenusinggrant_type=ig_exchange_token. Meta is explicit that this call includes your app secret and must never run in client-side code. - Refresh the long-lived token before it expires with
grant_type=ig_refresh_tokenongraph.instagram.com/refresh_access_token. The token must be at least 24 hours old and still valid. A token that goes 60 days without a refresh expires and cannot be refreshed.
Token refresh is the single most common cause of an integration that works for two months and then silently stops.
How Messaging Works: Webhooks, Windows, and Private Replies
Webhooks
Meta strongly recommends webhooks over polling, and for incoming messages they are the practical choice. You create an HTTPS endpoint with a valid certificate (self-signed certificates are not supported), subscribe your app to fields, and enable notifications for each account.
For Instagram Login messaging, the subscription fields listed in the docs are:
messagesmessaging_optinsmessaging_postbacksmessaging_reactionsmessaging_referralsmessaging_seen
For comments and private replies you subscribe to comments (and live_comments for Live).
Your endpoint has to handle two request types. First, a verification GET that carries hub.mode, hub.verify_token, and hub.challenge, where you check the token and echo the challenge back. Second, event POST requests signed with an X-Hub-Signature-256 header, which is an SHA-256 signature generated with your app secret. Meta says validating it is optional but recommended. Respond with 200 quickly.
A few webhook facts that bite in production:
- Failed deliveries are retried with decreasing frequency for up to 36 hours, so handle duplicates.
- Webhooks have no history. If you drop an event, you cannot ask Meta to replay it.
- A message you send yourself comes back as an event with
is_echoset, so ignore your own echoes. - Comment notifications only fire for public accounts.
The messaging window
You can reply to a person during the standard messaging window. For most user actions that is 24 hours from their last message. When the action is a person's first message after clicking a Click-to-Direct ad, Meta says the window may last up to 7 days from that message.
If a human needs more time, the Human Agent feature lets your app send a reply tagged human_agent within 7 days of the user's message. Meta limits its use to human support when an issue cannot be resolved in the standard window, such as a weekend or a case that takes more than 24 hours. The feature requires App Review.
Private replies to comments
When someone comments on your post, Reel, story, Live, or ad post, a webhook fires with the comment ID. You can then send a private reply by posting to /<IG_ID>/messages with recipient: { comment_id } instead of a user ID.
Meta's rules for private replies are strict:
- Only one message can be sent to the commenter.
- It must be sent within 7 days of the comment. For Instagram Live, only during the broadcast.
- Follow-up messages can only be sent if the person responds, and within 24 hours of that response.
- The reply lands in the person's inbox if they follow the account, or in Requests if they do not. See message requests on Instagram for where those messages sit.
That last rule explains why good comment-to-DM flows end the first message with a question or a button. A reply reopens the conversation, and without one you cannot send anything further.
Other things worth knowing
- Message text must be UTF-8 and 1,000 bytes or less.
- Supported attachments include images (png, jpeg, up to 8 MB), audio, video, and PDF files (up to 25 MB), plus links, reactions, stickers, and your own published posts.
- Group messaging is not supported. One conversation, one customer.
- Messages in the Requests folder that have been inactive for 30 days are not returned by the API.
- Messages delivered through the API do not count as read in the Instagram app until a reply is sent.
- Replying through a third-party app moves the conversation to the General folder.
- Where the law requires it, automated chats must disclose that the person is talking to an automated service. Meta recommends disclosure even where it is not required.
Send Your First Message
Once you have a long-lived token, your Instagram professional account ID (IG_ID), and the Instagram-scoped ID (IGSID) of someone who messaged you, the request is a single POST. This is the shape from Meta's docs:
curl -X POST "https://graph.instagram.com/v26.0/<IG_ID>/messages" \
-H "Authorization: Bearer <INSTAGRAM_USER_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"recipient": { "id": "<IGSID>" },
"message": { "text": "Thanks for reaching out! What can I help with?" }
}'
And the same call in Node.js 18 or later:
const IG_ID = process.env.IG_ID;
const TOKEN = process.env.IG_ACCESS_TOKEN;
async function sendText(igsid, text) {
const res = await fetch(`https://graph.instagram.com/v26.0/${IG_ID}/messages`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
recipient: { id: igsid },
message: { text },
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? "Send failed");
return data; // { recipient_id, message_id }
}
A successful call returns recipient_id and message_id. To answer a comment instead, swap the recipient for { comment_id: "<COMMENT_ID>" }, and remember the one-message limit.
A minimal webhook receiver in Express ties it together:
import express from "express";
import crypto from "node:crypto";
const app = express();
app.use(express.json({ verify: (req, _res, buf) => (req.rawBody = buf) }));
app.get("/webhook", (req, res) => {
if (
req.query["hub.mode"] === "subscribe" &&
req.query["hub.verify_token"] === process.env.VERIFY_TOKEN
) {
return res.status(200).send(req.query["hub.challenge"]);
}
res.sendStatus(403);
});
app.post("/webhook", (req, res) => {
const expected =
"sha256=" +
crypto.createHmac("sha256", process.env.APP_SECRET).update(req.rawBody).digest("hex");
if (req.get("X-Hub-Signature-256") !== expected) return res.sendStatus(401);
res.sendStatus(200); // acknowledge first, process after
for (const entry of req.body.entry ?? []) {
for (const event of entry.messaging ?? []) {
if (event.message?.is_echo) continue; // our own messages
if (event.message?.text) {
sendText(event.sender.id, "Got it, one moment.").catch(() => {});
}
}
}
});
app.listen(3000);
This is a starting point, not production code. A real integration also needs deduplication, a queue so slow work does not block the 200, retries, token storage and refresh, and a way to stop replying when a human takes over.
Rate Limits
Meta's messaging limits are counted per Instagram professional account and per API:
| API | Limit |
|---|---|
| Send API (text, links, reactions, stickers) | 100 calls per second |
| Send API (audio or video) | 10 calls per second |
| Private Replies (post and Reel comments) | 750 calls per hour |
| Private Replies (Live comments) | 100 calls per second |
| Conversations API | 2 calls per second |
Other Instagram Platform endpoints use Business Use Case rate limiting, where the rolling 24-hour call allowance is 4,800 times the number of impressions the account's content has had. These are technical limits for the API itself. The limit most account owners run into is different, and covered in our guide to how many Instagram DMs you can send per day.
The private reply limit of 750 per hour is the one to plan around if a Reel can take off: a viral post can generate more qualifying comments than your app can answer in an hour, so queue them rather than dropping them.
Common Errors and What They Mean
Graph API errors come back as a JSON body with message, type, code, optional error_subcode, and an fbtrace_id worth logging. Meta's error reference lists the common codes:
| Code | Meaning | What to do |
|---|---|---|
| 190 | Access token expired or invalid | Refresh the token, or send the user through login again |
| 10 | Permission denied | Check the permission was granted and the app has the access level you need |
| 200 to 299 | Permission-related errors | Same as code 10; check which permission the call needs |
| 4, 17, 341 | Throttling or app limit reached | Back off and retry later, and look at your request volume |
| 368 | Temporarily blocked for policy violations | Wait; review what your app was sending |
| 1, 2 | Temporary API issue | Retry after a pause |
Two failures are specific to messaging and worth recognizing:
Sending outside the allowed window. Developers report this surfacing as code 10 with a message saying the message is sent outside of the allowed window. The cause is the 24-hour rule, or the 7-day private reply rule. The fix is to track the last time the person messaged you and refuse to send once the window has closed, or use the Human Agent tag where you qualify.
Webhooks that never arrive. Usual suspects: the app is not set to Live, you only have Standard Access, the callback URL does not return the verification challenge, the account is private (for comment events), or the account was never enabled for notifications in your app.
Is the Instagram Messaging API Free?
Meta's Instagram Platform documentation does not describe a per-message fee for these messaging endpoints, so the direct API cost is not where the budget goes. The real costs are engineering time, hosting, the App Review and Business Verification process, and ongoing maintenance when Meta changes something. Check Meta's current terms before you commit, since commercial terms can change.
Build It Yourself or Use a Tool
Building directly on the API makes sense when:
- DM automation is a core part of your own product.
- You need custom logic, data models, or an inbox that off-the-shelf tools cannot give you.
- You have an engineer to own token refresh, webhooks, and policy changes.
Using a tool makes sense when you want the outcome, such as comment-to-DM, keyword replies, or an AI agent that answers questions, without owning the plumbing. That plumbing is real work: the Meta app, review, tokens, webhook infrastructure, window tracking, deduplication, retries, rate limits, and human handoff. Our n8n guide to Instagram DM automation covers the do-it-yourself route and the Meta setup it still requires.
FlowGent is one of those tools. It connects through Meta's official Instagram API, so it follows the rules above: it replies to people who messaged you or commented, and it does not do cold outreach. Plans start at $19 per month for flows such as comment-to-DM and keyword replies, with no AI, and AI agent plans start at $49 per month. There is a 7-day free trial. If your goal is to automate comment replies and DMs rather than to build an API integration, the comment-to-DM workflow is the quickest way to see it working.
Frequently Asked Questions
What is the Instagram Messaging API?
It is Meta's API for sending and receiving direct messages on an Instagram professional account. Messages arrive as webhook notifications, and your app replies through the /messages endpoint. It also supports private replies to comments, and with Instagram Login it runs on graph.instagram.com.
Is there an Instagram DM API?
Yes, the Instagram Messaging API is the official DM API. It is available for business and creator accounts, through either Instagram Login or Facebook Login, and it requires the permissions and access levels described above. There is no official DM API for personal accounts.
How do I get Instagram API access?
Convert to a professional account, register as a Meta developer, create an app, add the Instagram product, and request the permissions you need. Standard Access is enough for accounts you own or manage. To serve other businesses, your app needs Advanced Access through App Review and Business Verification, and it must be Live.
Which permission do I need to send Instagram DMs?
With Instagram Login you need instagram_business_basic and instagram_business_manage_messages. For private replies to comments you also need instagram_business_manage_comments. With Facebook Login the equivalent permissions are instagram_basic and instagram_manage_messages, plus Page permissions.
Can I message someone who never contacted me?
No. Meta's documentation says your app can send a message only after the Instagram user has messaged your professional account. The one exception is a single private reply to a commenter, within 7 days of the comment.
How long can I reply to a message?
For most user actions the standard window is 24 hours from their last message. After a first message that follows a Click-to-Direct ad, it can last up to 7 days. With the Human Agent feature, a human can reply within 7 days using the human_agent tag.
Can I use the Instagram API to automate comments and DMs?
Yes. The webhook delivers comments and messages, private replies answer commenters, and the send endpoint answers DMs. Automation must stay within the messaging window and the private reply rules, and you should disclose automation where the law requires it.
Sources checked. All facts in this guide were checked against Meta's documentation in October 2026:
- Instagram Platform overview: developers.facebook.com/documentation/instagram-platform/overview
- Send Messages (Instagram Login): developers.facebook.com/documentation/instagram-platform/instagram-api-with-instagram-login/messaging-api
- Send a Private Reply: developers.facebook.com/documentation/instagram-platform/private-replies
- Set up Instagram Webhooks: developers.facebook.com/documentation/instagram-platform/webhooks/setup
- Business Login for Instagram: developers.facebook.com/documentation/instagram-platform/instagram-api-with-instagram-login/business-login
- Human Agent feature: developers.facebook.com/docs/features-reference/human-agent
- Graph API error handling: developers.facebook.com/docs/graph-api/guides/error-handling