Create a workflow
Create a workflow. The definition is validated on write: invalid definitions are rejected with HTTP 400 and a details array listing every problem (unknown node references, unreachable nodes, missing edge descriptions, and so on), so a workflow that saves is a workflow that runs. Attach it to a phone number with PATCH /numbers/{id}.
Authorization
BearerAuth API key authentication. Get your key from the dashboard.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/workflows" \ -H "Content-Type: application/json" \ -d '{ "name": "Dental practice reception", "definition": { "version": 1, "entry_node": "reception", "global_prompt": "You work for Riverside Dental. Be warm and concise.", "nodes": [ { "id": "reception", "type": "conversation", "instructions": "You are the receptionist. Handle general questions. When the caller asks about availability, hand off to the availability check.", "first_line": "Good afternoon, Riverside Dental. How can I help you?", "global": true, "global_description": "The caller wants the reception back or has a general question." }, { "id": "check_availability", "type": "tool", "tool_name": "check_availability", "url": "https://api.example.com/availability", "arguments": { "location": "riverside", "days_ahead": 7 }, "first_line": "One moment while I look that up for you." }, { "id": "specialist", "type": "conversation", "instructions": "You are Sam, the scheduling specialist. Use the availability result from the context to help the caller pick a slot.", "first_line": "You are speaking with Sam, the scheduling specialist.", "llm_config": { "provider": "openai", "model": "gpt-5.4-mini" } }, { "id": "human", "type": "transfer", "destination": "+31201234567", "first_line": "I am transferring you to a colleague now, one moment please." }, { "id": "goodbye", "type": "end", "first_line": "Thanks for calling Riverside Dental. Have a great day!" } ], "edges": [ { "from": "reception", "to": "check_availability", "description": "The caller asks about available appointment slots.", "message": "Let me check that for you." }, { "from": "check_availability", "to": "specialist" }, { "from": "specialist", "to": "human", "description": "The caller explicitly asks for a human employee." }, { "from": "reception", "to": "goodbye", "description": "The caller indicates the conversation is finished." }, { "from": "specialist", "to": "goodbye", "description": "The caller indicates the conversation is finished." } ] } }'{
"workflow": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "Dental practice reception",
"is_active": true,
"definition": {
"version": 1,
"entry_node": "reception",
"global_prompt": "You work for Riverside Dental. Be warm and concise.",
"nodes": [
{
"id": "reception",
"type": "conversation",
"instructions": "You are the receptionist. Handle general questions. When the caller asks about availability, hand off to the availability check.",
"first_line": "Good afternoon, Riverside Dental. How can I help you?",
"global": true,
"global_description": "The caller wants the reception back or has a general question."
},
{
"id": "check_availability",
"type": "tool",
"tool_name": "check_availability",
"url": "https://api.example.com/availability",
"arguments": {
"location": "riverside",
"days_ahead": 7
},
"first_line": "One moment while I look that up for you."
},
{
"id": "specialist",
"type": "conversation",
"instructions": "You are Sam, the scheduling specialist. Use the availability result from the context to help the caller pick a slot.",
"first_line": "You are speaking with Sam, the scheduling specialist.",
"llm_config": {
"provider": "openai",
"model": "gpt-5.4-mini"
}
},
{
"id": "human",
"type": "transfer",
"destination": "+31201234567",
"first_line": "I am transferring you to a colleague now, one moment please."
},
{
"id": "goodbye",
"type": "end",
"first_line": "Thanks for calling Riverside Dental. Have a great day!"
}
],
"edges": [
{
"from": "reception",
"to": "check_availability",
"description": "The caller asks about available appointment slots.",
"message": "Let me check that for you."
},
{
"from": "check_availability",
"to": "specialist"
},
{
"from": "specialist",
"to": "human",
"description": "The caller explicitly asks for a human employee."
},
{
"from": "reception",
"to": "goodbye",
"description": "The caller indicates the conversation is finished."
},
{
"from": "specialist",
"to": "goodbye",
"description": "The caller indicates the conversation is finished."
}
]
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
}
}{
"error": "Invalid workflow definition",
"details": [
"entry_node \"missing\" does not reference an existing node",
"node 'human': transfer nodes require destination in E.164 format (e.g. +31612345678)"
]
}{
"error": "Invalid API key",
"message": "string"
}Get a workflow GET
Retrieve a specific workflow with its full definition.
Update a workflow PATCH
Update a workflow's name, definition or active state. A new definition replaces the old one entirely and is validated the same way as on create. Changes apply to the next call; calls already in progress finish on the definition they started with.