All endpoints

Create an outreach cadence

POSThttps://myagentmail.com/cadences

A cadence is a server-side outreach sequence — an ordered list of steps (LinkedIn invite → wait → DM → email → ...) that fire automatically per enrollment with branching on real-world events (invite accepted, lead replied).

The runtime is on MyAgentMail's side. Customer apps call POST /v1/cadences/:id/enrollments to enroll a lead and receive webhook events as the cadence progresses.

Request body

Content-Type: application/json

name
required
string
description
string
businessHoursOnly
boolean

default: true

exitOnReply
boolean

default: true

exitOnUnsubscribe
boolean

default: true

dailySendCap
integer

default: 50

webhookUrl
string

format: uri

steps
object[]

Optional inline step list. You can also PATCH /v1/cadences/:id/steps later.

kind
required
"linkedin_connect" | "linkedin_message" | "email" | "wait"

enum: "linkedin_connect" | "linkedin_message" | "email" | "wait"

delayDays
required
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"

staticSubject
string

Email-only. The literal subject line for static-strategy email steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens.

staticBody
string

The literal message body for static-strategy steps. Supports `{{name}}` / `{{first_name}}` / `{{email}}` tokens. Required when `draftStrategy: "static"`.

promptHint
string

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.

notes
string

Operator notes — not sent anywhere, just stored for the customer's reference.

Responses

201application/jsonCadence created.
ok
boolean
cadence
object
id
string

format: uuid

name
string
description
string
enabled
boolean
businessHoursOnly
boolean
exitOnReply
boolean
exitOnUnsubscribe
boolean
dailySendCap
integer
webhookUrl
string
webhookSecret
string

HMAC secret for X-MyAgentMail-Signature.

createdAt
string

format: date-time

updatedAt
string

format: date-time

steps
any[]

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.