ApiWorkflows

Get a workflow

GET
/workflows/{id}

Retrieve a specific workflow with its full definition.

Authorization

BearerAuth
AuthorizationBearer <token>

API key authentication. Get your key from the dashboard.

In: header

Path Parameters

id*string

Workflow UUID

Formatuuid

Response Body

application/json

application/json

application/json

curl -X GET "https://example.com/workflows/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{
  "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 API key",
  "message": "string"
}
{
  "error": "Invalid API key",
  "message": "string"
}

List all workflows GET

Retrieve all workflows in your organization. The list view summarizes each graph (entry node, node and edge counts); request a single workflow to get the full definition.

Create a workflow POST

Create a workflow. The definition is validated on write and anything invalid comes back as HTTP 400 with a `details` array listing every problem. Two kinds of check run there. The graph itself: unknown node references, unreachable nodes, missing edge descriptions, a transfer without an E.164 destination, and so on. And the values in the per-node config blocks, against the platform catalog: an unknown `provider` or `model` in `llm_config`, `tts_config` or `stt_config`, an unknown `stt_config.language`, an unknown `tts_config.voice_id` for a provider whose voices the catalog enumerates, a realtime provider in `llm_config` (realtime models cannot be set per node), and a `speech_config` block on a node (speech settings belong to the assistant). What write-time validation cannot judge is the assistant, because a workflow is stored on its own and is not bound to one until you attach it to a number. Everything that depends on the assistant is therefore checked at call start instead, where it fails closed and rejects before pickup rather than mid-call: per-node model overrides and `tts_config` / `stt_config` on a realtime assistant, a `voice` that does not belong to the provider of the assistant on the number, and a config block without a `provider`. A `201` says the definition is sound, not that every override suits the assistant that will end up running it. Attach it to a phone number with `PATCH /numbers/{id}`.