Cadences
List enrollments for this cadence
Returns enrollments newest-first, with per-row step-run summary so you can render a "3 of 5 ✅" progress + "Blocked: <reason>" badge in one HTTP call — no N+1 fetch into /v1/enrollments/{id}.
What you get per enrollment
Identity (set at enroll time, returned verbatim):
- leadExternalId — your idempotency key
- leadName, leadEmail, leadLinkedinUrl — whatever you sent on enrollment. Returned even if null.
- leadProfileUrn — urn:li:fsd_profile:…, set by the runner after the first LinkedIn invite resolves the profile. Null until then.
- sessionId — LinkedIn session the cadence runs through. May be auto-picked from the workspace pool if you didn't pass one (see commit f0d2ff1) — once picked, it's pinned to the enrollment.
State + progress:
- state — active | paused | completed | replied | accepted | bounced | unenrolled | error
- currentStep — 0-based index of the NEXT step due
- stepsCompleted — count of DISTINCT step indices that have fired with status='sent'. Visual: green checkmark count.
- nextStepDueAt — when the runner will next consider this row (ISO 8601). Past time = overdue + queued.
- lastStepFiredAt — ISO 8601 of the most recent step run.
- lastError — most recent FAILED step run (status= failed), or null if no failures. Keys: code, message, atStepIndex, firedAt. The code values match what runner.ts writes — most common today are NO_SESSION_AVAILABLE, WORKSPACE_QUOTA_EXHAUSTED, PINNED_SESSION_UNUSABLE, NO_TARGET, NO_INBOX, DRAFT_WEBHOOK_FAILED (your draft handler timed out, 5xx'd, or returned malformed JSON), and AI_STRATEGY_REMOVED (pre-existing step still on draftStrategy: "ai" — update the step to static or webhook). Skipped steps (a step whose condition didn't apply — e.g. after_accept on a rejected invite, or your draft handler returned { skip: true }) are NOT counted as errors; they're a normal part of cadence execution.
Worked example response
{
"ok": true,
"enrollments": [
{
"id": "01HZ…",
"cadenceId": "01HY…",
"leadExternalId": "delegated:lead:abc-123",
"leadName": "Jane Doe",
"leadEmail": "jane@acme.com",
"leadLinkedinUrl": "https://www.linkedin.com/in/jane-doe-1a2b3c/",
"leadProfileUrn": "urn:li:fsd_profile:ACoAAA…aaaa",
"sessionId": "01HX…",
"inboxId": "01HW…",
"currentStep": 3,
"state": "active",
"stepsCompleted": 2,
"nextStepDueAt": "2026-05-21T14:00:00Z",
"lastStepFiredAt": "2026-05-19T14:00:00Z",
"lastError": null,
"enrolledAt": "2026-05-18T10:30:00Z",
"updatedAt": "2026-05-19T14:00:00Z"
},
{
"id": "01HZ…",
"cadenceId": "01HY…",
"leadExternalId": "delegated:lead:def-456",
"leadName": "John Smith",
"leadEmail": null,
"leadLinkedinUrl": "https://www.linkedin.com/in/john-smith/",
"leadProfileUrn": null,
"sessionId": null,
"inboxId": null,
"currentStep": 0,
"state": "active",
"stepsCompleted": 0,
"nextStepDueAt": "2026-05-19T13:00:00Z",
"lastStepFiredAt": "2026-05-19T13:00:00Z",
"lastError": {
"code": "NO_SESSION_AVAILABLE",
"message": "no_active_linkedin_session_in_workspace — connect a LinkedIn account from /dashboard/linkedin to start running cadence steps",
"atStepIndex": 0,
"firedAt": "2026-05-19T13:00:00Z"
},
"enrolledAt": "2026-05-19T12:00:00Z",
"updatedAt": "2026-05-19T13:00:00Z"
}
]
}
Drilling into one enrollment
For per-step ✅ render (the full stepRuns[] history, including skipped steps, rendered message text, channel URNs), call GET /v1/enrollments/{id} — that endpoint returns the same enrollment fields plus a stepRuns array of the last 50 runs ordered newest-first.
get/cadences/{id}/enrollments
Request
- Base URL: https://anjal.app
- URL: https://anjal.app/cadences/{id}/enrollments
- Auth: API key in header X-API-Key
Path parameters
idstring uuid required
Query parameters
state'active' | 'paused' | 'completed' | 'replied' | 'accepted' | 'bounced' | 'unenrolled' | 'error'
Filter by enrollment state.
limitinteger
Response
Enrollment list (with per-row step-run summary).
Changes
No recorded changes to this operation across all 1 revision of this API.