REST API Reference
The /api/v1 endpoints let your backend start workflow runs, poll their status, fetch conversation messages, stream live events, and mint participant tokens. All endpoints require an API key unless noted otherwise.
Basics
All requests are JSON over HTTPS against your Chatterfly host. Authenticate with your deployment's API key as a bearer token:
Authorization: Bearer cf_your_api_key_here
Content-Type: application/jsonThe API key identifies the deployment, so endpoints operate on “the workflow this key belongs to” — there is no workflow ID parameter.
| Endpoint | Purpose |
|---|---|
| POST /api/v1/runs | Start a new run of the deployment. |
| GET /api/v1/runs/{id} | Get run status, state, and current step. |
| GET /api/v1/runs/{id}/messages | List the run's conversation messages. |
| GET /api/v1/runs/{id}/stream | WebSocket stream of live run events. |
| POST /api/v1/runs/{id}/tokens | Mint a participant token for a role. |
| GET /api/v1/schema/workflow | The workflow JSON Schema (public, no auth). |
Start a run
POST /api/v1/runs
Authorization: Bearer cf_your_api_key_here
Content-Type: application/json
{
"input": { "name": "Alice", "issue": "Billing query" }
}| Field | Description |
|---|---|
| input | Object of initial run state, validated against the workflow's declared inputs. Available to nodes via template variables like {{state.name}}. |
| connections | Optional. Per-run credentials for connections whose fulfillment is set to caller, keyed by connection slug. |
| hooks | Optional. Run-scoped event hooks (see Triggers & Webhooks). |
Returns 202 Accepted — execution is asynchronous, queued immediately:
{ "run_id": "run_xyz789", "status": "pending" }inputfails validation against the workflow's declared inputs, the API returns 422 with an { "errors": [...] } array describing each problem.Get run status
GET /api/v1/runs/run_xyz789{
"id": "run_xyz789",
"status": "running",
"state": { "name": "Alice", "issue": "Billing query" },
"current_step_id": "ask-details",
"created_at": "2026-06-10T12:00:00Z",
"started_at": "2026-06-10T12:00:01Z"
}| Field | Description |
|---|---|
| status | pending → running → completed | failed. Waiting states appear while a HITL session is open. |
| state | The run's accumulated state object — initial input plus values captured by Input/Agent nodes. |
| current_step_id | ID of the node currently executing, if any. |
| error | Failure message when status is failed. |
Get run messages
GET /api/v1/runs/run_xyz789/messages[
{
"id": "msg_1",
"role": "assistant",
"content": "Hi Alice! How can I help with your billing query?",
"step_id": "support-agent",
"created_at": "2026-06-10T12:00:02Z"
}
]Useful for rendering transcripts or archiving conversations after a run completes.
Stream run events
For live updates, open a WebSocket instead of polling. Events are pushed as JSON frames as the engine executes:
wss://your-chatterfly.example.com/api/v1/runs/run_xyz789/streamAuthenticate the upgrade request with the same Authorization header. Each frame carries an event type (step started/completed, message created, run completed, etc.) and a payload.
Mint participant token
POST /api/v1/runs/run_xyz789/tokens
Authorization: Bearer cf_your_api_key_here
Content-Type: application/json
{ "role": "customer" }{ "participant_token": "eyJhbGciOiJIUzI1NiIs..." }The token is a JWT valid for 1 hour, scoped to this run and role. Pass it to the widget on your frontend. See Authentication for details.
Workflow schema
The full JSON Schema for workflow definitions is served publicly — handy for editor tooling and validation in CI:
GET /api/v1/schema/workflowErrors & rate limits
| Status | Meaning |
|---|---|
| 400 | Malformed request body or invalid ID. |
| 401 | Missing or invalid API key. Check the Authorization header format: Bearer cf_… |
| 404 | Run not found — or it belongs to a different deployment than your key. |
| 422 | Run input failed validation; response body contains an errors array. |
| 429 | Per-tenant rate limit exceeded. Back off and retry with exponential delay. |
Error responses share the shape { "error": "message" }.
