Integration Guide

How to Get Instagram DM & Comment Notifications in Slack with InstantDM

Set up real-time Slack notifications for Instagram DMs, comments, and lead flow completions using InstantDM webhooks. Three methods: Slack Incoming Webhooks (simplest), Make.com, and Zapier. Includes message formatting examples and Block Kit templ...

Meta Business Partner
30,000+ creators
$9.99/mo flat

Never miss an Instagram interaction again. This guide shows you how to get real-time Slack notifications whenever someone comments on your post, sends you a DM, or completes a lead capture flow - all powered by InstantDM's webhook system.

You have three options:

  • Option A: Slack Incoming Webhooks (simplest, no third-party tools)
  • Option B: Via Make.com (visual builder, more formatting options)
  • Option C: Via Zapier (quick setup, no code)

Why Send InstantDM Events to Slack?

If your team lives in Slack, getting Instagram notifications there means faster response times and better coordination:

  • Instant awareness - see new comments and DMs the moment they happen
  • Team coordination - route different events to different channels (#instagram-comments, #new-leads, #support)
  • No app switching - your team doesn't need to check Instagram or InstantDM constantly
  • High-value lead alerts - get pinged immediately when a qualified lead completes your flow
  • Audit trail - Slack keeps a searchable history of all Instagram interactions

What You'll Need

Requirement Details
InstantDM account Trendsetter, Trendsetter Pro, or any Multi plan
InstantDM API key Found at Settings → API (or /api-integration page)
Slack workspace With permission to create apps or incoming webhooks
Make.com account (Option B) Free plan works for testing
Zapier account (Option C) Free plan works for simple Zaps

For full API documentation, visit instantdm.com/instagram-api-docs.


Option A: Slack Incoming Webhooks (Simplest)

This is the most direct approach - InstantDM sends webhook data to a small server you control, which formats and forwards it to Slack. No Make.com or Zapier needed.

Step 1: Create a Slack App

  1. Go to api.slack.com/apps and click Create New App.
  2. Choose From scratch.
  3. Name it InstantDM Notifications and select your workspace.
  4. Click Create App.

Step 2: Enable Incoming Webhooks

  1. In your Slack app settings, go to Incoming Webhooks in the left sidebar.
  2. Toggle Activate Incoming Webhooks to On.
  3. Click Add New Webhook to Workspace.
  4. Select the channel where you want notifications (e.g., #instagram-activity).
  5. Click Allow.
  6. Copy the Webhook URL (e.g., https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX).

Step 3: Get Your Slack Webhook URL

You now have a Slack webhook URL that accepts POST requests with JSON payloads. Any message you send to this URL will appear in your chosen Slack channel.

Test it with a curl command:

curl -X POST -H 'Content-Type: application/json' \
  --data '{"text":"Hello from InstantDM! 🎉"}' \
  YOUR_SLACK_WEBHOOK_URL

Step 4: Build a Webhook Forwarder

Since InstantDM's webhook payload format differs from Slack's expected format, you need a small server to receive InstantDM events and forward them to Slack with proper formatting.

Node.js Forwarder

const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());

const INSTANTDM_API_KEY = process.env.INSTANTDM_API_KEY;
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL;

function verifySignature(req) {
  const signature = req.headers['x-webhook-signature'];
  if (!signature) return false;
  const expected = crypto
    .createHmac('sha256', INSTANTDM_API_KEY)
    .update(JSON.stringify(req.body))
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

app.post('/webhook/instantdm', async (req, res) => {
  res.status(200).json({ received: true });

  if (!verifySignature(req)) return;

  const { event, timestamp, data } = req.body;
  const slackMessage = formatSlackMessage(event, timestamp, data);

  await fetch(SLACK_WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(slackMessage)
  });
});

function formatSlackMessage(event, timestamp, data) {
  switch (event) {
    case 'comment':
      return {
        blocks: [
          {
            type: 'header',
            text: { type: 'plain_text', text: '📝 New Instagram Comment' }
          },
          {
            type: 'section',
            fields: [
              { type: 'mrkdwn', text: `*User:*\n@${data.username}` },
              { type: 'mrkdwn', text: `*Time:*\n${new Date(timestamp).toLocaleString()}` }
            ]
          },
          {
            type: 'section',
            text: { type: 'mrkdwn', text: `*Comment:*\n>${data.comment_text}` }
          },
          {
            type: 'actions',
            elements: [
              {
                type: 'button',
                text: { type: 'plain_text', text: 'View Post' },
                url: data.post_url
              }
            ]
          }
        ]
      };

    case 'dm_received':
      return {
        blocks: [
          {
            type: 'header',
            text: { type: 'plain_text', text: '💬 New Instagram DM' }
          },
          {
            type: 'section',
            fields: [
              { type: 'mrkdwn', text: `*From:*\n@${data.username}` },
              { type: 'mrkdwn', text: `*Time:*\n${new Date(timestamp).toLocaleString()}` }
            ]
          },
          {
            type: 'section',
            text: { type: 'mrkdwn', text: `*Message:*\n>${data.message_text}` }
          }
        ]
      };

    case 'flow_completed':
      const vars = data.response_variables || {};
      let fieldsText = Object.entries(vars)
        .map(([key, value]) => `• *${key}:* ${value}`)
        .join('\n');

      return {
        blocks: [
          {
            type: 'header',
            text: { type: 'plain_text', text: '🎯 Flow Completed  -  New Lead!' }
          },
          {
            type: 'section',
            fields: [
              { type: 'mrkdwn', text: `*Instagram:*\n@${data.username}` },
              { type: 'mrkdwn', text: `*Flow:*\n${data.flow_name}` }
            ]
          },
          {
            type: 'section',
            text: { type: 'mrkdwn', text: `*Lead Data:*\n${fieldsText}` }
          }
        ]
      };

    default:
      return {
        text: `InstantDM event: ${event} from @${data.username}`
      };
  }
}

app.listen(3000, () => console.log('Slack forwarder running on port 3000'));

Python Forwarder

import os
import hmac
import hashlib
import requests
import threading
from datetime import datetime
from flask import Flask, request, jsonify

app = Flask(__name__)

INSTANTDM_API_KEY = os.environ.get('INSTANTDM_API_KEY')
SLACK_WEBHOOK_URL = os.environ.get('SLACK_WEBHOOK_URL')

def verify_signature(req):
    signature = req.headers.get('X-Webhook-Signature')
    if not signature:
        return False
    expected = hmac.new(
        INSTANTDM_API_KEY.encode(),
        req.get_data(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

@app.route('/webhook/instantdm', methods=['POST'])
def webhook():
    if not verify_signature(request):
        return jsonify({'error': 'Invalid signature'}), 401

    payload = request.get_json()
    thread = threading.Thread(target=forward_to_slack, args=(payload,))
    thread.start()

    return jsonify({'received': True}), 200

def forward_to_slack(payload):
    event = payload.get('event')
    timestamp = payload.get('timestamp')
    data = payload.get('data', {})

    message = format_slack_message(event, timestamp, data)
    requests.post(SLACK_WEBHOOK_URL, json=message)

def format_slack_message(event, timestamp, data):
    if event == 'comment':
        return {
            'blocks': [
                {'type': 'header', 'text': {'type': 'plain_text', 'text': '📝 New Instagram Comment'}},
                {'type': 'section', 'fields': [
                    {'type': 'mrkdwn', 'text': f'*User:*\n@{data.get("username")}'},
                    {'type': 'mrkdwn', 'text': f'*Comment:*\n>{data.get("comment_text")}'}
                ]},
                {'type': 'context', 'elements': [
                    {'type': 'mrkdwn', 'text': f'Post: {data.get("post_url", "N/A")} | {timestamp}'}
                ]}
            ]
        }
    elif event == 'dm_received':
        return {
            'blocks': [
                {'type': 'header', 'text': {'type': 'plain_text', 'text': '💬 New Instagram DM'}},
                {'type': 'section', 'fields': [
                    {'type': 'mrkdwn', 'text': f'*From:*\n@{data.get("username")}'},
                    {'type': 'mrkdwn', 'text': f'*Message:*\n>{data.get("message_text")}'}
                ]},
                {'type': 'context', 'elements': [
                    {'type': 'mrkdwn', 'text': timestamp}
                ]}
            ]
        }
    elif event == 'flow_completed':
        vars_data = data.get('response_variables', {})
        fields_text = '\n'.join([f'• *{k}:* {v}' for k, v in vars_data.items()])
        return {
            'blocks': [
                {'type': 'header', 'text': {'type': 'plain_text', 'text': '🎯 Flow Completed  -  New Lead!'}},
                {'type': 'section', 'fields': [
                    {'type': 'mrkdwn', 'text': f'*Instagram:*\n@{data.get("username")}'},
                    {'type': 'mrkdwn', 'text': f'*Flow:*\n{data.get("flow_name")}'}
                ]},
                {'type': 'section', 'text': {'type': 'mrkdwn', 'text': f'*Lead Data:*\n{fields_text}'}}
            ]
        }
    else:
        return {'text': f'InstantDM event: {event} from @{data.get("username")}'}

if __name__ == '__main__':
    app.run(port=3000)

Step 5: Configure InstantDM Webhook

  1. In InstantDM, go to Settings → API.
  2. Paste your forwarder server's URL (e.g., https://your-server.com/webhook/instantdm) into the Webhook URL field.
  3. Enable the events you want notifications for: comment, dm_received, flow_completed, etc.
  4. Click Save.

Option B: Via Make.com

Make.com gives you a visual interface to receive InstantDM webhooks and send formatted Slack messages - no code required.

Step-by-Step Setup

  1. Create a Make.com scenario with a Webhooks → Custom webhook trigger.
  2. Copy the webhook URL and paste it into InstantDM Settings → API.
  3. Click Run once in Make.com, then trigger a test event from InstantDM.
  4. Add a Router module to handle different event types on separate branches.
  5. On each branch, add a Filter (e.g., event equals comment) and a Slack → Send a Message module.
  6. Configure the Slack message for each event type.

Make.com Slack Message Templates

For comments:

📝 New Instagram Comment
User: @{{data.username}}
Comment: {{data.comment_text}}
Post: {{data.post_url}}
Time: {{timestamp}}

For DMs:

💬 New Instagram DM
From: @{{data.username}}
Message: {{data.message_text}}
Time: {{timestamp}}

For flow completions:

🎯 New Lead from Instagram!
Name: {{data.response_variables.full_name}}
Email: {{data.response_variables.email}}
Phone: {{data.response_variables.phone}}
Interest: {{data.response_variables.interest}}
Flow: {{data.flow_name}}
Instagram: @{{data.username}}
  1. Set the scenario to ON with Immediately scheduling.

For a detailed Make.com setup walkthrough, see the Make.com integration guide.


Option C: Via Zapier

Step-by-Step Setup

  1. Create a Zap with Webhooks by Zapier → Catch Hook as the trigger.
  2. Copy the webhook URL and paste it into InstantDM Settings → API.
  3. Click Test trigger in Zapier, then trigger a test event from InstantDM.
  4. Add a Filter by Zapier step to only process specific events (e.g., event exactly matches flow_completed).
  5. Add Slack → Send Channel Message as the action.
  6. Select your workspace and channel.
  7. Configure the message text using Zapier's field mapper.

Zapier Slack Message Template

🎯 New Instagram Lead!
Name: {{data__response_variables__full_name}}
Email: {{data__response_variables__email}}
Phone: {{data__response_variables__phone}}
Interest: {{data__response_variables__interest}}
Flow: {{data__flow_name}}
Instagram: @{{data__username}}
  1. Test and publish the Zap.

For a detailed Zapier setup walkthrough, see the Zapier integration guide.


Example: New Comment Notification with Commenter Username and Text

A simple notification that fires every time someone comments on your Instagram post:

Slack Message Output

📝 New Instagram Comment
━━━━━━━━━━━━━━━━━━━━━
User: @janedoe
Comment: "I want pricing info!"
Post: https://www.instagram.com/p/ABC123/
Time: Jan 15, 2025 10:32 AM

Slack Block Kit JSON (for Option A)

{
  "blocks": [
    {
      "type": "header",
      "text": { "type": "plain_text", "text": "📝 New Instagram Comment" }
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn", "text": "*User:*\n@janedoe" },
        { "type": "mrkdwn", "text": "*Time:*\nJan 15, 2025 10:32 AM" }
      ]
    },
    {
      "type": "section",
      "text": { "type": "mrkdwn", "text": "*Comment:*\n>I want pricing info!" }
    },
    {
      "type": "actions",
      "elements": [
        {
          "type": "button",
          "text": { "type": "plain_text", "text": "View Post" },
          "url": "https://www.instagram.com/p/ABC123/"
        }
      ]
    }
  ]
}

Example: Flow Completed Notification with All Lead Data

When someone completes a lead capture flow, send a rich notification with all collected data:

Slack Block Kit JSON

{
  "blocks": [
    {
      "type": "header",
      "text": { "type": "plain_text", "text": "🎯 New Lead from Instagram!" }
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn", "text": "*Name:*\nJohn Doe" },
        { "type": "mrkdwn", "text": "*Email:*\njohn@example.com" }
      ]
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn", "text": "*Phone:*\n+1234567890" },
        { "type": "mrkdwn", "text": "*Interest:*\nPremium Plan" }
      ]
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn", "text": "*Instagram:*\n@johndoe" },
        { "type": "mrkdwn", "text": "*Flow:*\nLead Capture Flow" }
      ]
    },
    {
      "type": "divider"
    },
    {
      "type": "context",
      "elements": [
        { "type": "mrkdwn", "text": "Received via InstantDM • Jan 15, 2025 10:30 AM" }
      ]
    }
  ]
}

