Integration Guide

How to Send Stripe Payment Links via InstantDM (Step-by-Step Guide)

Learn how to generate and send Stripe payment links through Instagram DMs using InstantDM. Collect payments directly from Instagram conversations.

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

Stripe Payment Links let you collect payments with a simple URL - no website or checkout page needed. Connecting InstantDM to Stripe lets you send payment links directly in Instagram DMs, turning conversations into transactions.


Why Use Stripe with InstantDM?

  • Instant checkout - send a payment link and get paid in seconds
  • No website needed - Stripe hosts the checkout page
  • Dynamic links - generate unique links per customer with custom amounts
  • Global payments - accept cards, Apple Pay, Google Pay, and local payment methods
  • Automatic receipts - Stripe sends confirmation emails automatically

Common Use Cases

  • Send a payment link after someone inquires about pricing via DM
  • Collect deposits or booking fees through Instagram conversations
  • Sell digital products (courses, ebooks, templates) via DM
  • Send invoices to leads who are ready to buy
  • Offer exclusive Instagram-only pricing with custom payment links

What You'll Need

Requirement Details
InstantDM account Trendsetter, Trendsetter Pro, or any Multi plan
Stripe account Free to create; standard processing fees apply
InstantDM API key Found at Settings → API in your InstantDM dashboard
Stripe API key Found at Developers → API keys in Stripe Dashboard

Method 1: Static Payment Links (Simplest)

Create a payment link once in Stripe and send it in your DM flows.

Step 1: Create a Payment Link in Stripe

  1. Go to dashboard.stripe.com.
  2. Navigate to Payment LinksNew.
  3. Add your product or set a custom amount.
  4. Configure options (quantity, tax, shipping if needed).
  5. Click Create link.
  6. Copy the URL (e.g., https://buy.stripe.com/abc123).

Step 2: Use in InstantDM Flows

Add the payment link as a button in your DM flow:

  • In the Flow Editor, add a Button node.
  • Set the button text to "Pay Now" or "Complete Purchase".
  • Set the URL to your Stripe payment link.

Or send it via the API:

{
  "action": "send_message",
  "type": "buttons",
  "recipient_id": "INSTAGRAM_USER_ID",
  "message": "Great choice! Here's your payment link:",
  "buttons": [
    { "title": "Pay $49", "url": "https://buy.stripe.com/abc123" }
  ]
}

Method 2: Dynamic Payment Links (Per Customer)

Generate unique payment links with custom amounts, pre-filled customer info, or metadata.

Step 1: Get Your Stripe API Key

  1. In Stripe Dashboard, go to Developers → API keys.
  2. Copy your Secret key (starts with sk_).

Step 2: Build a Webhook Receiver

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

const STRIPE_SECRET = process.env.STRIPE_SECRET_KEY;
const INSTANTDM_API_KEY = process.env.INSTANTDM_API_KEY;

async function createPaymentLink(amount, productName, customerEmail, metadata = {}) {
  // Create a price
  const priceResponse = await fetch('https://api.stripe.com/v1/prices', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${STRIPE_SECRET}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
      'unit_amount': String(amount), // in cents
      'currency': 'usd',
      'product_data[name]': productName,
    }),
  });
  const price = await priceResponse.json();
  
  // Create a payment link
  const linkParams = new URLSearchParams({
    'line_items[0][price]': price.id,
    'line_items[0][quantity]': '1',
  });
  
  if (customerEmail) {
    linkParams.set('customer_email', customerEmail);
  }
  
  // Add metadata
  Object.entries(metadata).forEach(([key, value]) => {
    linkParams.set(`metadata[${key}]`, value);
  });
  
  const linkResponse = await fetch('https://api.stripe.com/v1/payment_links', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${STRIPE_SECRET}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: linkParams,
  });
  
  return linkResponse.json();
}

