Automations
A short sequence that runs itself — a reminder the day before, a follow-up the day after, and a stop as soon as somebody replies.
| Method | Path | Does |
|---|---|---|
GET | /v1/automations | List them with their steps |
POST | /v1/automations | Create, with every step, paused |
PATCH | /v1/automations/{id} | Activate, pause or archive |
POST | /v1/automations/{id}/enter | Put one contact into it |
Creating one
POST /v1/automations
{
"name": "Appointment reminders",
"trigger_type": "contact_created",
"steps": [
{ "type": "send", "config": { "body": "Booked. See you soon." } },
{ "type": "wait", "config": { "minutes": 1440 } },
{ "type": "stop_if", "config": { "condition": "replied" } },
{ "type": "send", "config": { "body": "See you tomorrow." } }
]
}The whole sequence goes in one request. Not step by step over several: a half-built sequence that was somehow active would message people through an incomplete flow, and there is no undo for a sent SMS.
Every automation is created paused, whatever you send in status.One that started the moment it was saved would have messaged people before anybody had read it back.
Triggers
| Trigger | Fires when |
|---|---|
contact_created | A contact is added, however it was added |
list_joined | A contact joins a list |
inbound_keyword | Somebody texts a keyword you chose |
api | Only when you call /enter |
Steps
| Type | Config | Notes |
|---|---|---|
send | body | Sent as marketing, so consent and quiet hours both apply. |
wait | minutes | 1 to 43,200 — thirty days. Anchored the first time the step is reached. |
stop_if | condition | replied or opted_out. Ends the run for that contact. |
Up to twenty steps. The list of types is short on purpose: a step engine that can branch arbitrarily is a programming language with no debugger, built by somebody who did not think they were writing one.
stop_if is the one that matters
It checks before every remaining message, not only when the step is reached. Somebody who replies on day two of a five-day sequence hears nothing more from it — which is the difference between a reminder and a nuisance.
A stop_if without a condition is refused. It would be accepted, stored, and then silently continue, on the one step whose entire job is to stop messaging someone.
Activating
PATCH /v1/automations/{id} { "status": "active" }An automation with no steps cannot be activated — an empty active automation is almost always a half-finished one.
Pausing does less than you think
New contacts will not enter. Contacts already part-way through will continue.The API says this in the response, because the natural assumption is the opposite. To stop somebody mid-sequence, suppress them or let a stop_if catch them.
Entering a contact
POST /v1/automations/{id}/enter { "phone_number": "+447400123456" }{ "entered": true, "run_id": "01j8xk…" }A contact who does not enter is told why, rather than simply refused:
reason | Means |
|---|---|
automation_not_active | It is paused or archived. |
contact_opted_out | They have opted out. They will not be entered. |
already_entered | They have been through it, and re-entry is off. |
Every one of those is deliberate, so answering "not entered" without saying which would send you hunting for a bug that is not there.
Opt-outs are re-checked, not assumed
Consent is checked before every send in a run, not once at entry. A five-day sequence that checked only at the start would keep messaging somebody for four days after they asked it to stop.
Timing
Runs advance on a sweep every minute. A reminder an hour late is a reminder nobody needed, so that interval is the resolution of the feature rather than a tuning choice.