Developers · Agents

Let your AI run your Instagram.

Every DMowl feature is an MCP tool and a REST endpoint — generated from one registry, so docs, API and app never drift. Connect Claude or ChatGPT in 30 seconds.

claude mcp add --transport http dmowl https://dmowl.com/mcp \
  --header "Authorization: Bearer pk_live_…"
Then ask: “Create a comment-to-DM for my next reel with keyword RECIPE and show it to me.”

Auth

Bearer API key (pk_live_…) from Settings → API & MCP. Keys are hashed; you see them once.

Safety for agents

Automations are created as drafts. Tools that message real people are annotated destructiveHint so clients ask before running them.

Instagram rules built in

24h messaging window, verified follows, opt-outs — enforced server-side, explained in tool descriptions.

Account

get_account

read-only

Returns the connected Instagram account, plan and this month’s usage against the plan limits (active contacts, AI replies, automations, campaigns, seats). Call this first to orient yourself.

GET/api/v1/account

get_stats

read-only

Aggregated performance for the last N days: inbound/outbound messages, activated contacts, link clicks (conversions), and the top automations by conversions.

GET/api/v1/stats
daysintegerWindow in days (1–365). Default 30.

record_conversion

Attribute a sale to the DM that caused it. DMowl links forward with a `dmo` URL parameter (Stripe Payment Links: client_reference_id "dmo_<id>") — pass that value as `ref`. Idempotent per order_id. Sales without a DMowl ref are ignored.

POST/api/v1/conversions
ref*stringThe dmo value from the landing URL (or client_reference_id)
order_id*stringYour order or payment id (used to avoid duplicates)
amount*numberOrder value in major units, e.g. 49.90
currency*stringISO currency code, e.g. EUR

Contacts

list_contacts

read-only

Search the CRM. Filter by text (name, @handle, email), folder, follower status or having an email. Returns at most `limit` contacts, newest activity first.

GET/api/v1/contacts
querystringFree-text search
folder_idstringOnly contacts in this folder
follows_youbooleanOnly followers
has_emailbooleanOnly contacts with an email
limitintegerMax results (1–500). Default 50.

get_contact

read-only

One contact with folders, custom properties and their latest 20 messages.

GET/api/v1/contacts/{contact_id}
contact_id*stringContact id

update_contact

Set email/phone, merge custom properties, and add or remove folders. Properties are merged, not replaced; set a property to null to delete it.

PATCH/api/v1/contacts/{contact_id}
contact_id*stringContact id
emailstringEmail address
phonestringPhone number
propertiesobjectKey/value pairs to merge
add_foldersarrayFolder ids to add
remove_foldersarrayFolder ids to remove

list_folders

read-only

Folders (segments/tags) with contact counts. Use folder ids for filtering, campaign audiences and automation steps.

GET/api/v1/folders

create_folder

Create a folder to segment contacts.

POST/api/v1/folders
name*stringFolder name

Inbox

send_message

Send a direct message to a contact as the account owner. Instagram only delivers business messages within 24 hours of the contact’s last message. Sending pauses automations and AI for that contact (a human took over) unless keep_automation is true.

POST/api/v1/contacts/{contact_id}/messages
contact_id*stringContact id
text*stringMessage text (max 1000 chars)
keep_automationbooleanDo not switch the conversation to human handling

set_handling

Decide who handles a conversation: "human" (you; automations pause), "agent" (AI agent replies) or "none" (automations decide).

POST/api/v1/contacts/{contact_id}/handling
contact_id*stringContact id
handled_by*string · human | agent | none

Automations

list_automations

read-only

All automations (scenarios) with trigger, steps, status and performance.

GET/api/v1/automations
statusstring · active | paused | draftFilter by status

get_automation

read-only

One automation with its full trigger and steps.

GET/api/v1/automations/{automation_id}
automation_id*stringAutomation id

create_automation

Create an automation as a draft. trigger.type: comment | dm | story_reply | mention | live_comment. trigger.match: "keywords" (with trigger.keywords) or "any". For comment triggers set commentReplies (public reply variants) and optionally posts="selected" + postIds. Activate it afterwards with set_automation_status. Prefer create_automation_from_prompt or create_automation_from_template when you don’t need full control.

