Skip to main content

Dial Plans

Build visual call routing flows with dial plans.

Overview

A dial plan defines how incoming calls are routed through a series of steps, represented as a flowchart. Each step in the flowchart is called a node. Nodes check conditions (like business hours) or ring extensions, then route to the next step based on the outcome.

Think of it like a flowchart you'd draw on a whiteboard:

┌───────────┐
│ Start │
└─────┬─────┘


┌─────────────┐ open ┌───────────────┐
│ Check Hours │────────────▶│ Reception │
│ [Schedule] │ │ [InternalDial]│
└──────┬──────┘ └───────┬───────┘
│ │
│ closed timeout
│ │
└───────────┬────────────────┘


┌───────────┐
│ Voicemail │
└───────────┘

In this example:

  1. Every call starts at the "Check Hours" schedule node
  2. If the schedule is open, the call rings the reception extension
  3. If reception doesn't answer (timeout), or if the schedule is closed, the call routes to voicemail

Node Types

Schedule Node

Routes calls based on whether a schedule is currently open, closed, or on holiday.

Exits:

  • open — Schedule is currently within business hours
  • closed — Schedule is outside business hours
  • holiday — Current date falls within a holiday range

Internal Dial Node

Dials a user or nested dial plan and routes based on the outcome.

Configuration:

  • target_id — ID of the user, ring group, or dial plan to dial
  • timeout — How long to ring before giving up (0-300 seconds, default 30)

Exits:

  • next — Ring timed out or user was busy (call continues to next node)
  • (answered) — If answered, the dial plan ends and the call is connected

Creating a Dial Plan

const dialPlan = await dialstack.dialPlans.create(
{
name: 'Main Line Routing',
entry_node: 'check_hours',
nodes: [
{
id: 'check_hours',
type: 'schedule',
config: {
schedule_id: 'sched_01h2xcejqtf2nbrexx3vqjhp50',
open: 'reception',
closed: 'voicemail',
holiday: 'voicemail',
},
},
{
id: 'reception',
type: 'internal_dial',
config: {
target_id: 'user_01h2xcejqtf2nbrexx3vqjhp45',
timeout: 30,
next: 'voicemail',
},
},
{
id: 'voicemail',
type: 'internal_dial',
config: {
target_id: 'user_01h2xcejqtf2nbrexx3vqjhp99',
},
},
],
},
{ dialstackAccount: 'acct_01h2xcejqtf2nbrexx3vqjhp41' }
);

Key Concepts

Entry Node

The entry_node specifies which node executes first. Think of it as where the "Start" arrow points in your flowchart.

Exit Targets

Each node type has specific exits that route to other nodes. Set an exit to null (or omit it) to terminate the call at that point.

Node IDs

Node IDs are strings you define (like "check_hours" or "reception"). They must be unique within a dial plan and are used to wire nodes together.

Visual Position

Nodes can include optional position coordinates (x, y) for rendering in a visual editor. If omitted, nodes are auto-positioned.

Examples

After-Hours Voicemail

Route calls to voicemail when closed:

Start → Check Hours [Schedule] → (open) → Ring Group [Internal Dial]
→ (closed/holiday) → Voicemail
{
"name": "After-Hours Voicemail",
"entry_node": "check_hours",
"nodes": [
{
"id": "check_hours",
"type": "schedule",
"config": {
"schedule_id": "sched_...",
"open": "ring_group",
"closed": "voicemail",
"holiday": "voicemail"
}
},
{
"id": "ring_group",
"type": "internal_dial",
"config": {
"target_id": "user_...",
"next": "voicemail"
}
},
{
"id": "voicemail",
"type": "internal_dial",
"config": {
"target_id": "user_..."
}
}
]
}

Multi-Level Routing

Chain multiple schedule checks:

Start → Check Emergency [Schedule] → (open) → Emergency Line [Internal Dial]
→ (closed/holiday) → Check Hours [Schedule] → (open) → Reception [Internal Dial]
→ (closed/holiday) → Voicemail
{
"name": "Multi-Level Routing",
"entry_node": "check_emergency",
"nodes": [
{
"id": "check_emergency",
"type": "schedule",
"config": {
"schedule_id": "sched_emergency_...",
"open": "emergency_line",
"closed": "check_hours",
"holiday": "check_hours"
}
},
{
"id": "emergency_line",
"type": "internal_dial",
"config": {
"target_id": "user_emergency_..."
}
},
{
"id": "check_hours",
"type": "schedule",
"config": {
"schedule_id": "sched_business_...",
"open": "reception",
"closed": "voicemail",
"holiday": "voicemail"
}
},
{
"id": "reception",
"type": "internal_dial",
"config": {
"target_id": "user_reception_...",
"next": "voicemail"
}
},
{
"id": "voicemail",
"type": "internal_dial",
"config": {
"target_id": "user_voicemail_..."
}
}
]
}

Fallback Chain

Try multiple users before voicemail:

Start → Reception [Internal Dial] → (timeout 30s) → Manager [Internal Dial] → (timeout 20s) → Voicemail
{
"name": "Fallback Chain",
"entry_node": "reception",
"nodes": [
{
"id": "reception",
"type": "internal_dial",
"config": {
"target_id": "user_reception_...",
"timeout": 30,
"next": "manager"
}
},
{
"id": "manager",
"type": "internal_dial",
"config": {
"target_id": "user_manager_...",
"timeout": 20,
"next": "voicemail"
}
},
{
"id": "voicemail",
"type": "internal_dial",
"config": {
"target_id": "user_voicemail_..."
}
}
]
}

API Reference

  • Dial Plans — Create, update, and delete dial plans
  • Schedules — Define business hours for schedule nodes