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.

API access is available on eligible plans. View pricing →

Include the key in one of these headers:

HeaderFormat
AuthorizationBearer YOUR_API_KEY
x-api-keyYOUR_API_KEY
API keys are shown only once when generated. Store them securely.

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. Webhooks are dispatched asynchronously via SQS — they do not block the main DM processing pipeline.

Configure from: Settings → Integrations → Webhook Configuration

Headers on every webhook

HeaderDescription
Content-Typeapplication/json
X-Event-TypeEvent name (e.g. comment, dm_received)
X-TimestampISO-8601 UTC timestamp
X-Webhook-SignatureHMAC-SHA256 hex digest (if secret configured)

Available events

EventTrigger
commentNew comment on a post with active automation
dm_receivedNew inbound DM received
postbackButton clicked in DM automation
question_answeredUser answers a flow question
flow_completedAll nodes in a flow completed

Delivery behavior

BehaviorDetail
Timeout10 seconds
RetriesNone — fire-and-forget
BatchingNone — each event is a separate POST
OrderingNot guaranteed
DuplicatesPossible (SQS at-least-once). Use mid or comment id for dedup.

Error handling

Your endpoint should return a 2xx status code. Non-2xx responses are logged but never retried.

Error TypeBehavior
HTTP 4xx/5xxLogged, no retry
Timeout (10s)Logged, no retry
Connection errorLogged, no retry
Respond fast — return 2xx immediately and process the webhook asynchronously in your own system.

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

Payload types

comment, dm_received, postback
  → Raw Instagram webhook payloads
    (same structure Meta sends)

question_answered, flow_completed
  → InstantDM-specific structured data

comment

Fired when someone comments on a post that has an active automation. This is a pre-processing webhook — it fires before the automation processes the comment.

The payload is the raw Instagram webhook event as received from Meta.

FieldDescription
entry[].changes[].value.fromWho commented (id + username)
entry[].changes[].value.textComment text
entry[].changes[].value.mediaWhich post/reel was commented on
entry[].changes[].value.media.media_product_typeMedia type (e.g. REELS)
entry[].changes[].value.idComment ID
entry[].changes[].value.sender_idCommenter's IG user ID
entry[].changes[].value.recipient_idYour IG account ID

Example payload

{
  "entry": [{
    "id": "17841435672868203",
    "time": 1778223729,
    "changes": [{
      "value": {
        "from": {
          "id": "27021621630806157",
          "username": "pvamsi.krishna.73"
        },
        "media": {
          "id": "17933258556187263",
          "media_product_type": "REELS"
        },
        "id": "18114716611826474",
        "text": "2013",
        "recipient_id": "17841435672868203",
        "sender_id": "27021621630806157"
      },
      "field": "comments"
    }],
    "object": "instagram"
  }]
}

dm_received

Fired when someone sends a DM to your account (outside of automation-initiated conversations). The payload is the raw Instagram webhook event.

FieldDescription
entry[].messaging[].sender.idWho sent the DM
entry[].messaging[].message.textMessage text
entry[].messaging[].message.midMessage ID (use for deduplication)
entry[].idYour IG account ID (recipient)
entry[].messaging[].timestampMessage timestamp (ms)

Example payload

{
  "object": "instagram",
  "entry": [{
    "time": 1778223729706,
    "id": "17841476961942794",
    "messaging": [{
      "sender": {
        "id": "978239761327698"
      },
      "recipient": {
        "id": "17841476961942794"
      },
      "timestamp": 1778223722476,
      "message": {
        "mid": "aWdfZAG1faXRlbToxOklHTWVz...",
        "text": "New"
      }
    }]
  }]
}

postback

Fired when a user clicks a postback button in a DM automation (e.g., "Started following you!", "Get my content"). Fires before the automation processes the postback.

FieldDescription
entry[].messaging[].postback.titleButton text the user clicked
entry[].messaging[].postback.payloadJSON string with automation context (see below)
entry[].messaging[].postback.midMessage ID
entry[].messaging[].sender.idWho clicked the button

Payload JSON fields

FieldDescription
from.usernameWho clicked
media.idWhich post triggered the automation
textOriginal comment text
user_idInstantDM user who owns the automation
creator_usernameIG account that received the comment
comment_replyWhether this is a comment-triggered flow
story_replyWhether this is a story-triggered flow
dm_replyWhether this is a DM-triggered flow

Example payload

{
  "object": "instagram",
  "entry": [{
    "time": 1778223725146,
    "id": "17841408795204378",
    "messaging": [{
      "sender": {
        "id": "2031528510825908"
      },
      "recipient": {
        "id": "17841408795204378"
      },
      "timestamp": 1778223723887,
      "postback": {
        "title": "Started following you! 👍",
        "payload": "{\"from\": {\"id\": \"2031528510825908\", \"username\": \"__zain_z\"}, \"media\": {\"id\": \"17939513463036158\", \"media_product_type\": \"REELS\"}, \"text\": \"prompt\", \"recipient_id\": \"17841408795204378\", \"sender_id\": \"2031528510825908\", \"user_id\": \"e10b1fc8-cade-4608-99cd-ce269bee2a2b\", \"creator_username\": \"dr_amina_nijas\", \"comment_reply\": true, \"story_reply\": false, \"dm_reply\": false}",
        "mid": "aWdfZAG1faXRlbToxOklHTWVz..."
      }
    }]
  }]
}

question_answered

Fired each time a user answers a question node in a flow automation. Gives you real-time data as the flow progresses. This is an InstantDM-specific structured payload (not a raw Instagram event).