POST/api/v1/automations
name*stringName
trigger*objectTrigger config (see description)
steps*arrayOrdered steps. Types: message {text, buttons[]}, question {text, buttons[], property}, link {text, title, url, button, followUp, followUpMinutes}, ask_email {text}, ask_follow {text, button, failText?}, check {conditions[], failText, retryButton}, delay {minutes}, folder {folderId}, giveaway {giveawayId, text}, agent {note}. Use {{first_name}} to personalise.

create_automation_from_prompt

Describe a comment-to-DM automation in plain language (e.g. "send my PDF to everyone who comments GUIDE"). DMowl drafts keywords, replies, DM and link. Returns the draft — review, then activate.

POST/api/v1/automations/from-prompt
prompt*stringWhat should happen
languagestring · en | de

list_templates

read-only

Proven automation and campaign templates. Use a slug with create_automation_from_template.

GET/api/v1/templates
languagestring · en | de

create_automation_from_template

Copy a template into a new draft automation, optionally overriding the trigger keywords.

POST/api/v1/automations/from-template
slug*stringTemplate slug
keywordsarray
languagestring · en | de

update_automation

Replace name, trigger and/or steps of an automation. Omitted fields stay unchanged. Trigger fields are merged.

PATCH/api/v1/automations/{automation_id}
automation_id*stringAutomation id
namestringName
triggerobject
stepsarrayOrdered steps. Types: message {text, buttons[]}, question {text, buttons[], property}, link {text, title, url, button, followUp, followUpMinutes}, ask_email {text}, ask_follow {text, button, failText?}, check {conditions[], failText, retryButton}, delay {minutes}, folder {folderId}, giveaway {giveawayId, text}, agent {note}. Use {{first_name}} to personalise.

set_automation_status

Set status to "active" (starts reacting to real comments/DMs) or "paused". Activation validates keywords and steps and respects plan limits.

POST/api/v1/automations/{automation_id}/status
automation_id*stringAutomation id
status*string · active | paused

run_automation_for_contact

Manually start an automation’s steps for one contact (skips the trigger).

POST/api/v1/automations/{automation_id}/run
automation_id*stringAutomation id
contact_id*stringContact id

delete_automation

confirm first

Permanently delete an automation. Its past messages stay in the inbox.

DELETE/api/v1/automations/{automation_id}
automation_id*stringAutomation id

Campaigns

list_campaigns

read-only

DM campaigns with status and results (sent, replied, conversions).

GET/api/v1/campaigns

create_campaign

Create a draft campaign. audience.type: "active" (wrote in last 24h — safest under Instagram rules), "all", "followers" or "folder" (+ folder_id). Send it with send_campaign.

POST/api/v1/campaigns
name*stringName
audience*object{ type, folder_id? }
steps*arrayOrdered steps. Types: message {text, buttons[]}, question {text, buttons[], property}, link {text, title, url, button, followUp, followUpMinutes}, ask_email {text}, ask_follow {text, button, failText?}, check {conditions[], failText, retryButton}, delay {minutes}, folder {folderId}, giveaway {giveawayId, text}, agent {note}. Use {{first_name}} to personalise.

send_campaign

confirm first

Send a draft campaign now, or schedule it with an ISO timestamp in `at`. This messages real people — confirm with the user before calling.

POST/api/v1/campaigns/{campaign_id}/send
campaign_id*stringCampaign id
atstringOptional ISO 8601 time to schedule

Giveaways

list_giveaways

read-only

Giveaways with entry counts, status and winners (if drawn).

GET/api/v1/giveaways

create_giveaway

Create a giveaway. Then create an entry automation with a "giveaway" step (or ask the user to click “Create entry automation” in the app).

POST/api/v1/giveaways
name*stringName
prizestringPrize
winnersintegerNumber of winners
require_followbooleanVerify the follow (default true)

draw_giveaway

confirm first

Draw winners at random (follow re-verified), optionally DM them, and return the auditable draw record. Irreversible — confirm with the user first.

POST/api/v1/giveaways/{giveaway_id}/draw
giveaway_id*stringGiveaway id
notify_winnersboolean

AI Agent

get_agent

read-only

The AI agent’s activation mode and full configuration (voice, goals, knowledge base, links, handoff rules).

GET/api/v1/agent

update_agent

Change mode ("all" | "intents" | "automation" | "off") and/or merge config fields: role, length, styleRules, examples, description, goals, audience, instructions, knowledge, collect[], handoffKeywords, links[{label,url}], excludedFolders[], intents. Tip: append to `knowledge` rather than replacing it.

PATCH/api/v1/agent
modestring · all | intents | automation | off
configobject