InstantDM API Documentation
InstantDM is an Official Meta Business Partner that helps creators, businesses, and agencies automate their Instagram and Facebook DM conversations, comment responses, and lead generation flows. Built on the Meta Graph API.
What you can automate
Comment Automation — Automatically reply to comments and send DMs when someone comments on your post with a trigger word.
Flow Automation — Build multi-step DM flows with questions, buttons, media, and conditional logic. Collect leads, qualify prospects, and deliver content automatically.
AI Replies — Use AI models to generate contextual replies in DM conversations.
Why use the API?
The API lets you connect InstantDM with your existing tools. Receive real-time webhook events when comments, DMs, or flow completions happen. Send messages and reply to comments programmatically from Make.com, Zapier, n8n, or your own backend.
Platform
Official Meta Business Partner Built on Meta Graph API v25.0
Base URL
https://api.instantdm.com
Dashboard
https://app.instantdm.com
API Endpoint
POST https://api.instantdm.com/api-webhook
Webhook Config
Settings → Integrations → Webhook Configuration
API Keys
Settings → Integrations → API Keys
Authentication
All API requests require an API key. Generate one from your InstantDM dashboard under Settings → Integrations → API Keys.
Include the key in one of these headers:
| Header | Format |
|---|---|
Authorization | Bearer YOUR_API_KEY |
x-api-key | YOUR_API_KEY |
Example Request
curl -X POST https://api.instantdm.com/api-webhook \
-H "Authorization: Bearer sk-abc123..." \
-H "Content-Type: application/json" \
-d '{
"action": "send_message",
"type": "dm",
"recipient_id": "2358708294634624",
"message": {"text": "Hello!"}
}' Outbound Webhooks
InstantDM sends HTTP POST requests to your configured URL when events occur. Set one webhook URL and subscribe to the events you want.
Configure from: Settings → Integrations → Webhook Configuration
Headers on every webhook
| Header | Description |
|---|---|
Content-Type | application/json |
X-Event-Type | Event name (e.g. comment, dm_received) |
X-Timestamp | ISO-8601 UTC timestamp |
X-Webhook-Signature | HMAC-SHA256 hex digest (if secret configured) |
Available events
| Event | Trigger |
|---|---|
comment | New comment on your post |
dm_received | New direct message received |
postback | Button clicked in DMs |
question_answered | User answers a flow question |
flow_completed | Flow automation completes |
Webhook delivery format
POST https://your-webhook-url.com Content-Type: application/json X-Event-Type: comment X-Timestamp: 2026-04-29T15:32:06+00:00 X-Webhook-Signature: a1b2c3d4...
comment
Fired when someone comments on your Instagram post. The payload is the raw Instagram webhook event as received from Meta.
Example payload
{
"object": "instagram",
"entry": [{
"id": "17841432111391196",
"time": 1777476726126,
"changes": [{
"field": "comments",
"value": {
"id": "17890012345",
"text": "Love this!",
"from": {"id": "123456", "username": "user123"},
"media": {"id": "18071354672638470"}
}
}]
}]
} dm_received
Fired when you receive a new direct message. The payload is the raw Instagram webhook event.
Example payload
{
"object": "instagram",
"entry": [{
"messaging": [{
"sender": {"id": "2358708294634624"},
"recipient": {"id": "17841432111391196"},
"timestamp": 1777476725580,
"message": {
"mid": "aWdfZAG1f...",
"text": "Hey, I'm interested!"
}
}]
}]
} postback
Fired when a user clicks a button in DMs. Includes the raw Instagram event plus an idm_optimized_body field with resolved postback data.
Example payload
{
"object": "instagram",
"entry": [{
"messaging": [{
"sender": {"id": "2358708294634624"},
"postback": {
"title": "Get Started",
"payload": "{\"flow_id\":\"abc\"}"
}
}]
}],
"idm_optimized_body": {
"user_id": "6703dbc9-...",
"flow_id": "0e3501b6-...",
"sender_id": "2358708294634624"
}
} question_answered
Fired each time a user answers a question in a flow. Gives you real-time data as the flow progresses.
| Field | Description |
|---|---|
flow_id | Flow automation ID |
sender_id | Instagram user ID of the responder |
question | The question text |
question_type | Type: email, phone, address, text, etc. |
custom_variable_name | Variable name set in the flow editor |
user_response | The user's answer |
skip | true if the user skipped this question |
Example payload
{
"flow_id": "0e3501b6-...",
"sender_id": "2358708294634624",
"sender_username": "user123",
"question": "What's your email?",
"question_type": "email",
"custom_variable_name": "user_email",
"user_response": "user@example.com",
"skip": false,
"attempt_no": "1",
"timestamp": "2026-04-29 17:11:59"
} flow_completed
Fired once when a flow automation completes. Contains all collected data in one payload.
response_variables is a flat dict — keys are the custom_variable_name. Easy to map in Make.com or Zapier.
Example payload
{
"flow_id": "0e3501b6-...",
"flow_name": "Lead Gen Flow",
"sender_id": "2358708294634624",
"sender_username": "user123",
"completed_at": "2026-04-29 17:17:15",
"tags": ["lead", "vip"],
"response_variables": {
"email": "user@example.com",
"phone": "+919876543210",
"address": "123 Main St"
}
} Signature Verification
If you configure a webhook secret, every outbound request includes an X-Webhook-Signature header with an HMAC-SHA256 hex digest of the JSON body.
Always verify the signature before processing the webhook to ensure it came from InstantDM.
Node.js
const crypto = require('crypto');
function verify(body, signature, secret) {
const computed = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(body))
.digest('hex');
return computed === signature;
} Python
import hmac, hashlib, json
def verify(payload, signature, secret):
computed = hmac.new(
secret.encode(),
json.dumps(payload).encode(),
hashlib.sha256
).hexdigest()
return computed == signature Inbound API
Call InstantDM's API to perform actions from external systems. All actions use a single endpoint.
POST https://api.instantdm.com/api-webhook
Required headers
| Header | Value |
|---|---|
Authorization | Bearer YOUR_API_KEY |
Content-Type | application/json |
Available actions
post_comment — Reply to a comment send_message — Send a DM or comment private reply
Reply to Comment
Reply to a specific Instagram comment publicly.
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | "post_comment" |
comment_id | string | Yes | Instagram comment ID |
comment_text | string | Yes | Reply text |
Request
{
"action": "post_comment",
"comment_id": "17890012345",
"comment_text": "Thanks! Check your DM"
} Response
{
"message": "Comment reply posted",
"comment_id": "17890012346"
} Send Message
Send a message via Instagram DM. Two types:
DM Message — Send to a user by their Instagram user ID.
Comment Private Reply — Reply to a comment privately via DM.
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | "send_message" |
type | string | No | "dm" (default) or "comment_reply" |
recipient_id | string | For dm | Instagram user ID |
comment_id | string | For comment_reply | Instagram comment ID |
message | object | Yes | Message content (see formats) |
DM Message
{
"action": "send_message",
"type": "dm",
"recipient_id": "2358708294634624",
"message": {"text": "Hello!"}
} Comment Private Reply
{
"action": "send_message",
"type": "comment_reply",
"comment_id": "17890012345",
"message": {"text": "Here's the link..."}
} Message Formats
The message field supports multiple formats. Pass the object directly — InstantDM forwards it to the Instagram Graph API.
For media support details and limitations, see the Meta Instagram Messaging API documentation.
Text
{"text": "Hello!"} Image
{"attachment": {"type": "image",
"payload": {"url": "https://example.com/photo.jpg"}}} Video
{"attachment": {"type": "video",
"payload": {"url": "https://example.com/video.mp4"}}} Audio
{"attachment": {"type": "audio",
"payload": {"url": "https://example.com/audio.mp3"}}} Button Template
{"attachment": {"type": "template",
"payload": {
"template_type": "button",
"text": "Choose an option:",
"buttons": [
{"type": "web_url", "title": "Visit", "url": "https://..."},
{"type": "web_url", "title": "More", "url": "https://..."}
]
}
}} Quick Replies
{"text": "Pick one:",
"quick_replies": [
{"content_type": "text", "title": "A", "payload": "A"},
{"content_type": "text", "title": "B", "payload": "B"}
]
} Rate Limits
API rate limits are based on your InstantDM plan. On top of that, Meta's own rate limits also apply. Whichever limit is reached first, the automation will be stopped.
If you hit a rate limit, messages are not retried automatically — you'll need to resend them in the next rate limit window.
Error Codes
| Code | Message | Cause |
|---|---|---|
| 401 | Missing API key | No Authorization or x-api-key header |
| 401 | Invalid API key | Key not found or revoked |
| 400 | Missing comment_id or comment_text | post_comment missing required fields |
| 400 | Missing recipient_id | send_message (dm) missing recipient |
| 400 | Missing comment_id for comment_reply | send_message (comment_reply) missing comment ID |
| 400 | Missing message | No message content provided |
| 400 | Unknown action | Invalid action value |
| 404 | No Instagram access token found | User has no connected IG account |
| 4xx/5xx | Instagram API error | Error passed through from Meta Graph API |
| 403 | API access requires higher plan | User's plan doesn't include API access |
| 403 | API & Webhook integrations require higher plan | Trying to enable webhook config on ineligible plan |
| 403 | API keys require higher plan | Trying to generate API key on ineligible plan |
| 429 | Hourly rate limit reached. Please try again later. | Trendsetter/Trendsetter Pro user hit their hourly limit (2,000/hr or 20,000/hr) |
| 402 | Insufficient credits. Please upgrade or purchase top-up credits. | Multi-account plan user ran out of credits |