> ## Documentation Index
> Fetch the complete documentation index at: https://bavlio.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Save a campaign's sequence

> Saves the steps as the campaign's next sequence version and returns it, with warnings for template problems that did not stop the save. Leads already in the sequence carry on from the step with the same id, so keep the ids of steps you keep. Invite notes and the first message template on each path may not contain a link or {@booking_link}.

## OpenAPI

```json
{
  "openapi": "3.2.0",
  "info": {
    "title": "Bavlio API",
    "version": "1.0.0"
  },
  "paths": {
    "/campaigns/{id}/sequence": {
      "put": {
        "tags": [
          "Sequences"
        ],
        "operationId": "sequences.saveCampaignSequence",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "schema": {
              "type": "string",
              "description": "Campaign id."
            },
            "required": true
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "campaign_id": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Version number; each save adds one."
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Union_"
                      },
                      "description": "The steps, in the order they run."
                    },
                    "stats": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "reached": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "allOf": [
                              {
                                "minimum": 0
                              }
                            ]
                          },
                          "converted": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "allOf": [
                              {
                                "minimum": 0
                              }
                            ]
                          }
                        },
                        "required": [
                          "reached",
                          "converted"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Per step id: leads that reached the step (reached) and those who accepted, replied or booked a meeting at it (converted)."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "step_id": {
                            "type": "string",
                            "description": "The step whose text the warning is about."
                          },
                          "field": {
                            "type": "string",
                            "enum": [
                              "note",
                              "subject",
                              "body"
                            ],
                            "description": "Which text of the step: note, subject or body."
                          },
                          "message": {
                            "type": "string",
                            "description": "What to change, in plain words."
                          }
                        },
                        "required": [
                          "step_id",
                          "field",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Template problems that did not stop the save, such as a custom field no upload to the campaign has; empty when there are none."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "When the version was saved (ISO 8601)."
                    }
                  },
                  "required": [
                    "campaign_id",
                    "version",
                    "steps",
                    "stats",
                    "warnings",
                    "created_at"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "SequenceInvalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceInvalidEncoded"
                }
              }
            }
          },
          "401": {
            "description": "AuthMissing | AuthInvalid",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/AuthMissingEncoded"
                    },
                    {
                      "$ref": "#/components/schemas/AuthInvalidEncoded"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "WorkspaceNotFound | CampaignNotFound",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/WorkspaceNotFoundEncoded"
                    },
                    {
                      "$ref": "#/components/schemas/CampaignNotFoundEncoded"
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "CampaignArchived",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignArchivedEncoded"
                }
              }
            }
          }
        },
        "description": "Saves the steps as the campaign's next sequence version and returns it, with warnings for template problems that did not stop the save. Leads already in the sequence carry on from the step with the same id, so keep the ids of steps you keep. Invite notes and the first message template on each path may not contain a link or {@booking_link}.",
        "summary": "Save a campaign's sequence",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "steps": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Union_"
                    },
                    "description": "The steps, in the order they run."
                  }
                },
                "required": [
                  "steps"
                ],
                "additionalProperties": false
              }
            }
          },
          "required": true
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AuthInvalidEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "AuthInvalid"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              401
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "auth_invalid"
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "Bearer credential rejected"
            ]
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "AuthMissingEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "AuthMissing"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              401
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "auth_missing"
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "Bearer credential required"
            ]
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "WorkspaceNotFoundEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "WorkspaceNotFound"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              404
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "workspace_not_found"
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "No such workspace for this account: save a company profile or pick a workspace you belong to"
            ]
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "SequenceInvalidEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "SequenceInvalid"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              400
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "sequence_invalid"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "CampaignArchivedEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "CampaignArchived"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              409
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "campaign_archived"
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "The campaign is archived and takes no more changes"
            ]
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "CampaignNotFoundEncoded": {
        "type": "object",
        "properties": {
          "_tag": {
            "type": "string",
            "enum": [
              "CampaignNotFound"
            ]
          },
          "statusCode": {
            "type": "number",
            "enum": [
              404
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "campaign_not_found"
            ]
          },
          "message": {
            "type": "string",
            "enum": [
              "No campaign with this id belongs to the workspace"
            ]
          }
        },
        "required": [
          "_tag",
          "statusCode",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "Union_": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "visit_profile"
                ]
              }
            },
            "required": [
              "id",
              "kind"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "like_post"
                ]
              }
            },
            "required": [
              "id",
              "kind"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "invite"
                ]
              },
              "note": {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Invite note; no links or {@booking_link}. Braces mark what is filled in per lead. Inside braces, an @ names a lead's value: @first_name, @company, @title, @moment, @booking_link, @lead_id, or a custom field from a file uploaded to the campaign, like @city. Options split by | are tried in order and the first whose @ values the lead has is used, like {@first_name|there} or {@age year olds|Gen Z}; an option without an @ is plain text. Braces with a custom field end with an option without one, because leads Bavlio finds have no custom fields. Braces without an @ hold choices, one picked per lead, like {Hi|Hello|Hey}. Everything else is sent as written, an @ outside braces included."
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "kind",
              "note"
            ],
            "additionalProperties": false,
            "description": "Send a LinkedIn invite, with the note or, when null, without."
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "message"
                ]
              },
              "mode": {
                "type": "string",
                "enum": [
                  "template"
                ]
              },
              "template": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1900,
                    "description": "LinkedIn message. Braces mark what is filled in per lead. Inside braces, an @ names a lead's value: @first_name, @company, @title, @moment, @booking_link, @lead_id, or a custom field from a file uploaded to the campaign, like @city. Options split by | are tried in order and the first whose @ values the lead has is used, like {@first_name|there} or {@age year olds|Gen Z}; an option without an @ is plain text. Braces with a custom field end with an option without one, because leads Bavlio finds have no custom fields. Braces without an @ hold choices, one picked per lead, like {Hi|Hello|Hey}. Everything else is sent as written, an @ outside braces included."
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "id",
              "kind",
              "mode",
              "template"
            ],
            "additionalProperties": false,
            "description": "Send a LinkedIn message filled in from the template."
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "message"
                ]
              },
              "mode": {
                "type": "string",
                "enum": [
                  "ai"
                ]
              },
              "ai": {
                "type": "object",
                "properties": {
                  "brief": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000,
                    "description": "Instructions the AI writes the text from, for each lead."
                  }
                },
                "required": [
                  "brief"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "id",
              "kind",
              "mode",
              "ai"
            ],
            "additionalProperties": false,
            "description": "Send a LinkedIn message the AI writes from the brief."
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "email"
                ]
              },
              "subject": {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150,
                    "description": "Email subject. Braces mark what is filled in per lead. Inside braces, an @ names a lead's value: @first_name, @company, @title, @moment, @booking_link, @lead_id, or a custom field from a file uploaded to the campaign, like @city. Options split by | are tried in order and the first whose @ values the lead has is used, like {@first_name|there} or {@age year olds|Gen Z}; an option without an @ is plain text. Braces with a custom field end with an option without one, because leads Bavlio finds have no custom fields. Braces without an @ hold choices, one picked per lead, like {Hi|Hello|Hey}. Everything else is sent as written, an @ outside braces included."
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Subject; null replies in the thread of the lead's earlier email."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "template"
                ]
              },
              "template": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 5000,
                    "description": "Email body. Braces mark what is filled in per lead. Inside braces, an @ names a lead's value: @first_name, @company, @title, @moment, @booking_link, @lead_id, or a custom field from a file uploaded to the campaign, like @city. Options split by | are tried in order and the first whose @ values the lead has is used, like {@first_name|there} or {@age year olds|Gen Z}; an option without an @ is plain text. Braces with a custom field end with an option without one, because leads Bavlio finds have no custom fields. Braces without an @ hold choices, one picked per lead, like {Hi|Hello|Hey}. Everything else is sent as written, an @ outside braces included."
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "id",
              "kind",
              "subject",
              "mode",
              "template"
            ],
            "additionalProperties": false,
            "description": "Send an email filled in from the template."
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "email"
                ]
              },
              "subject": {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 150,
                    "description": "Email subject. Braces mark what is filled in per lead. Inside braces, an @ names a lead's value: @first_name, @company, @title, @moment, @booking_link, @lead_id, or a custom field from a file uploaded to the campaign, like @city. Options split by | are tried in order and the first whose @ values the lead has is used, like {@first_name|there} or {@age year olds|Gen Z}; an option without an @ is plain text. Braces with a custom field end with an option without one, because leads Bavlio finds have no custom fields. Braces without an @ hold choices, one picked per lead, like {Hi|Hello|Hey}. Everything else is sent as written, an @ outside braces included."
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Subject; null replies in the thread of the lead's earlier email."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "ai"
                ]
              },
              "ai": {
                "type": "object",
                "properties": {
                  "brief": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000,
                    "description": "Instructions the AI writes the text from, for each lead."
                  }
                },
                "required": [
                  "brief"
                ],
                "additionalProperties": false
              }
            },
            "required": [
              "id",
              "kind",
              "subject",
              "mode",
              "ai"
            ],
            "additionalProperties": false,
            "description": "Send an email the AI writes from the brief."
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "wait"
                ]
              },
              "days": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Days before the next step.",
                "allOf": [
                  {
                    "minimum": 1,
                    "maximum": 30
                  }
                ]
              }
            },
            "required": [
              "id",
              "kind",
              "days"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "Unique step id; leads stay on a step whose id a new version keeps."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "branch"
                ]
              },
              "condition": {
                "type": "string",
                "enum": [
                  "invite_accepted",
                  "replied"
                ]
              },
              "within_days": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Days to wait for the condition before taking no.",
                "allOf": [
                  {
                    "minimum": 1,
                    "maximum": 30
                  }
                ]
              },
              "yes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Union_"
                },
                "description": "Steps once the condition is met."
              },
              "no": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Union_"
                },
                "description": "Steps when it is not met in time."
              }
            },
            "required": [
              "id",
              "kind",
              "condition",
              "within_days",
              "yes",
              "no"
            ],
            "additionalProperties": false,
            "description": "Wait for the condition, then take the yes or no steps."
          }
        ],
        "description": "One step. visit_profile visits the lead's LinkedIn profile, like_post likes their latest post, wait pauses for the days given."
      }
    },
    "securitySchemes": {
      "bearer": {
        "description": "Send `Authorization: Bearer <token>`. The token is an API key, which starts with `bav_` and comes from creating an API key or starting a registration, or the access token of a Bavlio sign-in.",
        "type": "http",
        "scheme": "Bearer"
      }
    }
  },
  "security": [],
  "tags": [
    {
      "name": "Registration",
      "description": "Open a Bavlio account without signing in. Starting a registration returns an API key for a new ephemeral account, which becomes permanent once its email address is verified."
    },
    {
      "name": "Authentication",
      "description": "Identify the calling account, finish a registration and manage the account's API keys."
    },
    {
      "name": "Account",
      "description": "The account behind your sign-in, and deleting it."
    },
    {
      "name": "Workspaces",
      "description": "A workspace holds the company profile, outreach schedule, team, campaigns and billing Bavlio works with. Calls that act in a workspace use the one whose id is in the bavlio-workspace header, or the account's default workspace when the header is absent."
    },
    {
      "name": "Teams",
      "description": "Manage who belongs to a workspace: its members, their roles and the invitations to join it. Each workspace's plan sets how many team seats it has."
    },
    {
      "name": "Campaigns",
      "description": "A campaign finds leads that match an ideal customer profile (ICP) and buying signals, and reaches out to them through its sequence of LinkedIn and email steps."
    },
    {
      "name": "Lead imports",
      "description": "Bring your own leads: preview a CSV, confirm which column holds what, then import it into a campaign, where the leads go through the same sequence as the ones Bavlio finds."
    },
    {
      "name": "Sequences",
      "description": "A campaign's sequence is the steps Bavlio runs for each lead: profile visits, likes, invites, LinkedIn messages, emails, waits and conditions. Every message and email waits in the review queue for approval before it is sent."
    },
    {
      "name": "Inbox",
      "description": "Conversations with the people your campaigns reached and, for accounts that opt in, your other LinkedIn and email conversations: read them, reply to them and follow changes live."
    },
    {
      "name": "Reviews",
      "description": "Messages and emails go to a lead only after someone approves them. The review queue holds the replies Bavlio drafted for people who answered and the messages and emails it drafted for campaign sequences."
    },
    {
      "name": "Billing",
      "description": "The plans on offer and the workspace's subscription and usage. Plan changes, cancellation and the billing portal need the workspace owner or an admin."
    },
    {
      "name": "LinkedIn",
      "description": "Connect the LinkedIn accounts your campaigns send from, confirm their sign-ins, choose the country LinkedIn sees them from, and disconnect them."
    },
    {
      "name": "Meetings",
      "description": "Meetings booked through the workspace's calendar tool (Google Calendar, Calendly or Cal.com), and the calendar connection that imports them."
    },
    {
      "name": "Email",
      "description": "Connect a Bavimail account, add sending domains and tracking domains, and create the inboxes campaigns send email from."
    }
  ],
  "servers": [
    {
      "url": "https://api.bavlio.com"
    }
  ]
}
```
