The Workflow API allows you to create sophisticated voice bot experiences with branching logic, external integrations, and multi-step processes. Design complex call flows visually or programmatically.

Overview

Workflows enable you to:
  • Create multi-step voice interactions
  • Implement conditional branching based on user input
  • Integrate with external APIs and databases
  • Handle complex business logic
  • Build reusable workflow components

Concepts

Workflow Structure

A workflow consists of connected nodes that define the call flow:
Start → Greeting → Menu → [Branch based on input]
                           ├── Option 1 → Action A → End
                           ├── Option 2 → Action B → End
                           └── Default → Transfer → End

Node Types

Node TypeDescription
startEntry point of the workflow
speakPlay TTS message or audio
listenCapture user speech input
dtmfCapture keypad input
conditionBranch based on conditions
api_callMake external API requests
set_variableSet or modify variables
transferTransfer call to another number
endEnd the call

Endpoint

Create Workflow

POST https://voice.intron.io/api/v1/voice-bot/workflow

Execute Workflow

POST https://voice.intron.io/api/v1/voice-bot/workflow/{workflow_id}/execute

Authentication

Authorization: Bearer YOUR_API_KEY

Create Workflow

Request Body

{
  "name": "Appointment Scheduler",
  "description": "Handle appointment scheduling and rescheduling",
  "language": "en",
  "voice": "en-female-1",
  "nodes": [
    {
      "id": "start",
      "type": "start",
      "next": "greeting"
    },
    {
      "id": "greeting",
      "type": "speak",
      "content": "Hello {{customer_name}}, thank you for calling. How can I help you today?",
      "next": "main_menu"
    },
    {
      "id": "main_menu",
      "type": "listen",
      "timeout": 10,
      "intents": ["schedule", "reschedule", "cancel", "other"],
      "next": "route_intent"
    },
    {
      "id": "route_intent",
      "type": "condition",
      "conditions": [
        {"if": "intent == 'schedule'", "next": "schedule_flow"},
        {"if": "intent == 'reschedule'", "next": "reschedule_flow"},
        {"if": "intent == 'cancel'", "next": "cancel_flow"},
        {"else": "next", "next": "transfer_agent"}
      ]
    },
    {
      "id": "schedule_flow",
      "type": "api_call",
      "method": "GET",
      "url": "https://api.yourapp.com/available-slots",
      "headers": {"Authorization": "Bearer {{api_token}}"},
      "response_variable": "available_slots",
      "next": "offer_slots"
    },
    {
      "id": "offer_slots",
      "type": "speak",
      "content": "I have availability on {{available_slots[0]}} and {{available_slots[1]}}. Which works better for you?",
      "next": "capture_selection"
    },
    {
      "id": "capture_selection",
      "type": "listen",
      "timeout": 15,
      "next": "confirm_booking"
    },
    {
      "id": "confirm_booking",
      "type": "api_call",
      "method": "POST",
      "url": "https://api.yourapp.com/bookings",
      "body": {
        "customer_id": "{{customer_id}}",
        "slot": "{{user_input}}"
      },
      "next": "booking_confirmation"
    },
    {
      "id": "booking_confirmation",
      "type": "speak",
      "content": "Your appointment has been scheduled. You'll receive a confirmation shortly. Is there anything else I can help with?",
      "next": "end_call"
    },
    {
      "id": "transfer_agent",
      "type": "transfer",
      "phone_number": "+18001234567",
      "message": "Let me connect you with an agent who can help."
    },
    {
      "id": "end_call",
      "type": "end",
      "message": "Thank you for calling. Goodbye!"
    }
  ]
}

Response

{
  "status": "success",
  "workflow_id": "wf_abc123def456",
  "name": "Appointment Scheduler",
  "created_at": "2024-01-15T10:30:00Z",
  "nodes_count": 12
}

Execute Workflow

Request

curl -X POST https://voice.intron.io/api/v1/voice-bot/workflow/wf_abc123def456/execute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+1234567890",
    "variables": {
      "customer_name": "John Doe",
      "customer_id": "cust_123",
      "api_token": "your_backend_api_token"
    },
    "callback_url": "https://yourapp.com/webhooks/workflow"
  }'

Response

{
  "status": "success",
  "execution_id": "exec_xyz789",
  "workflow_id": "wf_abc123def456",
  "call_id": "call_abc123",
  "started_at": "2024-01-15T10:35:00Z"
}

Node Types in Detail

Speak Node

