Sequences

A sequence is an automated journey. A contact enters on a trigger, then walks a graph of steps at their own pace — and the graph is versioned, so a journey already under way never changes.

The four things you manipulate

ObjectWhat it is
SequenceThe journey's identity: a name, a status (active / paused), and a pointer to the version currently running
VersionA snapshot of the journey, with its trigger. A draft is editable; a published one never changes again
NodeOne step of a version: send_email, wait, add_tag, remove_tag, end_sequence, webhook
EdgeA wire from one node to the next. Adding a node wires it for you; edges exist so you can rewire
Two consequences run through everything below:
  • You never edit a running journey. Editing means opening a draft version, changing it, and publishing it. Contacts already walking the old version finish on the old version.
  • The trigger lives on the version, not on the sequence. You set it when you create the sequence — that call creates version 1 with it — and you change it the way you change anything else: on a draft, with PATCH on the version, then publish.
There is no endpoint to enrol a contact directly. Contacts enter a sequence through its trigger, and only through it: entering a list (list_joined) or receiving a tag (tag_added). Use the Audience API to add a contact to the list, or to tag it, and enrolment follows.

Status codes that matter here

Everything on the API reference applies. Three cases come up far more often here:
StatusWhen
201A sequence, a version, a node or an edge was created
400The journey refuses what you asked — an invalid graph at publish time, a write on a published version, a plan limit
404Unknown id, an id belonging to another organization, or an id belonging to another version
That last one is worth reading twice: a versionId that is not a version of the sequenceId in the URL answers 404, and so does a nodeId that is not in that version. Ids are only ever read inside the path that leads to them.

What a refused publication means

Every defect answers 400, names itself, and names the nodes involved — all of them at once, so you fix in one pass instead of publishing again to discover the next one.
DefectWhat it meansHow to fix it
emptyThe version has no node at allAdd at least one node
no entryEvery node has something pointing at it — there is no way inRemove the wire that closes the loop at the top
multiple entriesTwo nodes have nothing pointing at themWire one behind the other; a journey has one door
cycleThe wires come back on themselves — a contact would loop foreverRemove the wire that goes backwards
orphanA node is unreachable from the entryWire it in, or delete it
dangling branchA branch leads nowhereWire its end, or drop the branch
ambiguous branchA node has two outgoing wires with no way to chooseKeep one wire
edge out of graphA wire points at a node of another versionDelete that wire and rewire inside this version
empty sendA send_email node has no subject or no contentPATCH the node with a subject and HTML
incomplete actionAn add_tag / remove_tag node has no tagPATCH the node with a tagId
end with successorAn end_sequence node has a node after itDelete what follows: nothing runs after the end
invalid webhookA webhook node has no URL, or one the policy refusesPATCH the node with an https:// public URL
A version that is not a draft answers 400 too: a published version is a snapshot, republishing it in place would rewrite what contacts are walking. Use rollback instead.

Edges

Adding a node wires it for you. These endpoints exist for the shapes an append cannot make — and for undoing one.

Writing on a published version

Every write above — adding, editing, deleting, moving a node, wiring, unwiring, changing the trigger — answers 400 if the version is not a draft. That is not a permission problem, and retrying will not help: published versions are snapshots that contacts are executing. The way through is always the same three calls: open a draft, edit it, publish it.

An onboarding sequence, end to end

1

Create the sequence on its trigger

bash
SEQUENCE_ID=$(curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"name":"Onboarding","triggerType":"list_joined","triggerTargetId":"'$LIST_ID'"}' \
  "https://www.agentsmail.io/api/v1/sequences" | jq -r '.data.id')
It is paused, and version 1 already exists as a draft.
2

Find the draft to edit

bash
VERSION_ID=$(curl -s -H "x-api-key: $AGENTMAIL_API_KEY" \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions" \
  | jq -r '.data[] | select(.status=="draft") | .id')
3

Add the steps, in order

bash
curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"type":"send_email","templateId":"'$TEMPLATE_ID'"}' \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/nodes"

curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"type":"wait","waitHours":48}' \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/nodes"

curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"type":"add_tag","tagId":"'$TAG_ID'"}' \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/nodes"
Each one is appended behind the previous, and wired for you. Templates come from the Content & Send API, tags from the Audience API.
4

Read the graph back

bash
curl -s -H "x-api-key: $AGENTMAIL_API_KEY" \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/nodes" \
  | jq '.data[] | {id, type, subject, waitHours, tagId}'
An empty subject on a send_email is what will be refused at publication. Fix it with PATCH on the node.
5

Publish

bash
curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions/$VERSION_ID/publish"
A 400 here names the defect and the nodes: fix them and publish again. This loop costs nothing — nothing has been enrolled yet.
6

Activate

bash
curl -s -X PATCH -H "x-api-key: $AGENTMAIL_API_KEY" -H "content-type: application/json" \
  -d '{"status":"active"}' \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID"
From here, every contact entering the list walks the journey. Publishing without activating enrols nobody; activating without publishing answers 400.
7

Change something later

bash
NEW_VERSION_ID=$(curl -s -X POST -H "x-api-key: $AGENTMAIL_API_KEY" \
  "https://www.agentsmail.io/api/v1/sequences/$SEQUENCE_ID/versions" | jq -r '.data.id')
Edit that draft, publish it, and the sequence switches over. Contacts already walking the previous version finish on it — they never change journey mid-way.