# Automations API

The kinds of automation Zernio runs for you, from chat workflows and comments to DM to sequences, event alerts and ad rules, and when to pick each.

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

Automations let Zernio act for you when something happens: a DM arrives, someone comments a keyword, a contact joins a list, a post fails. Zernio runs them, not your server.

## What you can build

| You want | Use | Create it with |
|---|---|---|
| A chat flow: ask, wait for the answer, branch, hand off to a human | [Workflows](/products/automations/workflows) | `POST /v1/workflows` |
| A DM or public reply to everyone who comments a keyword | [Comments to DM](/products/comments-to-dm) | `POST /v1/comment-automations` |
| A drip of timed messages to the contacts you enroll | [Sequences](/sequences/create-sequence) | `POST /v1/sequences` |
| An alert or action when something happens in Zernio | [Event automations](/guides/automations) | `POST /v1/automations` |
| Changes to ad campaigns based on their results | [Ad rules](/guides/ad-rules) | `POST /v1/automations` |

## Platforms

<ProductPlatforms product="automations" />

The tiles show every platform an automation reaches. Each kind runs on its own set:

| Kind | Runs on |
|---|---|
| Workflows | WhatsApp, Instagram, Facebook, Telegram, X, Bluesky, Reddit and TikTok, one messaging account each |
| Comments to DM | DMs on Instagram and Facebook. Public replies on TikTok, Threads, LinkedIn and YouTube |
| Sequences | Instagram, Facebook, WhatsApp, Telegram, X, Bluesky, Reddit, Slack and iMessage |
| Event automations | Every account of a profile, alerting through Slack or email |
| Ad rules | Your connected ad accounts |

## How it works

A **workflow** is a graph of steps on one messaging account, for conversations that take more than one turn.

Its trigger can be a DM, a ref link, a comment, a story mention, a reaction, a lead form or your own API call.

A **comment automation** is a keyword rule, not a graph. It answers a matching comment with a DM, a public reply or both. Add a button to continue into a workflow.

A **sequence** sends a series of messages, each after a delay, to the contacts you enroll. On WhatsApp a step can be a template, so it reaches contacts outside the 24-hour window.

An **event or scheduled automation** watches your whole account: alert Slack when a post fails, or boost a post that takes off. **Ad rules** pause, scale or edit ads on a schedule.

## Your first request

This event automation posts in a Slack channel whenever an Instagram post of the profile fails. `to` names a connected Slack account and a channel.

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data } = await zernio.automations.createAutomation({
  body: {
    name: 'Failed Instagram posts to Slack',
    trigger: {
      type: 'post.failed',
      profileId: '6731a0c2e4b0f1a2b3c4d5e6',
      filter: { field: 'platform', op: 'equals', value: 'instagram' },
    },
    steps: [{ type: 'notify.send', to: [{ accountId: '6731a0c2e4b0f1a2b3c4d5f7', channelId: 'C0123456789' }] }],
    limits: { cooldown: '1h' },
  },
});

console.log(data.automation.id);
```
</Tab>
<Tab value="Python">
```python
from zernio import Zernio

client = Zernio()

created = client.automations.create_automation(
    body={
        "name": "Failed Instagram posts to Slack",
        "trigger": {
            "type": "post.failed",
            "profileId": "6731a0c2e4b0f1a2b3c4d5e6",
            "filter": {"field": "platform", "op": "equals", "value": "instagram"},
        },
        "steps": [{"type": "notify.send", "to": [{"accountId": "6731a0c2e4b0f1a2b3c4d5f7", "channelId": "C0123456789"}]}],
        "limits": {"cooldown": "1h"},
    },
)

print(created["automation"]["id"])
```
</Tab>
<Tab value="curl">
```bash
curl -X POST "https://zernio.com/api/v1/automations" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Failed Instagram posts to Slack",
    "trigger": {
      "type": "post.failed",
      "profileId": "6731a0c2e4b0f1a2b3c4d5e6",
      "filter": { "field": "platform", "op": "equals", "value": "instagram" }
    },
    "steps": [{ "type": "notify.send", "to": [{ "accountId": "6731a0c2e4b0f1a2b3c4d5f7", "channelId": "C0123456789" }] }],
    "limits": { "cooldown": "1h" }
  }'
```
</Tab>
</Tabs>

Response (`201`), trimmed:

```json
{
  "automation": {
    "id": "6741b2d3e4f5a6b7c8d9e0f1",
    "kind": "event",
    "status": "active",
    "name": "Failed Instagram posts to Slack",
    "createdAt": "2026-11-10T09:00:00Z"
  }
}
```

An event automation is on as soon as it is created, unless you send `"status": "paused"`.

## Examples

### Enroll contacts in a sequence

Once a sequence is active, enroll contacts by id. Contacts already enrolled are skipped, and the response reports each one.

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
const { data: result } = await zernio.sequences.enrollContacts({
  path: { sequenceId: '66f0a1b2c3d4e5f6a7b8c9d0' },
  body: { contactIds: ['66e5b2c3d4f5a6b7c8d9e0f1', '66e5b2c3d4f5a6b7c8d9e0f2'] },
});

console.log(result.enrolled, result.failed);
```
</Tab>
<Tab value="Python">
```python
result = client.sequences.enroll_contacts(
    sequence_id="66f0a1b2c3d4e5f6a7b8c9d0",
    contact_ids=["66e5b2c3d4f5a6b7c8d9e0f1", "66e5b2c3d4f5a6b7c8d9e0f2"],
)

print(result["enrolled"], result["failed"])
```
</Tab>
<Tab value="curl">
```bash
curl -X POST "https://zernio.com/api/v1/sequences/66f0a1b2c3d4e5f6a7b8c9d0/enroll" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["66e5b2c3d4f5a6b7c8d9e0f1", "66e5b2c3d4f5a6b7c8d9e0f2"] }'
```
</Tab>
</Tabs>

A workflow can enroll the contact it is talking to with an `enroll_sequence` step.

### Start a workflow from your backend

A workflow whose trigger is `api_call` runs when you call `POST /v1/workflows/{workflowId}/trigger`. `variables` become `{{orderId}}` and friends inside the workflow.

```bash
curl -X POST "https://zernio.com/api/v1/workflows/66d4a1b2c3e4f5a6b7c8d9e1/trigger" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "66e5b2c3d4f5a6b7c8d9e0f1", "variables": { "orderId": "A-1042" } }'
```

The [workflows page](/products/automations/workflows) builds a full one, and [Comments to DM](/products/comments-to-dm) creates a keyword rule.

## How it behaves

- **Comment automations win.** When a comment automation and a comment workflow match the same comment, only the automation answers.
- **One trigger, one start.** A redelivered platform event never starts the same workflow twice, and each comment is answered at most once.
- **Inbox access.** Workflows, sequences and comment automations send through the inbox, so legacy plans without it get `403` `INBOX_REQUIRED`.
- **Billing.** Past 2,000 runs a month, each run costs $0.002 ([automation pricing](/pricing/automations)). Messages they send also count as [outbound messages](/pricing/inbox).
- **Follow runs.** [Inbox webhooks](/webhooks/inbox) report workflow runs and sequence enrollments as they happen.

## Related

- [Workflows](/products/automations/workflows)
- [Comments to DM](/products/comments-to-dm)
- [Create sequence](/sequences/create-sequence)
- [Automations guide](/guides/automations)
- [Ad rules](/guides/ad-rules)
- [Automation pricing](/pricing/automations)