Play a message to the caller:
{
  "id": "welcome",
  "type": "speak",
  "content": "Welcome to our service, {{name}}!",
  "voice": "en-female-1",
  "speed": 1.0,
  "next": "next_node"
}
Or play pre-recorded audio:
{
  "id": "welcome",
  "type": "speak",
  "audio_url": "https://yourserver.com/audio/welcome.mp3",
  "next": "next_node"
}

Listen Node

Capture speech input:
{
  "id": "capture_intent",
  "type": "listen",
  "timeout": 10,
  "language": "en",
  "intents": ["yes", "no", "help"],
  "no_input_message": "I didn't hear anything. Could you please repeat?",
  "no_match_message": "I didn't understand. Please say yes or no.",
  "max_retries": 2,
  "next": "process_response"
}

DTMF Node

Capture keypad input:
{
  "id": "menu_selection",
  "type": "dtmf",
  "prompt": "Press 1 for sales, 2 for support, or 0 for operator.",
  "timeout": 10,
  "max_digits": 1,
  "valid_inputs": ["1", "2", "0"],
  "next": "route_selection"
}

Condition Node

Branch based on conditions:
{
  "id": "check_balance",
  "type": "condition",
  "conditions": [
    {"if": "balance > 1000", "next": "high_balance"},
    {"if": "balance > 0", "next": "positive_balance"},
    {"if": "balance == 0", "next": "zero_balance"},
    {"else": true, "next": "negative_balance"}
  ]
}

API Call Node

Make external API requests:
{
  "id": "fetch_account",
  "type": "api_call",
  "method": "GET",
  "url": "https://api.yourapp.com/accounts/{{account_id}}",
  "headers": {
    "Authorization": "Bearer {{api_key}}",
    "Content-Type": "application/json"
  },
  "timeout": 5000,
  "response_variable": "account_data",
  "on_error": "api_error_handler",
  "next": "process_account"
}

Set Variable Node

Set or modify variables:
{
  "id": "calculate_total",
  "type": "set_variable",
  "variables": {
    "total": "{{price}} * {{quantity}}",
    "formatted_total": "'$' + total.toFixed(2)"
  },
  "next": "display_total"
}

Transfer Node

Transfer the call:
{
  "id": "transfer_sales",
  "type": "transfer",
  "phone_number": "+18005551234",
  "message": "Please hold while I connect you to our sales team.",
  "timeout": 30,
  "on_failure": "transfer_failed"
}

Workflow Management

List Workflows

GET https://voice.intron.io/api/v1/voice-bot/workflow

Get Workflow

GET https://voice.intron.io/api/v1/voice-bot/workflow/{workflow_id}

Update Workflow

PUT https://voice.intron.io/api/v1/voice-bot/workflow/{workflow_id}

Delete Workflow

DELETE https://voice.intron.io/api/v1/voice-bot/workflow/{workflow_id}

Get Execution Status

GET https://voice.intron.io/api/v1/voice-bot/workflow/execution/{execution_id}

Response

{
  "execution_id": "exec_xyz789",
  "workflow_id": "wf_abc123def456",
  "status": "completed",
  "call_id": "call_abc123",
  "started_at": "2024-01-15T10:35:00Z",
  "ended_at": "2024-01-15T10:40:00Z",
  "duration": 300,
  "path": ["start", "greeting", "main_menu", "schedule_flow", "offer_slots", "confirm_booking", "end_call"],
  "variables": {
    "customer_name": "John Doe",
    "selected_slot": "Monday 2pm"
  }
}

Webhook Events

Node Executed

{
  "event": "workflow.node_executed",
  "execution_id": "exec_xyz789",
  "node_id": "greeting",
  "node_type": "speak",
  "timestamp": "2024-01-15T10:35:05Z"
}

Workflow Completed

{
  "event": "workflow.completed",
  "execution_id": "exec_xyz789",
  "workflow_id": "wf_abc123def456",
  "outcome": "success",
  "final_node": "end_call",
  "duration": 300,
  "variables": {...}
}

Error Handling

Add error handling nodes to gracefully handle failures:
{
  "id": "api_error_handler",
  "type": "speak",
  "content": "I'm having trouble accessing your information. Let me connect you with an agent.",
  "next": "transfer_agent"
}

Best Practices

Test your workflows thoroughly with different scenarios before deploying to production.
  1. Design for Failures: Always include error handling paths
  2. Keep It Simple: Break complex flows into smaller, reusable workflows
  3. Use Variables: Leverage variables for personalization and state management
  4. Set Timeouts: Configure appropriate timeouts for each node
  5. Monitor Executions: Track workflow performance and optimize based on data
For simpler automated calls without complex logic, see the Robo Voice Call documentation.