app.post('/instantdm-webhook', async (req, res) => {
  const { event, data } = req.body;
  
  if (event !== 'flow_completed') {
    return res.status(200).json({ status: 'skipped' });
  }
  
  const interest = data.response_variables?.interest;
  if (!interest) return res.status(200).json({ status: 'skipped' });
  
  // Map interests to products and prices
  const products = {
    'starter': { name: 'Starter Plan', amount: 4900 },
    'pro': { name: 'Pro Plan', amount: 9900 },
    'enterprise': { name: 'Enterprise Plan', amount: 29900 },
  };
  
  const product = products[interest.toLowerCase()];
  if (!product) return res.status(200).json({ status: 'skipped', reason: 'unknown interest' });
  
  try {
    const paymentLink = await createPaymentLink(
      product.amount,
      product.name,
      data.response_variables?.email,
      {
        instagram_username: data.username,
        flow_name: data.flow_name,
      }
    );
    
    // Send the payment link via InstantDM
    await fetch('https://api.instantdm.com/api-webhook', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${INSTANTDM_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        action: 'send_message',
        type: 'buttons',
        recipient_id: data.instagram_user_id,
        message: `Here's your personalized checkout for the ${product.name}:`,
        buttons: [
          { title: `Pay $${(product.amount / 100).toFixed(2)}`, url: paymentLink.url },
        ],
      }),
    });
    
    res.status(200).json({ status: 'sent', paymentUrl: paymentLink.url });
  } catch (error) {
    res.status(500).json({ status: 'error', message: error.message });
  }
});

app.listen(3000);

Method 3: Stripe Checkout Sessions

For more control (custom success pages, subscription billing, etc.), use Checkout Sessions:

async function createCheckoutSession(amount, productName, customerEmail, metadata) {
  const response = await fetch('https://api.stripe.com/v1/checkout/sessions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${STRIPE_SECRET}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
      'mode': 'payment',
      'success_url': 'https://yoursite.com/thank-you',
      'cancel_url': 'https://yoursite.com/cancelled',
      'customer_email': customerEmail || '',
      'line_items[0][price_data][currency]': 'usd',
      'line_items[0][price_data][unit_amount]': String(amount),
      'line_items[0][price_data][product_data][name]': productName,
      'line_items[0][quantity]': '1',
      ...Object.fromEntries(
        Object.entries(metadata || {}).map(([k, v]) => [`metadata[${k}]`, v])
      ),
    }),
  });
  return response.json();
}

Handling Payment Confirmation

Get notified when a payment is completed and send a thank-you DM.

Step 1: Set Up a Stripe Webhook

  1. In Stripe Dashboard, go to Developers → Webhooks.
  2. Click Add endpoint.
  3. Set the URL to your server (e.g., https://your-server.com/stripe-webhook).
  4. Select event: checkout.session.completed.

Step 2: Handle the Webhook

app.post('/stripe-webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const event = JSON.parse(req.body);
  
  if (event.type === 'checkout.session.completed') {
    const session = event.data.object;
    const instagramUsername = session.metadata?.instagram_username;
    
    if (instagramUsername) {
      // Look up the Instagram user ID from your database
      // Then send a thank-you DM
      await fetch('https://api.instantdm.com/api-webhook', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${INSTANTDM_API_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          action: 'send_message',
          type: 'text',
          recipient_id: session.metadata.instagram_user_id,
          message: `🎉 Payment received! Thank you for your purchase. We'll send you access details shortly.`,
        }),
      });
    }
  }
  
  res.status(200).json({ received: true });
});

Troubleshooting

Issue Solution
Payment link not working Verify the link URL is correct. Check that the product/price is active in Stripe.
Stripe API returning 401 Verify your Secret key. Ensure you're using the correct key (test vs. live).
Customer email not pre-filled Pass customer_email when creating the payment link or checkout session.
Webhook not receiving events Verify the webhook endpoint URL in Stripe. Check that the endpoint is publicly accessible.
Payment link expired Payment links don't expire by default. Check if you set an expires_at parameter.

Frequently Asked Questions

How much does Stripe charge?

Stripe charges 2.9% + $0.30 per successful transaction (US pricing). No monthly fees, no setup fees. International cards and currency conversion have additional fees.

Can I use Stripe for subscriptions via DM?

Yes. Create a Payment Link with mode: subscription and a recurring price. The customer subscribes through the link, and Stripe handles recurring billing.

Should I use Payment Links or Checkout Sessions?

Payment Links are simpler - create once, share the URL. Checkout Sessions give you more control (custom success pages, metadata, expiration). For most DM use cases, Payment Links are sufficient.

Can I send payment links in InstantDM flow buttons?

Yes. In the Flow Editor, add a Button node with the payment link URL. The button opens the Stripe checkout in the user's browser.


What's Next

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.