Call Methods Reference
A Call object represents a live phone call. You get one from @client.on_call (inbound) or client.dial() (outbound).
Properties
| Property | Type | Description |
|----------|------|-------------|
| call_id | str | Unique call identifier |
| node_id | str | Server node handling the call |
| state | str | Current state: created, ringing, answered, ending, ended |
| direction | str | inbound or outbound |
| tag | str | Correlation tag |
| device | dict | Device info (type, params) |
| segment_id | str | Segment identifier |
Actions: Blocking vs Fire-and-Forget
Methods like play(), record(), detect(), etc. return Action objects. The await call.play(...) itself only waits for the server to accept the command — the actual operation runs asynchronously on the server. You choose how to handle completion:
Wait inline (blocking)
action = await call.play([{"type": "tts", "params": {"text": "Hello"}}])
await action.wait() # blocks until playback finishes
# execution continues only after play is done
Fire and forget (background)
action = await call.play([{"type": "tts", "params": {"text": "Hello"}}])
# don't call action.wait() — continue immediately while audio plays
await call.send_digits("1234")
# check later if needed
if action.is_done:
print(f"Play result: {action.result}")
Fire with callback
# Sync callback
action = await call.play(
[{"type": "tts", "params": {"text": "Hello"}}],
on_completed=lambda event: print(f"Done: {event.params}"),
)
# continues immediately; callback fires when playback finishes
# Async callback
async def on_recording_done(event):
print(f"Recording URL: {event.params.get('url')}")
await call.hangup()
action = await call.record(on_completed=on_recording_done)
The on_completed callback is available on all action-based methods: play, record, play_and_collect, collect, detect, pay, send_fax, receive_fax, tap, stream, transcribe, and ai. It accepts both sync and async functions. Errors in callbacks are caught and logged, never crash the event loop. The callback also fires when the call is gone (404/410).
Action methods summary
| Method | Returns |
|--------|---------|
| action.wait(timeout=None) | Blocks until the action completes, returns the terminal RelayEvent |
| action.is_done | True if the action has completed |
| action.result | The terminal RelayEvent (or None if not done) |
| action.completed | True if the action reached a terminal state |
| action.stop() | Stop the operation on the server |
Some actions also have pause(), resume(), and volume().
Lifecycle
answer(**kwargs) -> dict
Answer an inbound call.
await call.answer()
hangup(reason="hangup") -> dict
End the call.
await call.hangup()
await call.hangup(reason="busy")
pass_() -> dict
Decline control, returning the call to routing.
await call.pass_()
Audio Playback
play(media, *, volume=None, direction=None, loop=None, control_id=None) -> PlayAction
Play audio. Returns a PlayAction with stop(), pause(), resume(), volume(), and wait().
# TTS
action = await call.play([{"type": "tts", "params": {"text": "Hello!"}}])
await action.wait()
# Audio file
action = await call.play([{"type": "audio", "params": {"url": "https://example.com/sound.mp3"}}])
# Silence
action = await call.play([{"type": "silence", "params": {"duration": 2}}])
# Ringtone
action = await call.play([{"type": "ringtone", "params": {"name": "us"}}])
# Control playback
await action.pause()
await action.resume()
await action.volume(-3.0)
await action.stop()
Recording
record(audio=None, *, control_id=None) -> RecordAction
Record the call. Returns a RecordAction with stop(), pause(), resume(), and wait().
action = await call.record(audio={"format": "wav", "stereo": True, "direction": "both"})
# ... later ...
await action.stop()
event = await action.wait()
print(f"Recording URL: {event.params.get('url')}")
Input Collection
play_and_collect(media, collect, *, volume=None, control_id=None) -> CollectAction
Play audio and collect DTMF or speech input. Returns a CollectAction.
action = await call.play_and_collect(
[{"type": "tts", "params": {"text": "Press 1 for sales, 2 for support."}}],
{"digits": {"max": 1, "digit_timeout": 5.0}},
)
event = await action.wait()
digit = event.params.get("result", {}).get("params", {}).get("digits", "")
collect(*, digits=None, speech=None, ..., control_id=None) -> StandaloneCollectAction
Collect input without playing audio.
action = await call.collect(
digits={"max": 4, "terminators": "#"},
speech={"language": "en-US"},
partial_results=True,
)
event = await action.wait()
Bridging
connect(devices, *, ringback=None, tag=None, max_duration=None, max_price_per_minute=None, status_url=None) -> dict
Bridge the call to another destination.
await call.connect(
[[{"type": "phone", "params": {"to_number": "+15551234567", "from_number": "+15559876543"}}]],
ringback=[{"type": "ringtone", "params": {"name": "us"}}],
)
disconnect() -> dict
Unbridge a connected call.
await call.disconnect()
DTMF
send_digits(digits, *, control_id=None) -> dict
Send DTMF tones.
await call.send_digits("1234#")
Detection
detect(detect, *, timeout=None, control_id=None) -> DetectAction
Detect machine, fax, or digits.
action = await call.detect({"type": "machine"}, timeout=30.0)
event = await action.wait()
SIP Refer
refer(device, *, status_url=None) -> dict
Transfer via SIP REFER.
await call.refer({"type": "sip", "params": {"to": "sip:user@example.com"}})
Transfer
transfer(dest) -> dict
Transfer call control to another RELAY app or SWML script.
await call.transfer("https://example.com/swml-endpoint")
Fax
send_fax(document, *, identity=None, header_info=None, control_id=None) -> FaxAction
action = await call.send_fax("https://example.com/document.pdf", identity="+15551234567")
event = await action.wait()
receive_fax(*, control_id=None) -> FaxAction
action = await call.receive_fax()
event = await action.wait()
Tap (Media Interception)
tap(tap, device, *, control_id=None) -> TapAction
Intercept call media and stream to an RTP endpoint.
action = await call.tap(
{"type": "audio", "params": {"direction": "both"}},
{"type": "rtp", "params": {"addr": "192.168.1.100", "port": 5000}},
)
Streaming
stream(url, *, name=None, codec=None, track=None, control_id=None, ...) -> StreamAction
Stream call audio to a WebSocket endpoint.
action = await call.stream(
"wss://example.com/audio",
name="my_stream",
codec="PCMU",
track="inbound_track",
)
# Stop streaming
await action.stop()
Payment
pay(payment_connector_url, *, control_id=None, charge_amount=None, currency=None, ...) -> PayAction
Collect a payment via DTMF.
action = await call.pay(
"https://pay.example.com",
charge_amount="25.99",
currency="usd",
input_method="dtmf",
)
event = await action.wait()
Conference
join_conference(name, *, muted=None, beep=None, max_participants=None, record=None, ...) -> dict
await call.join_conference("my_conference", muted=False, beep="onEnter")
leave_conference(conference_id) -> dict
await call.leave_conference("conf-123")
Hold
hold() -> dict / unhold() -> dict
await call.hold()
# ... later ...
await call.unhold()
Denoise
denoise() -> dict / denoise_stop() -> dict
await call.denoise()
# ... later ...
await call.denoise_stop()
Transcription
transcribe(*, control_id=None, status_url=None) -> TranscribeAction
action = await call.transcribe(status_url="https://example.com/transcription")
# ... later ...
await action.stop()
Live Transcribe / Translate
live_transcribe(action_obj) -> dict
await call.live_transcribe({"start": {"language": "en-US"}})
live_translate(action_obj, *, status_url=None) -> dict
await call.live_translate({"start": {"source": "en-US", "target": "es"}})
Echo
echo(*, timeout=None, status_url=None) -> dict
Echo audio back to the caller (useful for testing).
await call.echo(timeout=30.0)
AI Agent
ai(*, control_id=None, prompt=None, SWAIG=None, ai_params=None, ...) -> AIAction
Start an AI agent session on the call.
action = await call.ai(
prompt={"text": "You are a helpful support agent."},
SWAIG={"functions": [...]},
ai_params={"end_of_speech_timeout": 3000},
)
event = await action.wait()
amazon_bedrock(*, prompt=None, SWAIG=None, ...) -> dict
Connect to an Amazon Bedrock AI agent.
ai_message(*, message_text=None, role=None, ...) -> dict
Send a message to an active AI session.
ai_hold(*, timeout=None, prompt=None) -> dict / ai_unhold(*, prompt=None) -> dict
Put an AI session on/off hold.
Rooms
join_room(name, *, status_url=None) -> dict
await call.join_room("my_room")
leave_room() -> dict
await call.leave_room()
Queue
queue_enter(queue_name, *, control_id=None, status_url=None) -> dict
await call.queue_enter("support")
queue_leave(queue_name, *, control_id=None, queue_id=None, status_url=None) -> dict
await call.queue_leave("support", queue_id="q-123")
Digit Bindings
bind_digit(digits, bind_method, *, bind_params=None, realm=None, max_triggers=None) -> dict
Bind a DTMF sequence to trigger a RELAY method.
await call.bind_digit(
"*1",
"calling.play",
bind_params={"play": [{"type": "tts", "params": {"text": "You pressed star-1"}}]},
)
clear_digit_bindings(*, realm=None) -> dict
await call.clear_digit_bindings()
User Events
user_event(*, event=None, **kwargs) -> dict
Send a custom event.
await call.user_event(event="order_placed", order_id="12345")
Event Handling
on(event_type, handler)
Register an event listener on this call.
def on_play(event):
print(f"Play state: {event.params.get('state')}")
call.on("calling.call.play", on_play)
wait_for(event_type, predicate=None, timeout=None) -> RelayEvent
Wait for a specific event.
event = await call.wait_for("calling.call.play", timeout=30.0)
wait_for_ended(timeout=None) -> RelayEvent
Wait for the call to end.
event = await call.wait_for_ended()
print(f"End reason: {event.params.get('end_reason')}")