GET /v1/workflows and enroll a contact with POST /v1/workflows/{workflow_id}/enrollments.
List workflows
GET /v1/workflows returns the active, published workflows in your workspace that start manually, oldest first, up to 100. Each has a workflow_id and a label. Workflows that start another way, such as when a tag is added, aren’t listed. The list isn’t paginated.
curl
Response (200)
Enroll a contact
Send the contact’s ID and arequest_id that identifies this enrollment in your system.
curl
Response (201)
201 means the contact was enrolled and a workflow run started. The workflow’s first step runs from Blujay’s queue after the response; the messages it sends show up as message.sent and later events on your webhooks, with no link back to the enrollment.
Response fields
Retry safely with request_id
request_id is required (1 to 200 characters) and is how this endpoint avoids double enrollments. It doesn’t use the Idempotency-Key header.
- Sending the same
request_idfor the same workflow and contact again returns200with the original result. The contact isn’t enrolled twice. - The original result wins: a repeat with different
metadatadoesn’t change the enrollment. - The same
request_idfor a different contact is a separate enrollment. - A request that was rejected with an error isn’t remembered. After you fix the problem, send it again with the same
request_id.
Understand enrollments that don’t start a run
A200 can also mean Blujay accepted the enrollment but didn’t start a new run. Check enrollment_status and no_op_reason:
Response (200)
Add metadata
metadata is optional context about the enrollment, such as where it came from. Blujay stores it on the enrollment record so the enrollment can be traced back to your system when you contact support. Workflow steps can’t read it, it doesn’t change what the workflow sends, and no endpoint or webhook returns it.
- Up to 20 keys, each 1 to 64 characters.
- Values are strings (up to 500 characters), numbers, booleans or
null. - 4,096 bytes in total, measured as JSON.
400 VALIDATION_ERROR.
Handle errors
Limitations
- Enrollment is fire-and-forget. There is no endpoint to list a contact’s runs, read a run’s progress, cancel a run, or remove a contact from a workflow, and no webhook when a run starts, finishes or fails. Manage runs in the Blujay app.
- Only workflows that start manually can be enrolled through the API. Tag-triggered workflows start when you add the tag.
- One run per contact per workflow at a time: a second enrollment returns
no_opwithduplicate_non_terminal_rununtil the first run ends. - An opted-out contact is never enrolled (
no_op,contact_opted_out). - The messages a workflow sends follow the same sending rules and plan limits as API sends. A run on a Free Plan or AI Agent number can only message people who texted that number first; see Plans.
metadatais write-only.
Next steps
Contacts
Create or find the contact to enroll.
Opt-outs
Understand why an opted-out contact isn’t enrolled.
Idempotency
See how retries work across the API.