Campaign Contacts
An enrollment links a contact to a campaign and records how far that contact has progressed through the campaign's steps.
The enrollment object
json
{
"id": 77,
"campaign_id": 12,
"contact_id": 42,
"current_step_id": 3,
"status": "in_progress",
"completed_at": null,
"created_at": "...",
"updated_at": "...",
"contact": { /* Contact */ },
"current_step": { /* Step */ }
}status is one of pending, in_progress, completed, failed or unsubscribed.
Endpoints
In the paths below, {contact} is the contact ID, not the enrollment ID.
| Method | Path | Permission | Description |
|---|---|---|---|
| GET | /campaigns/{id}/contacts | campaigns:read | Enrollments, newest first (paginated) |
| POST | /campaigns/{id}/contacts | campaigns:write | Enroll contacts by ID |
| POST | /campaigns/{id}/contacts/enroll-from-lists | campaigns:write | Enroll every contact in some lists or segments |
| GET | /campaigns/{id}/contacts/{contact} | campaigns:read | Get one enrollment |
| DELETE | /campaigns/{id}/contacts/{contact} | campaigns:write | Remove a contact from the campaign. Returns 204. |
| POST | /campaigns/{id}/contacts/{contact}/skip | campaigns:write | Move a contact to the next step |
Enroll contacts
json
{ "contact_ids": [42, 43, 44] }- IDs that aren't in your workspace are ignored.
- Contacts already enrolled are counted in
skipped. - Enrolled contacts start at the first step.
- If the campaign is
active, they start receiving its emails immediately.
201
json
{ "data": { "message": "2 contacts enrolled successfully", "enrolled": 2, "skipped": 1 } }Enroll from lists or segments
json
{ "list_ids": [1, 2], "segment_ids": [3] }Returns the same response as enrolling contacts by ID.
Skip to the next step
POST /campaigns/{id}/contacts/{contact}/skipjson
{ "data": { "message": "Contact moved to next step", "status": null, "current_step_id": 4 } }If the contact was already on the last step, the response is "Contact campaign completed" with status: "completed".