Documentation Index
Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Beta. The Automations API is in beta and we are actively collecting feedback. Endpoints, payloads, and limits may change as we iterate. Please send feedback and bug reports to support so we can prioritize the right improvements.
How it works
Create an automation
POST /automations with the triggers and actions you want. The automation activates immediately.An end user engages
Someone comments on your post, replies to your story, sends a DM, or reacts to a DM. Meta delivers the webhook to Ayrshare.
Ayrshare matches and dispatches
The engine looks up every rule matching the event, checks per-action deduplication and your daily DM cap, then runs each action. A 20–60 second jitter is applied to DM sends to stay inside Instagram’s anti-spam heuristics.
Triggers
You can attach up to 50 triggers to one automation. Each trigger is a discriminated union on thetype field; type-specific fields live at the same level. All triggers are Instagram-only in v1.
| Type | Fires when | Config |
|---|---|---|
comment_keyword | A comment matching a keyword lands on a specific post | postId (required); keywords (required, ≥1 entry) |
story_reply | A user replies to a story via DM | storyId (optional) |
dm_reaction | A user reacts to one of your DMs with an emoji | emoji (optional — omit to fire on any emoji) |
dm_keyword | A user sends a DM whose text matches a keyword | keywords (required, ≥1 entry) |
storyId on a story trigger to fire on every story for the connected account.
Actions
You can attach up to 50 actions to one automation. They run sequentially; each result is recorded on the activity row.| Type | Effect | Config |
|---|---|---|
send_dm | Sends an Instagram DM to the user who triggered the rule, using a templated message. | message (required, templated) |
fire_webhook | POSTs the automation context to your account-level webhook URL (configure via POST /hook/webhook). | (none — payload shape is fixed; see below) |
send_email | Queues an email via the platform’s mail pipeline. | to (required, email); subject (optional, templated); message (required, templated) |
Per-action dedup window
Every action — regardless of type — additionally accepts an optional top-leveldedupWindowMinutes field that overrides the default 7-day per-recipient dedup window for that action only.
- Set to
0to disable dedup entirely for that action (typical forfire_webhook/send_emailwhere the receiver expects every event). - Capped at
525600(one year).
Action with a 24h dedup override
fire_webhook payload
When fire_webhook runs it POSTs a JSON body to your account-level webhook URL:
recipientUsername and keyword are null when the trigger doesn’t populate them (e.g. dm_keyword doesn’t carry a username on Meta’s payload; story_reply doesn’t have a keyword).
Template variables
send_dm.message, send_email.subject, and send_email.message support {{placeholder}} substitution. Unknown placeholders are rejected at create/update time (error 467) so a typo never silently leaks the literal {{foo}} into a customer-facing message.
| Placeholder | Resolves to |
|---|---|
{{recipient_username}} | The engaging user’s Instagram handle (when the webhook carries it) |
{{recipient_id}} | The engaging user’s Instagram participant ID (IGSID) |
{{recipient_name}} | Reserved; resolves to empty until a future enrichment source populates it |
{{sender_username}} | Your linked Instagram username |
{{sender_name}} | Your linked Instagram display name |
{{comment_text}} | The text of the comment / DM / story reply that fired the trigger |
{{comment_id}} | The platform id of the comment / message that fired |
{{comment_sent_at}} | ISO 8601 timestamp of the event (when available) |
{{matched_keyword}} | The keyword that matched (or the emoji string for dm_reaction) |
{{platform}} | Platform identifier (e.g. instagram) |
{{trigger_type}} | Trigger type (e.g. comment_keyword) |
No
sender_email / recipient_email. These are deliberately not exposed — your billing email has no legitimate place in a DM to a stranger, and Meta does not provide the recipient’s email on any IG webhook. Avoiding the placeholders prevents accidental disclosure.Rate limits and caps
| Plan | Active automations | Daily DM cap |
|---|---|---|
| Business | 10 | 1,000 |
| Enterprise | 50 | 5,000 |
rate_limited and no DM is sent. The active-automation cap is enforced on both POST (create) and on PUT when re-activating (active: false → true) — both surface error code 470.
Structural caps on a single automation: 1–50 triggers, 1–50 actions.
Instagram itself caps DMs at roughly 200/hour per account. The engine paces dispatch with a 20–60 second jitter to stay safely under this.
Activity statuses
A row inGET /automations/:id/activity carries a top-level status plus a per-action status inside actionResults[]:
| Status | Meaning |
|---|---|
pending | Just written; the worker hasn’t picked it up yet |
in_flight | Worker is currently dispatching |
sent | Every action succeeded |
failed | At least one action failed (and none hit an auth error) |
auth_error | The Instagram access token was invalid; the DM was not retried |
rate_limited | The daily DM cap (tier or per-profile) was hit; no DM was sent |
deduplicated | This action already fired to this recipient inside its dedup window |
skipped | The automation became inactive or was deleted between fan-out and dispatch |
pending and in_flight are transient; everything else is terminal.
Error codes
| Code | HTTP | Meaning |
|---|---|---|
| 462 | 400 | Missing required field: trigger |
| 463 | 400 | Invalid trigger type |
| 464 | 400 | Missing postId (required for comment_keyword) |
| 465 | 400 | Missing keywords (required for comment_keyword) |
| 466 | 400 | Missing message (required for send_dm / send_email) |
| 467 | 400 | Unknown template variable in message / subject |
| 468 | 403 | Business or Enterprise plan required |
| 469 | 404 | Automation not found (also returned when the caller doesn’t own it) |
| 470 | 429 | Active automation cap reached for your plan tier |
| 471 | 404 | No social account linked on the requested platform for this profile |
| 472 | 403 | Feature not yet available on your account — contact us for early access |
What Meta does NOT allow
A few commonly-requested capabilities are not supported because Meta doesn’t permit them on the public Instagram API:- Auto-DM on new followers. Instagram does not publish a follow webhook.
- First-message DMs to strangers. Meta requires the recipient to initiate contact (comment, reply, DM, reaction) before a business account can message them — which is exactly what every supported trigger here represents.
- Bulk outbound campaigns. Hourly DM caps and anti-abuse heuristics apply at the platform level.
Multi-profile usage
The endpoints respect theprofileKey header. Pass a child profile’s key and the automation is created/managed under that profile. Rate limits split across profiles via a per-profile sub-cap so one chatty profile doesn’t drain the parent account’s quota.
FAQ
Can I trigger on a new follower?
Can I trigger on a new follower?
No. Instagram does not publish a follow webhook, and Meta does not allow third-party apps to send a DM to a user who has not initiated a conversation. Every supported trigger (
comment_keyword, story_reply, dm_reaction, dm_keyword) satisfies the “user contacted you first” requirement.What happens if my access token is invalid when an automation fires?
What happens if my access token is invalid when an automation fires?
The activity row records status
auth_error and the DM is not retried. Relink the account, then the next matching engagement will fire normally.Why is there a delay before the DM is sent?
Why is there a delay before the DM is sent?
Each
send_dm dispatch is scheduled 20–60 seconds after the engagement to look organic to Instagram’s anti-spam systems. fire_webhook and send_email actions do NOT have jitter. The activity row’s created timestamp is when the trigger matched; completedAt is when dispatch finished.Are activity rows kept forever?
Are activity rows kept forever?
Activity rows are retained indefinitely for trace and analytics. The
GET /automations/:id/activity endpoint returns rows from the last 30 days for performance. (The dedup guard uses its own per-action window — defaulting to 7 days — which is unrelated to the activity lookback.)Does deleting an automation remove its activity history?
Does deleting an automation remove its activity history?
No. Delete is a soft-delete: the master row is flagged
deleted, no new dispatches occur, but historical activity rows remain readable via the activity endpoint.Endpoints
POST /automations— create a new automationGET /automations— list your automationsGET /automations/:id— fetch one automation with its triggers and actionsPUT /automations/:id— partial update; pause viaactive: falseDELETE /automations/:id— soft-deleteGET /automations/:id/activity— cursor-paginated dispatch audit log
