Replace the step list atomically
https://myagentmail.com/cadences/{id}/stepsSends the full ordered list of steps in one call — wipes the previous steps and reinserts. Steps are tiny; diffing is more trouble than it's worth.
Step kinds:
• linkedin_connect — POST a connection request (with note)
• linkedin_message — DM a 1st-degree connection
• email — (v1.1) send via configured inbox
• wait — no-op delay before the next step
Conditions (optional, NULL = always run):
• after_accept — only run if the previous linkedin_connect step's
invite has been accepted (signal.connection_accepted with
outbound attribution)
• no_reply_to_prev — only run if the lead hasn't replied since
the previous step
• never_replied — only run if the lead has never replied during
this enrollment
Path parameters
idrequired string |
Request body
Content-Type: application/json
stepsrequired object[] | |
kindrequired "linkedin_connect" | "linkedin_message" | "email" | "wait" | enum: "linkedin_connect" | "linkedin_message" | "email" | "wait" |
delayDaysrequired number | Days after the previous step's completion. 0 = fire on enrollment for step 0; 0.25 = 6 hours. |
condition"after_accept" | "no_reply_to_prev" | "never_replied" | enum: "after_accept" | "no_reply_to_prev" | "never_replied" |
draftStrategy"static" | "webhook" | How the runner gets the rendered content for this step. - `static` — Use `staticBody` (+ `staticSubject` for email) as the message verbatim, with `{{name}}`, `{{first_name}}`, `{{email}}` token substitution. Predictable; zero external deps. - `webhook` — At fire-time, the runner POSTs a `cadence.step.draft.requested` event to the cadence's `webhookUrl` and waits up to 30s for a JSON response of `{ body, subject?, skip?, defer? }`. The customer's app brings the actual content with its own business context, its own LLM if it wants one, its own thread memory. MAM never generates copy on the customer's behalf. The legacy `"ai"` value was REMOVED 2026-05-19 — MAM no longer drafts content server-side. New cadences passing `"ai"` get a `VALIDATION_ERROR` with a migration hint pointing here. Pre-existing rows with `"ai"` will surface `AI_STRATEGY_REMOVED` as the per-enrollment `lastError.code` when the runner tries to fire them — fix by updating the step to `static` (with `staticBody`) or `webhook` (with the cadence's `webhookUrl` set). enum: "static" | "webhook" default: "static" |
staticSubjectstring | Email-only. The literal subject line for static-strategy email steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens. |
staticBodystring | The literal message body for static-strategy steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens. Required when `draftStrategy: "static"`. |
promptHintstring | Free-text hint for the step. MAM does not read this — it's passed through verbatim in the `cadence.step.draft.requested` webhook payload (`step.promptHint`) so the customer's draft handler can use it as per-step context. Ignored by static strategy. |
notesstring | Operator notes — not sent anywhere, just stored for the customer's reference. |
Responses
Authentication
Send your API key in the X-API-Key header (or Authorization: Bearer <key>). Any prefix accepted by this endpoint — tk_, wk_, ak_, or sa_ — is documented in the key prefix table.