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
- Go to dashboard.stripe.com.
- Navigate to Payment Links → New.
- Add your product or set a custom amount.
- Configure options (quantity, tax, shipping if needed).
- Click Create link.
- 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
- In Stripe Dashboard, go to Developers → API keys.
- 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
- In Stripe Dashboard, go to Developers → Webhooks.
- Click Add endpoint.
- Set the URL to your server (e.g.,
https://your-server.com/stripe-webhook). - 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
- Set up Razorpay for Indian payment processing.
- Connect to Shopify for full e-commerce integration.
- Read the WooCommerce guide for WordPress stores.
- Build a Custom AI Agent to handle pricing inquiries.
- Explore the full API docs at instantdm.com/instagram-api-docs.