FieldTypeDescription
flow_idstringFlow automation ID
sender_idstringInstagram user ID of the responder
sender_usernamestringInstagram username of the responder
questionstringThe question text that was asked
question_typestringType: text, number, email, phone, address, etc.
custom_variable_namestringVariable name assigned to this answer
user_responsestringThe user's actual answer
skipbooleantrue if the user skipped this question
attempt_nostringFlow attempt number
timestampstringWhen the answer was recorded

Example payload

{
  "flow_id": "5a0441b5-6589-4452-b8bf-90902c865893",
  "sender_id": "2031528510825908",
  "sender_username": "__zain_z",
  "question": "What's your name?",
  "question_type": "text",
  "custom_variable_name": "user_name",
  "user_response": "Zain",
  "skip": false,
  "attempt_no": "1",
  "timestamp": "2026-05-06 04:45:30.123456"
}

flow_completed

Fired once when a user completes all nodes in a flow automation. Contains all collected data in one payload. This is an InstantDM-specific structured payload.

FieldTypeDescription
flow_idstringFlow automation ID
flow_namestringName of the flow
sender_idstringInstagram user ID who completed the flow
sender_usernamestringInstagram username
completed_atstringCompletion timestamp
attempt_nostringFlow attempt number
tagsarrayTags assigned during the flow
response_variablesobjectFlat dict of variable_name → user_answer (easy to map in Make.com or Zapier)
question_responsesarrayFull array of all Q&A pairs in the flow
The flow_completed webhook only fires for flows with Webhook enabled in the flow editor's Integrations popup.

Example payload

{
  "flow_id": "5a0441b5-6589-4452-b8bf-90902c865893",
  "flow_name": "Lead Capture Flow",
  "sender_id": "2031528510825908",
  "sender_username": "__zain_z",
  "completed_at": "2026-05-06 04:46:15.654321",
  "attempt_no": "1",
  "tags": ["hot-lead", "interested"],
  "response_variables": {
    "user_name": "Zain",
    "email": "zain@example.com",
    "interest": "pricing"
  },
  "question_responses": [
    {
      "question": "What's your name?",
      "question_type": "text",
      "custom_variable_name": "user_name",
      "user_response": "Zain",
      "skip": false
    },
    {
      "question": "What's your email?",
      "question_type": "email",
      "custom_variable_name": "email",
      "user_response": "zain@example.com",
      "skip": false
    }
  ]
}

Signature Verification

If you configure a webhook_secret, every outbound request includes an X-Webhook-Signature header with an HMAC-SHA256 hex digest.

The signature is computed as:

HMAC-SHA256(webhook_secret, raw_request_body)

Always verify the signature before processing the webhook to ensure it came from InstantDM. Use the raw request body (not parsed JSON) for verification.

Use constant-time comparison (e.g. hmac.compare_digest or crypto.timingSafeEqual) to prevent timing attacks.

Node.js

const crypto = require('crypto');

function verify(rawBody, signature, secret) {
  const computed = crypto
    .createHmac('sha256', secret)
    .update(rawBody) // use raw body, not parsed
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(computed),
    Buffer.from(signature)
  );
}

Python

import hmac, hashlib

def verify(raw_body, signature, secret):
    computed = hmac.new(
        secret.encode("utf-8"),
        raw_body.encode("utf-8"),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(computed, signature)

Webhook Plan Eligibility

Webhooks are only delivered when the InstantDM account owner has an eligible paid plan.

PlanWebhook Limit
Trendsetter Pro (monthly/yearly)20,000 webhooks/hour
Multi Starter (monthly/yearly)Credit-based
Multi Pro (monthly/yearly)Credit-based
Multi Ultra (monthly/yearly)Credit-based
Legacy plans (428337, 428338)2,000 webhooks/hour
Webhook rate limits are shared with DM sends. If you've hit your DM rate limit, webhooks will also be skipped.

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

HeaderValue
AuthorizationBearer YOUR_API_KEY
Content-Typeapplication/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.

FieldTypeRequiredDescription
actionstringYes"post_comment"
comment_idstringYesInstagram comment ID
comment_textstringYesReply 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.

FieldTypeRequiredDescription
actionstringYes"send_message"
typestringNo"dm" (default) or "comment_reply"
recipient_idstringFor dmInstagram user ID
comment_idstringFor comment_replyInstagram comment ID
messageobjectYesMessage 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.

To avoid hitting limits, space out your API calls and monitor the response headers for rate limit status. For high-volume use cases, contact support for guidance.

Error Codes

CodeMessageCause
401Missing API keyNo Authorization or x-api-key header
401Invalid API keyKey not found or revoked
400Missing comment_id or comment_textpost_comment missing required fields
400Missing recipient_idsend_message (dm) missing recipient
400Missing comment_id for comment_replysend_message (comment_reply) missing comment ID
400Missing messageNo message content provided
400Unknown actionInvalid action value
404No Instagram access token foundUser has no connected IG account
4xx/5xxInstagram API errorError passed through from Meta Graph API
403API access requires higher planUser's plan doesn't include API access
403API & Webhook integrations require higher planTrying to enable webhook config on ineligible plan
403API keys require higher planTrying to generate API key on ineligible plan
429Hourly rate limit reached. Please try again later.Trendsetter/Trendsetter Pro user hit their hourly limit (2,000/hr or 20,000/hr)
402Insufficient credits. Please upgrade or purchase top-up credits.Multi-account plan user ran out of credits