Developers
The DMpop API.And MCP.
Create comment-to-DM campaigns from your own tools. A content pipeline can publish a reel and switch on its DM automation in the same step, or your AI assistant can do it when you ask.
Authentication
Create a key in Settings → API keys. It is shown once, so store it somewhere safe. Send it with every request:
Authorization: Bearer dmp_your_key_hereBase URL: https://app.dmpop.com/api/v1. Requests and responses are JSON. Each key can make 60 requests a minute. A key acts for its whole workspace, so treat it like a password.
Typical pipeline
Either create the campaign before you post, and DMpop attaches it to the next reel within about five minutes of it going live:
curl -X POST https://app.dmpop.com/api/v1/campaigns \ -H "Authorization: Bearer $DMPOP_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Hooks guide reel", "nextReel": true, "keywords": ["GUIDE"], "message": "Hey {username}, here is the guide you asked for.", "link": "https://example.com/guide", "buttonLabel": "Get the guide", "publicReplies": ["Sent you a DM!"] }'Or, if your pipeline publishes first and knows the post ID, attach it directly with "postId": "1789..." instead of nextReel.
Use with ChatGPT, Claude, Codex or Cursor (MCP)
DMpop is also an MCP server, so an AI assistant can list your posts and create, pause or delete campaigns when you ask it to. The MCP guide walks through each app.
ChatGPT and Claude (no key needed). Add https://app.dmpop.com/mcp as a custom connector. In ChatGPT: Settings → Apps → Advanced settings → Developer mode, then create an app with OAuth. In Claude: Customize → Connectors → Add custom connector. You sign in to DMpop and allow access; disconnect any time in Settings → API keys and MCP.
Command-line tools can use an API key instead.
claude mcp add --transport http dmpop https://app.dmpop.com/mcp \ --header "Authorization: Bearer dmp_your_key_here"[mcp_servers.dmpop]url = "https://app.dmpop.com/mcp"bearer_token_env_var = "DMPOP_API_KEY"{ "mcpServers": { "dmpop": { "url": "https://app.dmpop.com/mcp", "headers": { "Authorization": "Bearer dmp_your_key_here" } } }}Tools: list_instagram_accounts, list_recent_posts, list_campaigns, get_campaign, create_campaign, update_campaign and delete_campaign. Then just ask, for example: “Set up a DMpop campaign on my next reel: when people comment GUIDE, DM them https://example.com/guide.”
Endpoints
| Endpoint | What it does |
|---|---|
GET /accounts | Connected Instagram accounts. |
GET /posts?accountId=&limit=12 | Recent posts and reels with their IDs (up to 25). |
GET /campaigns | All campaigns with their numbers. |
POST /campaigns | Create a campaign. |
GET /campaigns/{id} | One campaign with sends, skips, failures, clicks and click rate. |
PATCH /campaigns/{id} | Change any field. Only the fields you send change. Send {"active": false} to pause. |
DELETE /campaigns/{id} | Delete a campaign. |
Campaign fields
| Field | Type | What it does |
|---|---|---|
| name | string, required | A label for the campaign. |
| message | string, required | The DM text. Use {username} for the person's handle and {link} to place the tracked link in the text. |
| nextReel | boolean | Attach to the next reel you publish. Use this when the campaign is created before posting. |
| postId | string | Attach to an existing post or reel. Get IDs from GET /posts. |
| anyPost | boolean | Run on every post. Exactly one of nextReel, postId or anyPost is needed. |
| keywords | string[] | Up to 10 trigger words, e.g. ["GUIDE"]. Needed unless anyWord is true. |
| anyWord | boolean | Reply to every comment, whatever it says. |
| wholeWord | boolean | Match whole words only. Default true. |
| link | URL | The link to send. Taps are counted unless trackClicks is false. |
| buttonLabel | string, max 20 | Text on the link button, e.g. "Get the guide". |
| secondLink, secondButtonLabel | URL, string | An optional second link button. |
| trackClicks | boolean | Default true: links go through a DMpop redirect so taps are counted. False sends links exactly as given, e.g. for affiliate programmes that don't allow redirects. |
| publicReplies | string[] | Public replies posted under the comment. One is picked at random each time. |
| openingMessage, openingButtonLabel | string, string | Send a short opener with a button first; the link follows when it is tapped. |
| requireFollow, followPrompt, followButtonLabel | boolean, string, string | Only send the link to people who follow you. |
| followUpMessage, followUpDelayMinutes | string, 0 to 1440 | An optional later message. |
| alsoOnDms | boolean | Also reply when someone sends the keyword in a DM or Story reply. |
| accountId | string | Which connected account to use. Defaults to the most recently connected one. |
| active | boolean | Default true. Set false to create the campaign paused. |
Responses and errors
Successful calls return { "data": ... }. A campaign looks like this:
{ "data": { "id": "cmv...", "name": "Hooks guide reel", "active": true, "trigger": "next_reel", "postId": null, "keywords": ["GUIDE"], "links": [{ "url": "https://example.com/guide", "label": null, "trackedUrl": "https://app.dmpop.com/r/..." }], "stats": { "sent": 0, "skipped": 0, "failed": 0, "clicks": 0, "ctr": 0 } }}Errors return { "error": { "message": "...", "details": ... } } with a status code: 400 for an invalid request, 401 for a missing or revoked key, 404 for something that doesn't exist, 429 when the rate limit is hit. Unknown fields are rejected, so typos don't pass silently.
Questions: hello@dmpop.com. Campaigns made through the API follow the same rules as the dashboard, including Instagram's limits and our Terms.