Example: High-Value Lead Alert When Specific Tags Are Applied

Send an urgent alert to a dedicated channel when a lead matches high-value criteria (e.g., enterprise budget, specific interest):

Node.js - Conditional Alert

function formatSlackMessage(event, timestamp, data) {
  if (event !== 'flow_completed') return null;

  const vars = data.response_variables || {};
  const isHighValue = detectHighValueLead(vars);

  const blocks = [
    {
      type: 'header',
      text: {
        type: 'plain_text',
        text: isHighValue ? '🔥 HIGH-VALUE Lead from Instagram!' : '🎯 New Lead from Instagram'
      }
    },
    {
      type: 'section',
      fields: [
        { type: 'mrkdwn', text: `*Name:*\n${vars.full_name || 'N/A'}` },
        { type: 'mrkdwn', text: `*Email:*\n${vars.email || 'N/A'}` }
      ]
    },
    {
      type: 'section',
      fields: [
        { type: 'mrkdwn', text: `*Phone:*\n${vars.phone || 'N/A'}` },
        { type: 'mrkdwn', text: `*Interest:*\n${vars.interest || 'N/A'}` }
      ]
    },
    {
      type: 'section',
      fields: [
        { type: 'mrkdwn', text: `*Instagram:*\n@${data.username}` },
        { type: 'mrkdwn', text: `*Flow:*\n${data.flow_name}` }
      ]
    }
  ];

  if (isHighValue) {
    blocks.push({
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: '⚡ *This lead matches high-value criteria. Prioritize follow-up!*'
      }
    });
  }

  return { blocks };
}

