Skip to navigation

UpdateSequenceV2

View as Markdown

Creates or fully replaces the sequence (workflow) of a campaign, voice steps included.

The v2 version of UpdateSequence, and the write to use for any campaign whose sequence has voice notes. Two things differ from v1:

  1. A MESSAGE node’s payload carries messageVersions instead of messages, so you can read, write and delete voice versions, not only text.

  2. The messageVersions list you send replaces what is stored: any version you leave out is deleted, voice versions included. Read the sequence with GetCampaignSequenceV2 first and send back what you want to keep. Deleting a version never deletes the recording behind it.

The START node is implicit; the root of the request must be your first action node. Every path through the tree must end with an END node.

Allowed statuses: DRAFT, SCHEDULED, PAUSED. Any other status returns 400 CAMPAIGN_STATUS_NOT_EDITABLE. Once leads have entered the campaign, the shape of the sequence must stay the same - only payloads and delays can change - and a request that changes it returns 400 SEQUENCE_UPDATE_INCONSISTENT.

Body Parameters

  • campaignId (long, required): The campaign to update.

  • sequence (PublicSequenceNodeDtoV2, required): Root node of the workflow tree.

PublicSequenceNodeDtoV2 fields

The same as the v1 node (see UpdateSequence), except for the MESSAGE payload.

  • nodeType (string, required): One of CONNECTION_REQUEST, MESSAGE, INMAIL, VIEW_PROFILE, FOLLOW, LIKE_POST, FIND_EMAIL, CHECK_IS_CONNECTION, CHECK_IS_OPEN_PROFILE, SEND_LEAD_TO_INSTANTLY, SEND_LEAD_TO_SMARTLEAD, SEND_LEAD_TO_BISON, END. A node without a nodeType is rejected with 400 FIELD_VALUE_INVALID.

  • unconditionalNode (PublicSequenceNodeDtoV2, required for non-END nodes): The next node to follow unconditionally, or when a branching condition is false.

  • conditionalNode (PublicSequenceNodeDtoV2): The next node when the branching condition is true. Required for CONNECTION_REQUEST, CHECK_IS_CONNECTION, CHECK_IS_OPEN_PROFILE and FIND_EMAIL. On MESSAGE and INMAIL it is the exit taken when the lead replies and must be an END node; if you leave it out, an END node is added for you. Other nodes must not set it.

  • actionDelay (int, optional) / actionDelayUnit (string, optional): The wait before this node runs. Range 0-100; unit HOUR (the default) or DAY. An omitted actionDelay is 0. The unconditional child of CONNECTION_REQUEST, MESSAGE, INMAIL, VIEW_PROFILE, FOLLOW and LIKE_POST, and the conditional child of CONNECTION_REQUEST, need a delay of at least 3 hours and at most 500 days - END nodes included - or the request is rejected with 400 SEQUENCE_NODE_DELAY_INVALID. actionDelay: 3 with actionDelayUnit: "HOUR" is always valid.

  • payload (object, conditional): Node-specific. Required for CONNECTION_REQUEST, MESSAGE, INMAIL, LIKE_POST, SEND_LEAD_TO_INSTANTLY, SEND_LEAD_TO_SMARTLEAD and SEND_LEAD_TO_BISON; omitting it is rejected with 400 SEQUENCE_NODE_PAYLOAD_MISSING. Every payload except MESSAGE is the same as in v1 - see UpdateSequence.

  • externalReference (string, optional): Your own tracking ID for this step. Max 100 characters.

MESSAGE payload

  • messageVersions (PublicMessageVersion[], required): One entry per version of the step; one version is picked at random for each lead. At least one is required. The list replaces what is stored.

  • fallbackMessage (string): Plain text sent instead of a version whose text uses a variable the lead has no value for, and instead of a voice version whose voice note cannot be produced. Required when any version is VOICE, and when a TEXT or DYNAMIC version uses a variable other than {FIRST_NAME}, {LAST_NAME}, {MY_FIRST_NAME} and {MY_LAST_NAME}. It may itself use only those four variables. Max 8000 characters.

PublicMessageVersion fields

  • type (string): TEXT (the default) or VOICE.

  • voiceMode (string): Used only when type is VOICE. DYNAMIC (the default) speaks message as an AI voice note in each sender’s assigned voice; STATIC sends one uploaded recording (staticClipId) as it is.

  • message (string): For TEXT, the message text, max 8000 characters. For a DYNAMIC voice version, the script that is spoken: max 800 characters and at least 3 spoken words (a {VARIABLE} counts as one word). Must be empty on a STATIC version.

  • staticClipId (long): STATIC versions only, and required there: the clipId returned by UploadStaticClip. It must be a recording in your workspace.

  • messageId (string, optional): The version’s id. When you edit a sequence, send back the id GetCampaignSequenceV2 returned: a voice note being generated for a lead is tied to its version’s id, and a version sent without an id gets a new one. Leave it out only for a new version. Ids must be unique within a step, and FALLBACK, MANUAL and unknown (in any letter case) are reserved.

  • durationMs (int, read-only): Length of the version’s recording in milliseconds. Ignored on write.

  • transcript (string, read-only): Transcript of the version’s recording. null is normal and never blocks sending. Ignored on write.

  • staticClipTranscript (string): Read-only on a STATIC version: the server always reports the recording’s own transcript and ignores any value you send. Must be empty on a TEXT or DYNAMIC version.

  • importedTranscript (string): Read-only on a STATIC version: the script a shared step arrived with, shown only while the step has no recording, and ignored on write. Must be empty on a TEXT or DYNAMIC version.

  • needsRecording (bool, read-only): true on a STATIC version that has no recording. Ignored on write.

