All endpoints

Batch-patch lead identity on multiple enrollments

POSThttps://myagentmail.com/cadences/{id}/enrollments/bulk-relink

Batched form of PATCH /v1/enrollments/{id} for the common recovery flow "we enrolled N leads with the wrong payload shape; fix all of them at once."

Same merge semantics as the per-row PATCH (only fields present in each update are touched; explicit null clears).

Partial failure is allowed

A single bad row (terminal state, external-ID conflict, not-found) does NOT fail the whole batch. The response contains a results[] array mirroring the input order; each slot is either { ok: true, enrollmentId, enrollment } or { ok: false, enrollmentId, code, error, detail }. Response status is always 200; inspect results[i].ok per row.

Limits

  • Max 100 updates per call. Iterate client-side for larger batches.
  • Each enrollmentId must belong to the cadence in the path — rows pointing at a different cadence are rejected with CADENCE_MISMATCH.

?retryNow=true

Applies to all rows in the batch. Same semantics as the per-row endpoint — resets next_step_due_at on each successfully- updated row to NOW so the runner re-attempts on its next tick.

Worked example

Request:

POST /v1/cadences/01HY…/enrollments/bulk-relink?retryNow=true
Content-Type: application/json

{
  "updates": [
    {
      "enrollmentId": "01HZ…aaaa",
      "leadName": "Jane Doe",
      "leadLinkedinUrl": "https://www.linkedin.com/in/jane-doe-1a2b3c/"
    },
    {
      "enrollmentId": "01HZ…bbbb",
      "leadName": "John Smith",
      "leadLinkedinUrl": "https://www.linkedin.com/in/john-smith/"
    }
  ]
}

Response:

{
  "ok": true,
  "succeeded": 2,
  "failed": 0,
  "results": [
    { "ok": true, "enrollmentId": "01HZ…aaaa", "enrollment": { … } },
    { "ok": true, "enrollmentId": "01HZ…bbbb", "enrollment": { … } }
  ]
}

With one row in a terminal state:

{
  "ok": true,
  "succeeded": 1,
  "failed": 1,
  "results": [
    { "ok": true, "enrollmentId": "01HZ…aaaa", "enrollment": { … } },
    {
      "ok": false,
      "enrollmentId": "01HZ…bbbb",
      "code": "ENROLLMENT_TERMINAL_STATE",
      "error": "Enrollment is in terminal state 'replied'; lead identity cannot be modified.",
      "detail": { "state": "replied" }
    }
  ]
}

Path parameters

id
required
string

Cadence id. All enrollments in `updates` must belong to this cadence.

Query parameters

retryNow
boolean

Request body

Content-Type: application/json

updates
required
object[]
enrollmentId
required
string

format: uuid

leadName
string
leadEmail
string

format: email

leadLinkedinUrl
string

format: uri

leadProfileUrn
string
leadExternalId
string
inboxId
string

format: uuid

sessionId
string

format: uuid

Responses

200application/jsonPer-row results. Inspect each `results[i].ok` — overall status code is 200 even when some rows failed.
ok
boolean
succeeded
integer
failed
integer
results
object[]
ok
boolean
enrollmentId
string

format: uuid

enrollment
object

Present when ok=true. Same shape as the per-row PATCH response.

code
"NOT_FOUND" | "CADENCE_MISMATCH" | "ENROLLMENT_TERMINAL_STATE" | "LEAD_EXTERNAL_ID_CONFLICT" | "PATCH_FAILED"

Present when ok=false.

enum: "NOT_FOUND" | "CADENCE_MISMATCH" | "ENROLLMENT_TERMINAL_STATE" | "LEAD_EXTERNAL_ID_CONFLICT" | "PATCH_FAILED"

error
string
detail
object

Extra context — `{ state }` on terminal, `{ conflictingExternalId }` on ID conflict.

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.