# Automations

> Workflows, statistics, runs, activating, pausing, adding subscribers.

Reading needs Automations: view, every action Automations: manage.

## What the API can do

Workflows are built in the app. The API reads them with their triggers and steps, reports their numbers, activates and pauses them, and moves subscribers in and out.

| Method and path | What it does |
|---|---|
| `GET /automations` | Lists workflows. |
| `GET /automations/{id}` | One workflow with its triggers and steps. |
| `GET /automations/{id}/stats` | Numbers per email step and per A/B split. |
| `GET /automations/{id}/runs` | The subscribers' runs. |
| `POST /automations/{id}/activate` | Activates for new subscribers. |
| `POST /automations/{id}/pause` | Pauses. |
| `POST /automations/{id}/subscribers` | Queues subscribers to enter from the start. |
| `DELETE /automations/{id}/subscribers/{subscriber_id}` | Cancels a subscriber's active run. |

## List and read workflows

`GET /automations` lists every workflow, last change first, without triggers and steps. Parameters: `status` (`draft`, `active`, `paused`), `search` (name contains), `limit`, `cursor`.

```bash
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/automations/477323d4-1ba3-4658-b70d-a7d94ceed56b"
```

```json
{"data":{"id":"477323d4-1ba3-4658-b70d-a7d94ceed56b","name":"Welcome email (EN)","status":"active","reenter":false,"created_at":"2026-05-05T06:00:00Z","updated_at":"2026-05-05T09:00:00Z","issues":[],"stats":{"active":0,"completed":660,"canceled":0,"failed":0},"triggers":[{"id":"t1","type":"joins_group","settings":{"exclude_groups":[],"groups":["5e30c6ff-0462-47d1-9a6c-7db4c33d6b9a"]}}],"steps":[{"id":"e1","type":"email","parent":null,"settings":{"from_email":"hirlevel@news.kertlak.example.com","from_name":"Kertlak Garden Shop","subject":"Welcome to Kertlak, {$name}"}}]}}
```

| Key | Meaning |
|---|---|
| `status` | `draft`, `active` or `paused`. |
| `reenter` | Whether subscribers may enter the workflow again. |
| `issues` | What the workflow misses before it can be activated, each with a `code` (for example `no_trigger`, `no_steps`, `subject_required`, `sender_unverified`) and the `trigger` or `step` it concerns. |
| `stats` | Runs by status: `active`, `completed`, `canceled`, `failed`. |
| `triggers` | Single-workflow answers only. `type`: `joins_group`, `clicks_link`, `updated_field`, `anniversary`, `exact_date`, `joins_segment`, with its `settings`. |
| `steps` | Single-workflow answers only. `type`: `delay`, `condition`, `split`, `email`, `webhook`, `notify`, `move_to_step`, `update_field`, `copy_to_groups`, `move_to_groups`, `remove_from_groups`, `unsubscribe`. `parent` is the step a run comes from (`null` for the first), `branch` is `yes` or `no` after a condition, `a`, `b` or `c` after an A/B split. |

Email steps show their subject and sender, never the content. Webhook steps show only the target's origin. A step type added later shows only `id`, `type`, `parent` and `branch`, so ignore types you don't know.

## Statistics

```bash
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/automations/477323d4-1ba3-4658-b70d-a7d94ceed56b/stats"
```

```json
{"data":{"emails":{"e1":{"sent":660,"delivered":655,"opened":299,"clicked":76,"unsubscribed":2,"bounced":2,"complaints":1,"queued":0}},"paths":{}}}
```

`emails` is keyed by email step ID; `paths` by A/B split step ID, with the number of runs per path.

## Runs

`GET /automations/{id}/runs`, latest change first. Parameters: `status` (`active`, `completed`, `canceled`, `failed`), `search` (email address contains, needs Subscribers: view), `limit`, `cursor`. `total` comes on the first page only.

```bash
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/automations/477323d4-1ba3-4658-b70d-a7d94ceed56b/runs?limit=2"
```