function detectHighValueLead(vars) {
  const budget = parseInt(vars.budget) || 0;
  const interest = (vars.interest || '').toLowerCase();
  const companySize = (vars.company_size || '').toLowerCase();

  return (
    budget >= 5000 ||
    interest.includes('enterprise') ||
    interest.includes('premium') ||
    companySize.includes('enterprise') ||
    companySize.includes('50+')
  );
}

// Route high-value leads to a different Slack channel
async function sendToSlack(event, timestamp, data) {
  const message = formatSlackMessage(event, timestamp, data);
  if (!message) return;

  const vars = data.response_variables || {};
  const isHighValue = detectHighValueLead(vars);

  const webhookUrl = isHighValue
    ? process.env.SLACK_HIGH_VALUE_WEBHOOK_URL  // #high-value-leads channel
    : process.env.SLACK_WEBHOOK_URL;             // #instagram-leads channel

  await fetch(webhookUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(message)
  });
}

Customizing Slack Message Formatting

Using Block Kit

Slack's Block Kit lets you create rich, interactive messages. Key block types:

Block Type Use For
header Bold title at the top of the message
section Text content with optional fields (side-by-side layout)
divider Horizontal line separator
context Small, muted text (timestamps, metadata)
actions Buttons and interactive elements
image Inline images

