Enroll contacts
Enroll up to 100 contacts into an active workflow. Enrollment is asynchronous: each contact gets a pending execution that the workflow engine then runs. Running the workflow can send emails and texts and place AI calls, which cost money.
POST
https://api.centerfy.ai/webhooks/inbound/workflows/:id/enroll Headers
| Header | Required | Value | Description |
|---|---|---|---|
x-api-key | Yes | your sub-account API key (cfy_…) | Authenticates the request; or use Authorization: Bearer <key>. |
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | The workflow id. |
Body parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
contact_ids | string[] (uuid) | Yes | — | 1 to 100 contact ids in this sub-account. Duplicates are ignored. |
allow_duplicates | boolean | No | — | Enroll contacts even if they are already in this workflow. Defaults to false: contacts with a pending, running, waiting, waiting_for_reply or paused execution are skipped. |
Request body
{
"contact_ids": [
"3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
"8d4e5f6a-7b8c-4d9e-9f0a-2b3c4d5e6f7a"
]
}Example
curl -X POST "https://api.centerfy.ai/webhooks/inbound/workflows/{id}/enroll" \
-H "x-api-key: $CENTERFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact_ids": [
"3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
"8d4e5f6a-7b8c-4d9e-9f0a-2b3c4d5e6f7a"
]
}' import { CenterfyClient } from "@centerfy/sdk";
const centerfy = new CenterfyClient({ apiKey: process.env.CENTERFY_API_KEY! });
const result = await centerfy.workflows.enroll("<workflowId>", {
"contact_ids": [
"3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
"8d4e5f6a-7b8c-4d9e-9f0a-2b3c4d5e6f7a"
]
});
console.log(result); centerfy workflows enroll <workflowId> '{"contact_ids":["3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f","8d4e5f6a-7b8c-4d9e-9f0a-2b3c4d5e6f7a"]}' MCP tool: centerfy_workflows_enroll (see MCP server)
Response
{
"status": "success",
"enrolled": 1,
"skipped_contact_ids": [
"8d4e5f6a-7b8c-4d9e-9f0a-2b3c4d5e6f7a"
],
"executions": [
{
"id": "7c3d4e5f-6a7b-4c8d-8e9f-1a2b3c4d5e6f",
"workflow_id": "5a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
"status": "pending",
"started_at": "2026-10-05T14:00:00.000Z",
"completed_at": null,
"error_message": null,
"current_step_id": null,
"next_step_at": null
}
]
}Errors
400— if a contact id is not a UUID (invalid_contact_ids) or not in this sub-account (missing_contact_ids); nothing is enrolled in that case.404— if the workflow is not in this sub-account.409— if the workflow is not active.
Notes
Returns 202 (also when every contact was skipped — enrolled is then 0). Skipping already-enrolled contacts makes retries safe.