```json
{"data":[{"id":"dc47e464-5a95-46b4-87e7-10fd672bbd26","subscriber":{"id":"92af241b-ab4a-442c-a087-30236d57ce62","email":"felix.harris@example.org"},"status":"completed","source":"trigger","current_step":"e1","started_at":"2026-10-21T16:51:00.565674Z","finished_at":"2026-10-21T16:51:07.565674Z"},{"id":"10146ae9-3c5c-41ff-9167-8e172e1690f2","subscriber":{"id":"622089f1-ac52-42dc-9cf6-4b7ec9f616d8","email":"becker.samuel@example.com"},"status":"completed","source":"trigger","current_step":"e1","started_at":"2026-10-21T15:00:46.009312Z","finished_at":"2026-10-21T15:00:50.009312Z"}],"meta":{"next_cursor":"ATFli9bJvH7vKdoiO_bfuDPeXu6Ewb_n7VatGLvGHqYhgF6cXmaxAQGUfTzVplQTbrQ0ytcGl-4Z2Yynkn28Z3cxcMQE","prev_cursor":null,"limit":2,"total":660}}
```

`source` tells how the run started: `trigger`, `manual`, `activation`, `readd` or `auto_readd`.

## Activate and pause

`POST /automations/{id}/activate` (no body) activates a workflow **for new subscribers only**; activating for existing subscribers is done in the app. An active workflow stays as it is and the answer is the workflow. A workflow that isn't ready answers `422 validation`, and its `fields` name the place: `automation`, `trigger.<id>` or `step.<id>`.

```bash
curl -X POST "$ECHO_API/automations/477323d4-1ba3-4658-b70d-a7d94ceed56b/activate" -H "Authorization: Bearer $ECHO_TOKEN"
```

`200 OK` with the workflow (same shape as `GET /automations/{id}`).

`POST /automations/{id}/pause` (no body) pauses an active workflow. A paused one stays as it is; a draft is `409 not_active`. Runs of a workflow paused for more than 7 days fail.

```bash
curl -X POST "$ECHO_API/automations/4a640568-5407-49d3-920a-237d5a1927f6/pause" -H "Authorization: Bearer $ECHO_TOKEN"
```

```json
{"data":{"id":"4a640568-5407-49d3-920a-237d5a1927f6","name":"Visszacsábító sorozat","status":"paused","reenter":false,"created_at":"2026-08-31T06:00:00Z","updated_at":"2026-10-05T13:20:00Z","issues":[],"stats":{"active":0,"completed":150,"canceled":0,"failed":0},"triggers":[{"id":"t1","type":"joins_segment","settings":{"segment":"056e2b2a-9214-48e6-b8cf-fa001d8893d4"}}],"steps":[{"id":"e1","type":"email","parent":null,"settings":{"from_email":"hirlevel@news.kertlak.example.com","from_name":"Kertlak Webshop","subject":"Hiányzol nekünk, {$name}"}},{"id":"d1","type":"delay","parent":"e1","settings":{"amount":7,"date":"","field":"","mode":"for","month_day":0,"past":"","past_target":"","time":"","unit":"days","until":"","weekdays":[],"zone":""}},{"id":"e2","type":"email","parent":"d1","settings":{"from_email":"hirlevel@news.kertlak.example.com","from_name":"Kertlak Webshop","subject":"Maradjunk kapcsolatban?"}}]}}
```

## Add subscribers to a workflow

`POST /automations/{id}/subscribers` queues 1 to 100 subscribers (by ID) to enter an **active** workflow from its start.

```bash
curl -X POST "$ECHO_API/automations/{id}/subscribers" \
  -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \
  -d '{"subscribers":["d5f0b4b1-b59d-40eb-b2e0-74857893a055"]}'
```

For an active workflow the answer is `200 OK` with `data.queued` (the number of active subscribers queued) and `data.not_added` (the IDs that are unknown, not active, or were being changed at that moment). A subscriber already in the workflow, or who left it within 24 hours, is skipped when the queue is processed. Entering the workflow sends its emails for real.

The same request to the paused workflow above answers `409`:

```json
{"error":{"code":"not_active","message":"The workflow is not active."}}
```

## Take a subscriber out of a workflow

`DELETE /automations/{id}/subscribers/{subscriber_id}` cancels the subscriber's active run: `204 No Content`. Without an active run the answer is `404 not_found`.