Adding Buttons

{
  "type": "actions",
  "elements": [
    {
      "type": "button",
      "text": { "type": "plain_text", "text": "View in HubSpot" },
      "url": "https://app.hubspot.com/contacts/YOUR_PORTAL/contact/CONTACT_ID",
      "style": "primary"
    },
    {
      "type": "button",
      "text": { "type": "plain_text", "text": "View Instagram Profile" },
      "url": "https://instagram.com/USERNAME"
    }
  ]
}

Adding Emoji and Color

Use Slack's built-in emoji codes in your messages:

  • 📝 :memo: - for comments
  • 💬 :speech_balloon: - for DMs
  • 🎯 :dart: - for lead completions
  • 🔥 :fire: - for high-value leads
  • :zap: - for urgent alerts

Using Attachments for Color Coding

{
  "attachments": [
    {
      "color": "#36a64f",
      "blocks": [
        {
          "type": "section",
          "text": { "type": "mrkdwn", "text": "🎯 *New Lead:* John Doe (john@example.com)" }
        }
      ]
    }
  ]
}

Color codes:

  • #36a64f (green) - new leads
  • #ff9900 (orange) - warm leads
  • #ff0000 (red) - high-value / urgent
  • #439FE0 (blue) - informational

Troubleshooting

Issue Solution
Slack messages not appearing Verify the Slack webhook URL is correct. Test it with a curl command first.
Messages appearing in wrong channel Each Slack incoming webhook is tied to a specific channel. Create separate webhooks for different channels.
Formatting looks broken Ensure you're using valid Block Kit JSON. Test your payload at api.slack.com/tools/block-kit-builder.
InstantDM webhook not firing Check that the webhook URL is saved in InstantDM Settings → API and the correct events are enabled.
Duplicate notifications Add idempotency checks using the event's message_id or comment_id to prevent processing the same event twice.
Make.com/Zapier not receiving data Click "Run once" (Make.com) or "Test trigger" (Zapier) before sending a test event from InstantDM.

