Sequences
Update Sequence
Update sequence identity, settings, structure, or existing nodes
PUT
Update Sequence
Update Sequence
Updates sequence sending identity, metadata, auto-stop behavior, branch logic, graph topology, linear steps, and email content. You can insert new linear steps withinsertSteps, restructure existing nodes with graphEdit, or target
any existing node with nodeUpdates.
Request
string
required
Sequence ID.
string
Updated sequence name.
string
Updated dashboard description.
string[]
Replacement dashboard label names. Missing labels are created.
boolean
Whether recipients can cancel this sequence from email preferences.
string
Atomically replace the current trigger with
contact_added, tag_added,
segment_entered, event_received, inbound_webhook, inactivity, or
frequency. Include the matching trigger fields (listId, listIds,
listScope, tagName, tagNames, segmentId, eventName,
propertyFilters, integrationSlug, integrationEventKey,
customIntegration, inactiveDays, inactivityBaseline, minCount, or
timeWindowDays) in the same request. Active sequences require
confirmLiveChange: true. Trigger replacement cannot be combined with node,
content, or structural graph changes.string[]
Several list IDs for a replacement
contact_added trigger. A contact joining
any of them enters the sequence. Cannot be combined with listScope. Up
to 25 lists.string[]
Several tag names for a replacement
tag_added trigger. Receiving any of
them enters the contact into the sequence. Up to 25 tags.string
default:"any_contact"
For a replacement
contact_added trigger with no list at all. any_contact
enrolls every contact that is added, even one that joins no list; any_list
waits for a list membership. Cannot be combined with listId or listIds.string
From address for every sequence email. Its domain must be configured and
verified. Mutually exclusive with
senderProfileId.string
Display name recipients see, e.g.
Brennon at TradeTally. Selects the sender
identity of that name on fromEmail, creating it when the address has no
identity by that name; the mailbox’s other display names, and everything
pinned to them, are untouched. Requires fromEmail; omit it when you send
senderProfileId, which already carries its own display name.string
Existing sender profile ID. It already supplies both the From address and the
display name, so send it on its own and omit
fromEmail and fromName. To
keep this profile under a different display name, set fromName on the email
steps instead, where it is a per-step override.string
Reply-To address for every sequence email. Mutually exclusive with
replyProfileId.string
Display name for the Reply-To address. Requires
replyTo; omit it when you
send replyProfileId, which already carries its own display name. An address
carries one Reply-To name company-wide: if replyTo already has a saved
profile under a different name, that saved name is kept and the response
warnings array says so.string
Existing reply profile ID. It already supplies both the Reply-To address and
the display name, so send it on its own and omit
replyTo and replyToName.string
Updated re-entry mode:
unlimited, one_time, or matching_field.
matching_field is only valid for event-based sequence triggers.string
Dot-path event property used by
matching_field. Set to null or omit it to
use the built-in defaults.{"enrollmentMode":"matching_field","enrollmentFieldPath":"order.id"} to allow one active run per order while blocking duplicate active runs for the same subscriber and order.
boolean
Set to
true to stop new enrollments for an active sequence while current
recipients continue. Set to false to reopen new enrollments.object | null
Updated local-time sending window for every email step. Set to
null to
remove the sending restriction. When set, email steps that become due outside
the window wait until the next allowed local time.string[] | null
Email addresses that receive a blind copy of every email this sequence sends,
such as a customer support inbox (max 10). BCC recipients are invisible to the
subscriber. Set to
null to remove them.object
Updated auto-stop condition, re-evaluated before every step including the
first one. Use
has_tag, does_not_have_tag, added_to_list,
removed_from_list, entered_segment, field_changed, event_received, or
none. does_not_have_tag and removed_from_list stop the run whenever the
subscriber lacks that tag or list membership, so they act as a required-tag or
required-list allowlist and cancel everyone else before any step sends.
Guarded-out contacts still enroll and are then cancelled at the trigger node,
so they appear as cancellations there rather than in the active or waiting
enrollment counts. Clearing the guard does not retry them: they only receive
the sequence if the trigger fires for them again, and on the one_time
enrollment mode not even then. event_received only counts events received
after enrollment; the enrolling event and earlier history do not satisfy the
stop. Use event_property_filter with propertyFilters to require every
literal-value filter to match a later stop event, or event_property rules to
compare the stop event with the enrolling event. field_changed can use a
typed field_value comparison. Tag/list defaults are returned with value: null and an entry_audience match config; that public shape can be sent back
unchanged to preserve the per-enrollment guard.object
Insert an if/else branch after an existing node. Provide
afterNodeId and a
branches array. Each conditional path can create steps, route directly to
an existing targetNodeId, or run steps and then reach that target. The else
path uses elseSteps and/or elseTargetNodeId. Use the completion node ID
returned by the sequence GET endpoint to end one path immediately. Empty
branch paths are rejected unless you set allowEmptyPaths: true. Branch
conditionType values include has_tag, does_not_have_tag, in_list,
in_segment, event_received, link_clicked, and field comparisons. For
has_tag and does_not_have_tag, provide tagId or tagName. For
event_received and link_clicked, set activityScope to this_sequence,
previous_email, or ever; omitting it checks ever. Path steps use the
same shape as insertSteps, so an action inside a path carries its fields in
config - for example { "nodeType": "action_add_tag", "config": { "tagName": "newsletter-confirmed" } }.Set splitMode to random to make the branch a weighted A/B split instead of
an if/else. Each subscriber is then assigned a path by percentage when they
reach the node, so no subscriber attribute is evaluated. A random split
requires randomPercentages with one non-negative value per entry in
branches, in the same order, summing to 100. Its paths must omit
conditionType and condition-specific fields, and it has no else path, so elseSteps and
elseTargetNodeId are rejected. To test two versions of a single existing
email step and have a winner picked automatically, create an A/B test on that
step instead.object
Insert one or more new linear steps into the sequence. Provide
afterNodeId
to insert after a specific node from GET /api/v1/sequences/{sequenceId}. If
afterNodeId is omitted, the steps are appended only when the sequence has
exactly one linear tail. Linear insertion supports every non-trigger addable
step type that does not require companion records: email, SMS, delay, tag/list
actions, attribute updates, discounts, conditions, wait-for-event steps, and
webhooks. SMS steps use type: "sms" with a plain-text text field (optional
label, ineligibleAction, imageUrls); generate copy with the Generate
SMS endpoint. Email and delay steps can use
fixed delay/delayMs waits, dynamic waitUntil date-field waits, or
waitUntilWeekday waits that hold the step until the next occurrence of a
weekday inside a local-time window (for example { "day": "sunday", "startTime": "09:00", "endTime": "12:00", "timezone": "America/Los_Angeles" } - contacts already inside the window continue
immediately). Use
nodeType: "logic_wait_for_event" with a config containing eventName,
timeoutDays (1-365), timeoutAction (continue or exit), and an optional
label to insert an event gate. Event receipt and a continuing timeout both
use the gate’s single next path; timeoutAction: "exit" completes the
enrollment on timeout. Tag, list, subscriber-update, condition, and webhook
node types carry their fields in config: action_add_tag and
action_remove_tag take tagName, or tagId when you have the real tag ID
(a missing tag definition is created for you), action_add_to_list and
action_remove_from_list take listId, action_update_attributes takes the
Update Subscriber fields, logic_condition takes conditionType plus that
condition’s resource field, and action_webhook takes an HTTPS url with
optional method (GET, POST, PUT, PATCH, DELETE), headers, a
JSON body template (valid JSON as written, with merge tags inside quoted
values), a resultKey that saves the response so later email
steps can use {{webhooks.KEY.data.field}} merge tags, and onError
(continue, exit, or fail). Webhook url, headers, and body support
merge tags resolved when the step runs. action_ai takes a merge-tag
prompt (max 8000 chars), a required resultKey, outputFields (1-10
entries of { key, description, maxLength, fallback } - fallback is used
when generation fails so emails still send; combined field limits must fit
the step’s 2000-token response budget), optional includeTags,
includeEventProperties, includeRecentEvents (with recentEventLimit,
1-50, default 10), and includeAttributes context selectors, and
onError (default continue); later steps read the output with
{{ai.KEY.field}} merge tags. SMS, discount, and delay steps keep using their
step-level fields described above. Use branch for if/else paths. Provide
only one of branch, insertSteps, or graphEdit in a request. Inserted
email steps inherit the effective sender identity (sender profile, display
name, and Reply-To) of the nearest sequence email. Across a branch merge, only
identity fields shared by every incoming path are inherited; conflicting
fields use the sequence or company defaults. Set senderProfileId/fromEmail
or replyProfileId/replyTo on a step to override the inherited identity.object
Restructure existing sequence nodes. Set
action to move_node,
duplicate_node, delete_node, or replace_edges, and include the
expectedRevision returned as graphRevision by the latest
GET /api/v1/sequences/{sequenceId} response. A stale revision is rejected.move_node and duplicate_node require nodeId plus exactly one of
afterNodeId or beforeNodeId. beforeNodeId funnels every incoming path
through the moved or copied node, so it can relocate an A/B test below paths
that converge at a shared continuation. Duplicated email and A/B test steps
receive independent content records; A/B metrics and winner state reset.delete_node automatically reconnects a linear step. To delete a split node,
also provide the complete replacement edges. replace_edges always requires
the complete normalized topology returned by the sequence GET endpoint and
supports atomic path reconnects or multi-node reorders. Deleting an A/B test
step also removes its test, variants, and variant localizations unless the test
is currently in progress or replacement variants are still being generated.Preserve condition.branchId on every edge leaving a branch node. Graph edits
reject cycles, disconnected nodes, invalid branch lanes, and changes that
remove the trigger/end path.Deleting an otherwise-deletable step that currently holds active or waiting
recipients moves those recipients to the step’s next step in the committed
topology - including a rerouted path supplied via replacement edges - and
processes them immediately; the response reports the count as
migratedRecipientCount (or completedRecipientCount when the deleted step has
no continuation). Trigger and end steps remain protected, as do A/B test steps
while variants are generating or a test is active. Recipient migration is also
refused when recipients could continue to more than one surviving step (for
example a merge step whose incoming paths are rerouted to different steps),
because the platform will not pick a path for them.boolean
Required when inserting linear steps, branches, or applying
graphEdit to an
active sequence. Set it to true only after confirming the live-flow impact
for current and future recipients. Content-only email edits do not require
this flag.array
Atomic, type-aware patches for existing nodes. Each item requires
nodeId
and a non-empty changes object. Pass the updatedAt returned for that node
by GET /api/v1/sequences/{sequenceId} as expectedUpdatedAt to prevent a
stale write. A node may appear only once, and nodeUpdates cannot be combined
with legacy email/SMS/subscriber step arrays or structural edits.Each node read also includes updateHints, which lists that node type’s
editable fields, managed fields, special restrictions, and the exact
expectedUpdatedAt token to return.logic_delay accepts exactly one of delay (days, hours, minutes),
delayMs, waitUntil, or waitUntilWeekday (day/days, startTime,
optional endTime, timezone). action_email accepts name/label, subject, preview
text, HTML or blocks, emailPreset (branded or minimal), emailTheme,
transactional mode, and per-step sender/reply identity. Setting emailPreset transforms that linked
email’s native blocks using the same Style > Format behavior as the
dashboard without changing the company default. Native block emails may include
supported custom HTML blocks. An email stored entirely as one standalone raw
HTML block does not support emailPreset, and emailPreset cannot be combined
with html or htmlContent. A blocks patch that omits emailPreset never
changes the step’s format - see the emails parameter below. A format switch is
not a lossless toggle: minimal deletes standalone logo blocks, so switching
back to branded generates a new logo block with a new id and the company
name as its alt text. Send the authored logo block in blocks alongside the
branded update to keep it. Both directions are reported in the response
warnings.emailTheme restyles that one linked email and leaves the company default and
every other email untouched. It is a partial patch merged into the email’s
current theme, so {"colors": {"background": "#ffffff"}} repaints the
outer canvas and keeps the email’s fonts, spacing, and other colors. Use
colors.content for the inner content card and colors.surface for nested
cards and tinted tiles. A step with
no override merges into the company theme rather than the platform preset.
Send null to drop the override so the step follows the company theme again.
Supported sections are presetId, buttonStyle, colors, typography, and
layout; colors must be 6-digit hex, and numeric values are clamped to their
supported ranges. Use PATCH /api/v1/companies/{companyId} to move the
account-wide default instead.
SMS and every other stored node type accept their type-specific editable
config fields. Omitted fields are preserved. Managed linked-resource IDs,
node-type conversion, and branch path IDs/count are rejected; use graphEdit
for topology changes. Webhook header patches merge with existing headers, and
redacted values from the read response cannot be written back.boolean
Required with
nodeUpdates when the sequence is active. Set it to true only
after confirming the behavior change. Existing waiting recipients retain their
already-calculated scheduledFor; a new delay applies when recipients reach
that node after the update.array
Existing email step updates. Provide
emails or steps, not both. Items
without nodeId or emailId are matched by existing step order and do not
create new steps. html and htmlContent are preserved as one raw HTML
block; provide blocks for native Sequenzy block content. Each item can also
set emailPreset to minimal or branded when working with native blocks,
including emails that contain supported custom HTML blocks. Emails stored
entirely as one standalone raw HTML block do not support format changes. Each
item can also set emailTheme to override that one email’s theme, with the
same partial-patch and null-clears rules described under nodeUpdates. Each
item can also set per-step sender identity: senderProfileId or fromEmail
(+ optional fromName) for the From identity, and replyProfileId or
replyTo (+ optional replyToName) for the Reply-To. A fromName on its own
only changes the visible display name. Per-step identity overrides the
sequence-level sender for that step. Email items can also set
isTransactional, ccEmails, and bccEmails to match the dashboard
delivery settings, and attachments ([{ filename, path }]) to configure
URL-backed file attachments fetched at send time. For event-triggered
sequences, path may use {{event.file_url}} and filename may also use
event merge tags; values come from the event that enrolled each subscriber
(max 10, 7MB total per email; an empty array removes them).blocks are validated against the block schema, exactly as on create. A block
that is structurally invalid is rejected with 400 naming the step, the block
index, and the field, rather than stored - a stored block the renderer cannot
render fails every future send of that step. Fields that parse but will not
render as their name suggests come back in an advisory warnings array on the
200. Email steps created through branch or insertSteps are checked the
same way; their warning paths are rooted at the path label, for example
If.steps[0].blocks[0] and Inserted.steps[0].blocks[0].Replacing blocks keeps that step’s existing Style > Format rather than
the company default. A step that already had a logo or a footer gets them back
even when you omit them, and every block added that way is named in the
warnings array, so you can see what landed without re-reading the sequence.
Send emailPreset to change the format instead. A step stored as one
standalone raw HTML block has no format, so replacing it with another
standalone raw HTML block stores it exactly as sent and nothing is added.
Replacing that markup with native blocks is a conversion rather than a markup
edit, so the new blocks do get a footer.array
Alias for
emails. Use insertSteps to create new steps.array
Content updates for existing SMS steps, targeted by
nodeId (an action_sms
node from GET /api/v1/sequences/{sequenceId}). Each entry can set text (or
blocks), imageUrls (with text), label, and ineligibleAction (skip
or exit). SMS content edits are content-only and do not require
confirmStructuralChange. Use insertSteps to create new SMS steps.array
Full config replacements for existing Update Subscriber steps, targeted by
an
action_update_attributes node ID from
GET /api/v1/sequences/{sequenceId}. Values can use standalone event merge
tags such as {{event.plan}}; number and boolean tags are coerced after
resolution.node_end: