---
title: "Add a sequence step"
method: POST
path: "/business/campaigns/{campaignId}/steps"
tags: ["Campaign steps"]
---

# Add a sequence step

`POST /business/campaigns/{campaignId}/steps`

## Request

- Base URL: `https://api.tryfuse.ai/api/v1`
- URL: `https://api.tryfuse.ai/api/v1/business/campaigns/{campaignId}/steps`
- Auth: HTTP basic

Adds one sequence step. `sequenceNumber` is the step's 0-based slot - the same numbering GET /business/campaigns/{campaignId}/steps reports - and must be free (409 STEP_POSITION_TAKEN); existing steps are not shifted on insert, and only DELETE renumbers. `daysBetween` is the wait after the previous step (after the campaign start for step 0). `type: manual` sends your `subject`/`body` as written, with {Variable} tokens and spintax substituted per lead at send time; `type: ai_generated` writes its own topic and title with AI when the step is created and renders each message per lead (do not send `topic`); `type: ai_reply` drafts a reply from the `topic` you supply and parks it for approval. `linkedin_visit` and `linkedin_like` steps carry no message at all. A `linkedin_connection` step may not follow a `linkedin_message` step (422 STEP_ORDER_INVALID). Only the token owner may add steps. Rate limit: 30 requests/minute and 1,000/day per token owner, shared by every campaign, scheduled-send, campaign-template and knowledge-hub endpoint.

Errors:
- `404` `CAMPAIGN_NOT_FOUND` — No campaign with this id exists, it belongs to another account (including a campaign delegated to you or shared by your team's visibility settings), or it has been deleted.
- `409` `STEP_POSITION_TAKEN` — A step already occupies this sequenceNumber in the campaign.
- `422` `STEP_ORDER_INVALID` — A linkedin_connection step would follow a linkedin_message step.
- `422` `VALIDATION_FAILED` — Unknown key, missing channel/sequenceNumber/daysBetween, a value out of range, a topic on an ai_generated step, a missing topic on an ai_reply step, or content on a linkedin_visit / linkedin_like step; `param` names the field.
- `429` `RATE_LIMITED` — More than 30 campaign requests in a minute, or 1,000 in a day, for this token owner (the bucket is shared by every /business/campaigns, /business/scheduled-sends, /business/campaign-templates and /business/knowledge-hubs call).
- `500` `UNEXPECTED_ERROR` — The step could not be stored, or AI topic generation failed for an ai_generated step.

Requires one of the following token scopes: campaigns.

## Path parameters

- `campaignId` string, required: The campaign's id (24-character hex ObjectId), as returned by POST /business/campaigns or as the campaignId of a GET /business/campaigns row.

## Request body

- object
  - `channel` 'email' | 'linkedin_connection' | 'linkedin_message' | 'linkedin_visit' | 'linkedin_like' | 'inmail' | 'dialer' | 'todo', required: Step channel: email, linkedin_connection (connection request), linkedin_message (message to an accepted connection), linkedin_visit (profile visit, no content), linkedin_like (reaction to a recent post, no content), inmail (LinkedIn InMail, consumes InMail credits), dialer (phone-call task for a rep) or todo (free-form human task). A linkedin_connection step cannot come after a linkedin_message step (422 STEP_ORDER_INVALID).
  - `type` 'manual' | 'ai_generated' | 'ai_reply': manual (default) sends your subject/body as written; ai_generated writes a topic and title with AI at creation and renders each message per lead at send time (send no topic — it is generated); ai_reply is an AI-drafted reply that waits for approval and needs a topic.
  - `sequenceNumber` integer, required: The step's 0-based slot in the sequence — the same numbering GET /business/campaigns/{campaignId}/steps reports, so 0 is the first step. Must be unused in this campaign (409 STEP_POSITION_TAKEN); existing steps are not shifted on insert (only DELETE renumbers).
  - `daysBetween` integer, required: Whole days to wait after the previous step (or after the campaign start for the first step) before this one is due, 0-90.
  - `subject` string: Subject line for a manual step (up to 500 characters, may be empty); becomes the step title. Rejected on linkedin_visit and linkedin_like steps, which carry no message.
  - `body` unknown
  - `topic` string: Free text: what this step should say, in your own words — there is no fixed set of topics. 1-500 characters. Required for ai_reply, rejected for ai_generated (which generates its own) and for linkedin_visit / linkedin_like steps. Stored but not rendered on a manual step.
  - `cc` string[]: Accepted values: bare email addresses such as ops@example.com — a display name or angle brackets is rejected, up to 320 characters each. Every address you list is copied on every send of this step, up to 10 addresses. Only an email step actually sends them: on any other channel the value is stored and never used.

## Response `201`

Success

- object
  - `step` object, required
    - `id` string, required
    - `channel` 'email' | 'linkedin_connection' | 'linkedin_message' | 'linkedin_visit' | 'linkedin_like' | 'inmail' | 'dialer' | 'todo' | 'null', nullable, required
    - `type` 'manual' | 'ai_generated' | 'ai_reply' | 'null', nullable, required: How the step's message is produced.
    - `sequenceNumber` integer, nullable, required: 0-based slot in the sequence.
    - `daysBetween` integer, nullable, required: Whole days to wait after the previous step.
    - `title` string, nullable, required: Editor label; set from the subject on a manual step and generated with the topic on an AI step.
    - `topic` string, nullable, required: Brief an AI step writes each message from; null on an unwritten manual step.
    - `subject` string, nullable, required: Manual subject line; null when the step has no template yet or is AI-written.
    - `body` string, nullable, required: Manual message body; null when the step has no template yet or is AI-written.
    - `cc` string[], required: Addresses copied on every send of this step (email only).

## Other responses

- `400`: Error
- `401`: Error
- `402`: Error
- `403`: Error
- `404`: Error
- `409`: Error
- `422`: Error
- `429`: Error
- `500`: Error

---

[API](https://skmtc.dev/fuseai/apis/fuse-business-api.md) · [All operations](https://skmtc.dev/fuseai/apis/fuse-business-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fuseai/apis/fuse-business-api/revisions/50d95e0536f4?raw)