Frequently Asked Questions

What's the simplest way to get Instagram notifications in Slack?

The simplest approach is Option B (Make.com) or Option C (Zapier) - both require zero code. Create a webhook trigger, paste the URL into InstantDM, add a Slack action, and you're done. If you want full control over message formatting, use Option A (Slack Incoming Webhooks) with a small Node.js or Python forwarder.

Can I send different event types to different Slack channels?

Yes. With Option A, use different Slack webhook URLs for different event types in your forwarder code. With Make.com, use a Router module with filters to send comments to #instagram-comments and leads to #new-leads. With Zapier, create separate Zaps for each event type, each pointing to a different Slack channel.

Are Slack notifications real-time?

Yes. InstantDM fires webhooks within seconds of the event. Slack incoming webhooks process messages instantly. The total delay from Instagram interaction to Slack notification is typically under 5 seconds.

How many notifications can I send to Slack?

Slack's incoming webhooks have a rate limit of 1 message per second per webhook URL. For most Instagram accounts, this is more than enough. If you're processing very high volumes, batch notifications or use Slack's Web API instead of incoming webhooks.

Can I include the Instagram user's profile picture in the Slack notification?

Instagram's API doesn't expose profile pictures in webhook payloads. You can include the username and a link to their Instagram profile (https://instagram.com/USERNAME), but the profile image itself isn't available in the webhook data.

Do I need a paid Slack plan for this?

No. Slack's free plan supports incoming webhooks and the Slack API. The only limitation is that free Slack workspaces have a 90-day message history limit, so older notifications won't be searchable after 90 days.

Can I get notifications on my phone via Slack?

Yes. If you have the Slack mobile app installed and notifications enabled for the channel, you'll get push notifications on your phone for every Instagram event. You can also use Slack's notification preferences to only get mobile alerts for specific keywords or mentions.


What's Next

  • Set up your first notification using whichever option (A, B, or C) fits your needs.
  • Create a lead capture flow in InstantDM to generate flow_completed events with lead data.
  • Route leads to HubSpot using the HubSpot CRM integration guide.
  • Automate more workflows with Make.com or Zapier.
  • Build a Custom AI Agent to auto-respond to DMs and get Slack alerts when the AI hands off to a human.
  • Explore the full API docs at instantdm.com/instagram-api-docs.

Ready to Automate Your Instagram DMs?

Join 30,000+ creators and brands using InstantDM today.

Start Your Free Trial

No credit card required. Setup in under 15 minutes.