Sending back what GetCampaignSequenceV2 returned

A body read from GetCampaignSequenceV2 can be sent back unchanged: durationMs, transcript and needsRecording are ignored, and on a STATIC version so are staticClipTranscript and importedTranscript, which the server sets from the version’s recording. Sending them back never causes a 400. Two cases still need a change first:

  • A STATIC version that needs a recording (needsRecording: true) is rejected with 400 SEQUENCE_NODE_PAYLOAD_INVALID:
{
"errorMessage": "Error in one of the nodes in the campaign sequence. A pre-recorded voice clip in a \"Send Message\" action has no recording attached. Upload the clip and use the id the upload returns.",
"errorCode": "SEQUENCE_NODE_PAYLOAD_INVALID"
}

Give it a staticClipId, or replace it with a DYNAMIC version whose message is the script, or remove it (the step must keep at least one version).

  • A version whose staticClipId is not a recording in your workspace is rejected with 400 STATIC_CLIP_NOT_FOUND: Error in one of the nodes in the campaign sequence. A pre-recorded voice clip in a "Send Message" action refers to a recording that does not exist in this workspace. Upload the clip again in this workspace.

Voice rules that return 400

Nothing is saved when any of these is broken:

  • messages on a MESSAGE payload (FIELD_NOT_SUPPORTED). It is the v1 field, and even "messages": [] is refused: 'messages' is not supported on the v2 endpoints. Use 'messageVersions', or call GetCampaignSequence, UpdateSequence or Create for the text-only v1 contract. messages stays valid on CONNECTION_REQUEST and INMAIL payloads.

  • staticClipId, or a non-empty staticClipTranscript or importedTranscript, on a TEXT or DYNAMIC version (FIELD_VALUE_INVALID). The message names the field, for example: 'staticClipTranscript' only applies to a STATIC voice version (type VOICE, voiceMode STATIC); remove it from this version.

  • A non-empty message on a STATIC version (FIELD_VALUE_INVALID): 'message' must be empty on a STATIC voice version: what the lead hears, and its transcript, come from the recording (staticClipId). Use a DYNAMIC voice version to have a script spoken, or a TEXT version to send text.

  • A reserved messageId, or the same messageId twice in one step (FIELD_VALUE_INVALID).

  • A DYNAMIC script with fewer than 3 spoken words (VOICE_SCRIPT_TOO_SHORT), for example: The AI voice script at sequence.conditionalNode.payload.messageVersions[1] has 2 spoken word(s). AI voice scripts need at least 3 words — very short scripts come out garbled. A short script already stored on the campaign and sent back unchanged with its messageId is accepted.

  • A DYNAMIC script over 800 characters, an empty TEXT or DYNAMIC message, a voice step without a valid fallbackMessage, or a step without versions (SEQUENCE_NODE_PAYLOAD_INVALID).

Errors

Every { "errorMessage": "..." } error body carries an errorCode; branch on the code, not on the message. Request-validation 400s (for example actionDelay outside 0-100, or a nodeType name that does not exist) use the standard problem-details shape instead.

  • 400 CAMPAIGN_STATUS_NOT_EDITABLE, SEQUENCE_UPDATE_INCONSISTENT, SEQUENCE_INVALID (the tree’s structure is not valid), SEQUENCE_NODE_PAYLOAD_MISSING, SEQUENCE_NODE_PAYLOAD_INVALID, SEQUENCE_NODE_DELAY_INVALID, FIELD_NOT_SUPPORTED, FIELD_VALUE_INVALID, REQUIRED_FIELD_MISSING (a SEND_LEAD_TO_* payload is missing a required field), VOICE_SCRIPT_TOO_SHORT, STATIC_CLIP_NOT_FOUND, and for SEND_LEAD_TO_* nodes INTEGRATION_NOT_CONFIGURED, INTEGRATION_CREDENTIALS_INVALID and INTEGRATION_REQUEST_FAILED.
  • 403 NO_ACTIVE_SUBSCRIPTION: the workspace has no active subscription.
  • 404 CAMPAIGN_NOT_FOUND, CAMPAIGN_API_NOT_ENABLED (the campaign API is not enabled for your account), and INTEGRATION_RESOURCE_NOT_FOUND (the Instantly, Smartlead or EmailBison campaign or list of a SEND_LEAD_TO_* node was not found).

Headers

X-API-KEYstringOptional

API key header using this scheme. Example: “X-API-KEY: {API_KEY}”

Request

This endpoint expects an object.
campaignIdlongRequired
The campaign to update.
sequenceobjectRequired

One node of a campaign sequence on the v2 endpoints (GetCampaignSequenceV2, UpdateSequenceV2, CreateV2). Nodes form a tree through conditionalNode and unconditionalNode. The START node is implicit - the root is your first action node - and every path ends with an END node.

Errors

400
Update Sequence V2campaigns Request Bad Request Error
403
Update Sequence V2campaigns Request Forbidden Error
404
Update Sequence V2campaigns Request Not Found Error