Skip to navigation

dial

View as MarkdownOpen in Claude

Initiate an outbound call. Sends a calling.dial JSON-RPC request and waits for the server to return a calling.call.dial event confirming the call was answered or failed. Returns a fully-initialized Call object with valid call_id and node_id.

The devices parameter supports both serial and parallel dialing strategies. Each inner list represents a set of devices to ring simultaneously (parallel). The outer list represents sequential attempts — if the first group fails, the next group is tried.

Raises RelayError if the dial fails or if no answer is received within the dial_timeout period. The default timeout is 120 seconds.

Parameters

devices
list[list[dict[str, Any]]]Required

Nested array of device definitions for serial and parallel dialing. Each device is a dict with type and params keys.

  • Serial dial (try one after another): each inner list has one device
  • Parallel dial (ring simultaneously): one inner list with multiple devices

Up to 20 devices are dialed in total, counted across all inner lists rather than per list. Any device after the 20th is skipped.

devices[][].type
strRequired

Device type. Valid values:

  • "phone" — PSTN phone number
  • "sip" — SIP endpoint
devices[][].params
dictRequired

Device-specific parameters.

devices[][].params.to_number
strRequired

Destination phone number in E.164 format (for "phone" type).

devices[][].params.from_number
strRequired

Caller ID phone number in E.164 format (for "phone" type).

devices[][].params.timeout
int

Per-device ring timeout in seconds.

tag
str | NoneDefaults to None

Client-provided correlation tag for event matching. Auto-generated as a UUID if not supplied.

max_duration
int | NoneDefaults to None

Maximum call duration in seconds. The call is automatically ended when this limit is reached.

dial_timeout
float | NoneDefaults to 120.0

How long in seconds to wait for the dial to complete (answer or failure) before raising a timeout error.

Returns

Call — A call object with all properties populated and ready for call control operations.

Examples

Simple outbound call

import asyncio
from signalwire.relay import RelayClient
client = RelayClient(
project="your-project-id",
token="your-api-token",
contexts=["default"],
)
async def main():
async with client:
call = await client.dial(
devices=[[{
"type": "phone",
"params": {
"from_number": "+15551234567",
"to_number": "+15559876543",
"timeout": 30,
},
}]],
)
action = await call.play([{"type": "tts", "params": {"text": "Hello!"}}])
await action.wait()
await call.hangup()
asyncio.run(main())

Serial dial (failover)

import asyncio
from signalwire.relay import RelayClient
client = RelayClient(
project="your-project-id",
token="your-api-token",
contexts=["default"],
)
async def main():
async with client:
# Try the first number, then fall back to the second
call = await client.dial(
devices=[
[{"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}}],
[{"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}}],
],
)
asyncio.run(main())

Parallel dial (ring all)

import asyncio
from signalwire.relay import RelayClient
client = RelayClient(
project="your-project-id",
token="your-api-token",
contexts=["default"],
)
async def main():
async with client:
# Ring both numbers simultaneously, first to answer wins
call = await client.dial(
devices=[[
{"type": "phone", "params": {"to_number": "+15551111111", "from_number": "+15550000000"}},
{"type": "phone", "params": {"to_number": "+15552222222", "from_number": "+15550000000"}},
]],
)
asyncio.run(main())