Relay SDK for Python
Getting Started
The Relay SDK for Python enables developers to connect and use SignalWire's Relay APIs within their own Python code. Our Relay SDK allows developers to build or add robust and innovative communication services to their applications.
The Relay SDK for Python is easy to use and only takes a few minute to setup and get running.
Source Code: signalwire/signalwire-python
Support: SignalWire Community Slack Channel
Installation
Install the package using either pip
or pipenv
:
Using
pip
pip install signalwire
Using
pipenv
pipenv install signalwire
Minimum Requirements
The Python SDK is build on top of asyncio and requires at least Python 3.6 to be run.
We suggest to use Python 3.7 or above.
Using the SDK
The Python SDK can be used to get up and running with Relay quickly and easily. In order to use the SDK, you must get your project and token from your SignalWire dashboard.
There are a few ways to get started, depending on your needs: Relay.Consumer
, Relay.Task
and Relay.Client
.
Relay Consumer
A Relay.Consumer
creates a long running process, allowing you to respond to incoming requests and events in realtime. Relay Consumers abstract all the setup of connecting to Relay and automatically dispatches workers to handle requests; so you can concentrate on writing your code without having to worry about multi-threading or blocking, everything just works. Think of Relay Consumers like a background worker system for all your calling and messaging needs.
Relay Consumers can scale easily, simply by running multiple instances of your Relay.Consumer
process. Each event will only be delivered to a single consumer, so as your volume increases, just scale up! This process works well whether you are using Docker Swarm, a Procfile on Heroku, your own webserver, and most other environments.
Setting up a new consumer is the easiest way to get up and running.
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['home', 'office']
async def ready(self):
# Consumer is successfully connected with Relay.
# You can make calls or send messages here..
async def on_incoming_call(self, call):
result = await call.answer()
if result.successful:
print('Call answered..')
# Run your consumer..
consumer = CustomConsumer()
consumer.run()
Learn more about Relay Consumers
Relay Task
A Relay.Task
is simple way to send jobs to your Relay.Consumers
from a short lived process, like a web framework. Relay Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a Relay Task as a way to queue a job for your background workers to processes asynchronously.
For example, if you wanted to make an outbound call and play a message when your user clicks a button on your web application, since Relay is a realtime protocol and relies on you to tell it what to do in realtime, if you did this within your web application, your web server would block until the call was finished... this may take a long time! Instead, simply create a new Relay Task. This task will be handled by a running Relay Consumer process and your web application can respond back to your user immediately.
Send a task in the
office
context with custom data.
# create-task.py
from signalwire.relay.task import Task
project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
task = Task(project=project, token=token)
success = task.deliver('office', {
'uuid': 'unique id',
'data': 'data for your job'
})
if success:
print('Task delivered')
else:
print('Error delivering task..')
Handle the task in a Consumer.
# consumer-task.py
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def on_task(self, message):
print('Handle inbound task')
print(message['uuid']) # => 'unique id'
print(message['data']) # => 'data for your job'
consumer = CustomConsumer()
consumer.run()
Relay Client
Relay.Client
is a lower level object, giving you a basic connection to Relay but that is all. It is best used when you are creating a script only concerned with sending outbound requests or you want complete control over the Relay connection yourself.
Setting up a new client and make an outbound call.
from signalwire.relay.client import Client
async def ready(client):
call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY')
result = await call.dial()
if result.successful:
print('Your call has been answered..')
project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
client = Client(project=project, token=token)
client.on('ready', ready)
client.connect()
Learn more about Relay Clients
Contexts
Relay uses Contexts as a simple way to separate events to specific consumers, allowing you to write consumers for specific types of calls or messages or scale them independently. A Context is simply a named string, that allows you to categorize requests. When creating outbound requests, or configuring phone numbers for inbound requests, you can specify the context; Relay will then deliver that call or event to Consumers that are configured to listen for that context.
For example, you could have a customer support phone number configured to send to Relay with the support
context, and a personal number configured with personal
context. Relay would deliver these events to any Consumer listening for those contexts. This gives you a lot of control in how messages are delivered to your Consumers, allowing you to write Consumer classes specific to the context, scale them independently, or separate traffic based on your own business rules.
API Reference
Relay.Client
Relay.Client
is the basic connection to Relay, allowing you send commands to Relay and setup handlers for inbound events.
Constructor
Constructs a client object to interact with Relay.
Parameters
project |
string | required | Project ID from your SignalWire Space |
token |
string | required | Token from your SignalWire Space |
Examples
Create a Client to interact with the Relay API.
from signalwire.relay.client import Client
client = Client(project='<project-id>', token='<project-token>')
Properties
connected |
boolean | Returns true if the client is connected to Relay. |
calling |
Relay.Calling |
Returns a Relay.Calling instance associated with the client. |
tasking |
Relay.Tasking |
Returns a Relay.Tasking instance associated with the client. |
messaging |
Relay.Messaging |
Returns a Relay.Messaging instance associated with the client. |
Methods
connect
Activates the connection to the Relay API. The connection to Relay does not happen automatically so that you can setup handlers to events that might occur before the connection is successfully established.
Available In:
Returns
None
Examples
# Make sure you have attached the listeners you need before connecting the client, or you might miss some events.
client.connect()
disconnect
Coroutine that close the Relay connection, cancel the pending tasks and stop the event loop.
Available In:
Returns
awaitable
- A coroutine object.
Examples
Within an
async
function
import asyncio
# with a 'client' variable already created..
async def sleep_and_disconnect():
await asyncio.sleep(5)
await client.disconnect()
print('Client disconnected!')
asyncio.run(sleep_and_disconnect())
Scheduling a new asyncio task.
import asyncio
# schedule a task to disconnect the client..
asyncio.create_task(client.disconnect())
on
Attach an event handler for a specific type of event. The handler could be a coroutine or a normal function.
Available In:
Parameters
event |
string | required | Event name. Full list of events Relay.Client Events |
handler |
function | required | Function to call when the event comes. |
Returns
Relay.Client
- The client object itself.
Examples
Subscribe to the
ready
event.
def do_something(client):
pass
client.on('ready', do_something)
off
Remove an event handler that were attached with .on()
. If no handler
parameter is passed, all listeners for that event
will be removed.
Parameters
event |
string | required | Event name. Full list of events Relay.Client Events |
handler |
function | optional | Function to remove. Note: handler will be removed from the stack by reference so make sure to use the same reference in both .on() and .off() methods. |
Returns
Relay.Client
- The client object itself.
Examples
Subscribe to the
ready
event and then, remove the handler.
def do_something(client):
pass
client.on('ready', do_something)
# .. later
client.off('ready', do_something)
Events
All available events you can attach a listener on.
ready |
The session has been established and all other methods can now be used. |
signalwire.socket.open |
The websocket is open. However, you have not yet been authenticated. |
signalwire.socket.error |
The websocket gave an error. |
signalwire.socket.message |
The client has received a message from the websocket. |
signalwire.socket.close |
The websocket is closing. |
Relay.Calling
This represents the API interface for the Calling Relay Service. This object is used to make requests related to managing end to end calls.
Methods
dial
Make an outbound Call and waits until it has been answered or hung up.
Available In:
Parameters
call_type |
string | optional | The type of call. Default to phone as it is the only supported for now. |
from_number |
string | required | The party the call is coming from. Must be a SignalWire number or SIP endpoint that you own. |
to_number |
string | required | The party you are attempting to call. |
timeout |
number | optional | The time, in seconds, the call will ring before going to voicemail. |
Returns
coroutine
- Coroutine object that will be fulfilled with a Relay.Calling.DialResult
object.
Examples
Make an outbound Call and print the call object if it was answered.
async def ready(client):
result = await client.calling.dial(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY')
if result.successful:
# Call has been answered and is now active. Use 'result.call' to access the Call object.
print(result.call)
else:
print('Call failed or not answered.')
newCall
Create a new Call
object. The call has not started yet allowing you to attach event listeners on it.
Available In:
Parameters
See Relay.Calling.Dial
for the parameter list.
Returns
Call
- A new Relay.Calling.Call
object.
Examples
Create a new Call object.
call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY', timeout=30)
# Use the call object..
Relay.Calling.AnswerResult
This object is returned by the answer
method.
Properties
successful |
boolean | Whether the call has been answered from the remote party. |
event |
Relay.Event |
Last event that completed the operation. |
Relay.Calling.Call
All calls in SignalWire have a common generic interface, Call
. A Call
is a connection between SignalWire and another device.
Properties
id |
string | The unique identifier of the call. |
call_type |
string | The type of call. Only phone is currently supported. |
from_number |
string | The phone number that the call is coming from. |
to_number |
string | The phone number you are attempting to call. |
timeout |
number | The seconds the call rings before being transferred to voicemail. |
state |
string | The current state of the call. See Relay.Calling.Call State Events for all the possible call states. |
prev_state |
string | The previous state of the call. |
context |
string | The context the call belongs to. |
active |
boolean | Whether the call is active. |
ended |
boolean | Whether the call has ended. |
answered |
boolean | Whether the call has been answered. |
failed |
boolean | Whether the call has failed. |
busy |
boolean | Whether the call was busy. |
Methods
amd
Alias for detect_answering_machine
.
amd_async
Alias for detect_answering_machine_async
.
answer
Answer an inbound call.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.AnswerResult
object.
Examples
Answer an inbound call and check if it was successful.
result = await call.answer()
if result.successful:
print('Call answered..')
else:
print('Call failed or not answered.'
connect
Attempt to connect an existing call to a new outbound call and waits until one of the remote party picks the call or the connect fails.
This method involves complex nested parameters.
You can connect to multiple devices in series, parallel, or any combination of both with creative use of the parameters. Series implies one device at a time, while parallel implies multiple devices at the same time.
Available In:
Parameters
device_list |
list | required | List or nested list of dict with the following structure: Nested depends on whether to dial in serial or parallel. |
call_type |
string | optional | The device type. Only phone is currently supported and is the default. |
from_number |
string | optional | The party the call is coming from. If not provided, the SDK will use the from_number of the originator call.Must be a SignalWire number or SIP endpoint that you own. |
to_number |
string | required | The party you are attempting to connect with. |
timeout |
number | optional | The time, in seconds, the call will ring before going to voicemail. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.ConnectResult
object.
Examples
Trying to connect a call by calling in series
+18991114444
and+18991114445
.
devices = [
{ 'to_number': '+18991114444', 'timeout': 10 },
{ 'to_number': '+18991114445', 'timeout': 20 }
]
result = await call.connect(device_list=devices)
if result.successful:
# result.call is the remote leg connected with yours
remote_call = result.call
Combine serial and parallel calling. Call
+18991114443
first and - if it doesn't answer - try calling in parallel+18991114444
and+18991114445
. If none of the devices answer, continue the same process with+18991114446
and+18991114447
.
devices = [
{ 'to_number': '+18991114443', 'timeout': 30 },
[
{ 'to_number': '+18991114444', 'timeout': 30 },
{ 'to_number': '+18991114445', 'timeout': 20 }
],
[
{ 'to_number': '+18991114446', 'timeout': 30 },
{ 'to_number': '+18991114447', 'timeout': 20 }
]
]
result = await call.connect(device_list=devices)
if result.successful:
# result.call is the remote leg connected with yours.
remote_call = result.call
connect_async
Asynchronous version of connect
. It does not wait the connect to completes or fails but returns a Relay.Calling.ConnectAction
you can interact with.
Available In:
Parameters
See connect
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.ConnectAction
object.
Examples
Trying to connect a call by calling in series
+18991114444
and+18991114445
.
devices = [
{ 'to_number': '+18991114444', 'timeout': 10 },
{ 'to_number': '+18991114445', 'timeout': 20 }
]
action = await call.connect_async(device_list=devices)
# .. do other important things while Relay try to connect your call..
# .. check whether the action has completed
if action.completed:
# Your call is now connected with a remote peer
detect
Start a detector on the call and waits until it has finished or failed.
The detect
method is a generic method for all types of detecting, see detect_answering_machine
, detect_digit
or detect_fax
for more specific usage.
Available In:
Parameters
- To detect an answering machine:
detect_type |
string | required | machine |
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
wait_for_beep |
boolean | optional | Whether to wait until the AM is ready for voicemail delivery. Defaults to false. |
initial_timeout |
number | optional | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. |
end_silence_timeout |
number | optional | Number of seconds to wait for voice to finish. Defaults to 1.0. |
machine_voice_threshold |
number | optional | How many seconds of voice to decide is a machine. Defaults to 1.25. |
machine_words_threshold |
number | optional | How many words to count to decide is a machine. Defaults to 6. |
- To detect digits:
detect_type |
string | required | digit |
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
digits |
string | optional | The digits to detect. Defaults to "0123456789#*". |
- To detect a fax:
detect_type |
string | required | fax |
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
tone |
string | optional | The fax tone to detect: CED or CNG .Defaults to "CED". |
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectResult
object.
Examples
Detect a machine with custom parameters and timeout.
result = await call.detect(detect_type='machine', timeout=45, initial_timeout=3)
if result.successful:
print(f'Detector Result: {result.result}')
Detect a Fax setting timeout only.
result = await call.detect(detect_type='fax', timeout=45)
if result.successful:
print(f'Detector Result: {result.result}')
detect_async
Asynchronous version of detect
. It does not wait the detector ends but returns a Relay.Calling.DetectAction
you can interact with.
Available In:
Parameters
See detect
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectAction
object.
Examples
Detect all the digits using default parameters. Stop the action after 5 seconds.
import asyncio # to use sleep
action = await call.detect_async(detect_type='digit')
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
detect_answering_machine
This is a helper function that refines the use of detect
. The coroutine will return a Relay.Calling.DetectResult
object as soon as the detector decided who answered the call: MACHINE
, HUMAN
or UNKNOWN
.
Available In:
Parameters
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
wait_for_beep |
boolean | optional | Whether to wait until the AM is ready for voicemail delivery. Defaults to false. |
initial_timeout |
number | optional | Number of seconds to wait for initial voice before giving up. Defaults to 4.5. |
end_silence_timeout |
number | optional | Number of seconds to wait for voice to finish. Defaults to 1.0. |
machine_voice_threshold |
number | optional | How many seconds of voice to decide is a machine. Defaults to 1.25. |
machine_words_threshold |
number | optional | How many words to count to decide is a machine. Defaults to 6. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectResult
object.
Examples
Perform an AMD and wait until the machine is ready.
result = await call.detect_answering_machine(wait_for_beep=True)
if result.successful:
print(f'AMD result: {result.result}') # MACHINE || HUMAN || UNKNOWN
detect_answering_machine_async
Asynchronous version of detect_answering_machine
. It does not wait the detector ends but returns a Relay.Calling.DetectAction
you can interact with.
Available In:
Parameters
See detect_answering_machine
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectAction
object.
Examples
Perform an asynchronous AMD on the call. Then stop the action if not completed yet.
action = await call.detect_answering_machine_async()
# Do other things while detector runs and then stop it...
if action.completed:
detect_result = action.result.result # MACHINE || HUMAN || UNKNOWN
await action.stop()
detect_digit
This is a helper function that refines the use of detect
. This simplifies detecting digits on a call.
Available In:
Parameters
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
digits |
string | optional | The digits to detect. Defaults to "0123456789#*". |
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectResult
object.
Examples
Detect digits and then write a log with the result.
result = await call.detect_digit()
if result.successful:
print(f'Digits detected: {result.result}')
detect_digit_async
Asynchronous version of detect_digit
. It does not wait the detector ends but returns a Relay.Calling.DetectAction
you can interact with.
Available In:
Parameters
See detect_digit
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectAction
object.
Examples
Detect only
1-3
digits. Stop the action after 5 seconds.
import asyncio # to use sleep
action = await call.detect_digit_async(digits='123')
await asyncio.sleep(5)
await action.stop()
detect_fax
This is a helper function that refines the use of detect
. This simplifies detecting a fax
.
Available In:
Parameters
timeout |
number | optional | Number of seconds to run the detector. Defaults to 30.0. |
tone |
string | optional | The fax tone to detect: CED or CNG .Defaults to "CED". |
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectResult
object.
Examples
Detect fax on the current call.
result = await call.detect_fax()
if result.successful:
# A fax has been detected!
detect_fax_async
Asynchronous version of detect_fax
. It does not wait the detector ends but returns a Relay.Calling.DetectAction
you can interact with.
Available In:
Parameters
See detect_fax
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.DetectAction
object.
Examples
Detect fax on the current call. Stop the action after 5 seconds.
import asyncio # to use sleep
action = await call.detect_fax_async()
await asyncio.sleep(5)
await action.stop()
dial
This will start a call that was created with new_call
and waits until the Call has been answered or hung up.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.DialResult
object.
Examples
call = client.calling.new_call(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY')
result = await call.dial()
if result.successful:
print('Call answered..')
else:
print('Call failed or not answered.')
fax_receive
Prepare the call to receive an inbound fax. It waits until the fax has been received or failed.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.FaxResult
object.
Examples
Receiving a fax on the call and grab URL and number of received pages from the FaxResult object
result = await call.fax_receive()
if result.successful:
url = result.document # URL location of the document
num_pages = result.pages
fax_receive_async
Asynchronous version of fax_receive
. It does not wait the fax to be received but returns a Relay.Calling.FaxAction
you can interact with.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.FaxAction
object.
Examples
Trying to receive a fax. Stop the attempt after 5 seconds.
import asyncio # to use sleep
action = await call.fax_receive_async()
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
fax_send
Send a Fax
through the call. It waits until the fax has been sent or failed.
Available In:
Parameters
document |
string | required | Http(s) URL to the document to send. PDF format only. |
identity |
string | optional | Identity to display on receiving fax. Defaults to SignalWire DID. |
header |
string | optional | Custom string to add to header of each fax page. Set to empty string to disable sending any header. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.FaxResult
object.
Examples
Sending a fax on the call and grab URL and number of received pages from the FaxResult object
result = await call.fax_send(url='https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', header='Custom Header')
if result.successful:
url = result.document # URL location of the document
num_pages = result.pages
fax_send_async
Asynchronous version of fax_send
. It does not wait the fax to be sent but returns a Relay.Calling.FaxAction
you can interact with.
Available In:
Parameters
See fax_send
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.FaxAction
object.
Examples
Trying to send a fax. Stop sending it after 5 seconds.
import asyncio # to use sleep
action = await call.fax_send_async(url='https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', header='Custom Header')
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
hangup
Hangup the call.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.HangupResult
object.
Examples
Hangup a call and check if it was successful.
result = await call.hangup()
if result.successful:
print('Call hanged up..')
on
Attach an event handler for the event
.
Available In:
Parameters
event |
string | required | Event name. Full list of events Relay.Calling.Call events |
callback |
function | required | Function to call when the event comes. |
Returns
Relay.Calling.Call
- The call object itself.
Examples
Subscribe to the
answered
events for a given call.
def on_answered():
# Call has been answered from the remote party!
call.on('answered', on_answered)
off
Remove an event handler that were attached with .on()
. If you don't pass a callback, all listeners for that event
will be removed.
Available In:
Parameters
event |
string | required | Event name. Full list of events Relay.Calling.Call events |
callback |
function | optional | Function to remove. Note: callback will be removed from the stack by reference so make sure to use the same reference in both .on() and .off() methods. |
Returns
Relay.Calling.Call
- The call object itself.
Examples
Subscribe to the call
ended
state change and then, remove the event handler.
def on_ended():
pass
call.on('ended', on_ended)
# .. later
call.off('ended', on_ended)
play
Play one or multiple media in a Call and waits until the playing has ended.
The play
method is a generic method for all types of playing, see play_audio
, play_silence
or play_tts
for more specific usage.
Available In:
Parameters
media_list |
list | required | List of media to play. See below for each type. |
volume |
float | optional | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0 . |
- To play an audio file:
type |
string | required | audio |
url |
string | required | Http(s) URL to audio resource to play. |
- To play a text to speech string:
type |
string | required | tts |
text |
string | required | TTS to play. |
language |
string | optional | Default to en-US . |
gender |
string | optional | male or female . Default to female . |
- To play silence:
type |
string | required | silence |
duration |
number | required | Seconds of silence to play. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResult
object.
Examples
Play multiple media elements in the call.
media_list = [
{ 'type': 'tts', 'text': 'Listen this awesome file!' },
{ 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' },
{ 'type': 'silence', 'duration': 5 },
{ 'type': 'tts', 'text': 'Did you like it?' }
]
result = await call.play(media_list)
play_async
Asynchronous version of play
. It does not wait the playing to completes but returns a Relay.Calling.PlayAction
you can interact with.
Available In:
Parameters
See play
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayAction
object.
Examples
Play multiple media elements in the call and stop them after 5 seconds.
import asyncio # to use sleep
media_list = [
{ 'type': 'tts', 'text': 'Listen this awesome file!' },
{ 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' },
{ 'type': 'silence', 'duration': 5 },
{ 'type': 'tts', 'text': 'Did you like it?' }
]
action = await call.play_async(media_list)
await asyncio.sleep(5)
await action.stop()
play_audio
This is a helper function that refines the use of play
. This simplifies playing an audio file.
Available In:
Parameters
url |
string | required | Http(s) URL to audio resource to play. |
volume |
float | optional | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0 . |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResult
object.
Examples
Play an Mp3 file.
result = await call.play_audio('https://cdn.signalwire.com/default-music/welcome.mp3')
play_audio_async
Asynchronous version of play_audio
. It does not wait the playing to completes but returns a Relay.Calling.PlayAction
you can interact with.
Available In:
Parameters
See play_audio
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayAction
object.
Examples
Play an Mp3 file and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3')
await asyncio.sleep(5)
await action.stop()
play_silence
This is a helper function that refines the use of play
. This simplifies playing silence.
Available In:
Parameters
duration |
number | required | Seconds of silence to play. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResult
object.
Examples
Play silence for 10 seconds.
result = await call.play_silence(10)
play_silence_async
Asynchronous version of play_silence
. It does not wait the playing to completes but returns a Relay.Calling.PlayAction
you can interact with.
Available In:
Parameters
See play_silence
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayAction
object.
Examples
Play silence for 60 seconds then stop it after 5 seconds.
import asyncio # to use sleep
action = await call.play_silence_async(60)
await asyncio.sleep(5)
await action.stop()
play_ringtone
This is a helper function that refines the use of play
. This simplifies playing TTS.
Available In:
Parameters
name |
string | required | The name of the ringtone. See ringtones for the supported values. |
duration |
float | optional | Duration of ringtone to play. Default to 1 ringtone iteration. |
volume |
float | optional | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0 . |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResult
object.
Examples
Play a single US ringtone.
result = await call.play_ringtone(name='us')
play_ringtone_async
Asynchronous version of play_ringtone
. It does not wait the playing to completes but returns a Relay.Calling.PlayAction
you can interact with.
Available In:
Parameters
See play_ringtone
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayAction
object.
Examples
Play the US ringtone for 30 seconds but stop it after 5 seconds.
import asyncio # to use sleep
action = await call.play_ringtone_async(name='us', duration=30)
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
play_tts
This is a helper function that refines the use of play
. This simplifies playing TTS.
Available In:
Parameters
text |
string | required | TTS to play. |
language |
string | optional | Default to en-US . |
gender |
string | optional | male or female . Default to female . |
volume |
float | optional | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0 . |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResult
object.
Examples
Play TTS.
result = await call.play_tts(text='Welcome to SignalWire!', gender='male')
play_tts_async
Asynchronous version of play_tts
. It does not wait the playing to completes but returns a Relay.Calling.PlayAction
you can interact with.
Available In:
Parameters
See play_tts
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayAction
object.
Examples
Play TTS and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.play_tts_async(text='Welcome to SignalWire!', gender='male')
await asyncio.sleep(5)
await action.stop()
prompt
Play one or multiple media while collecting user's input from the call at the same time, such as digits
and speech
.
It waits until the collection succeed or timeout is reached.
The prompt
method is a generic method, see prompt_audio
, prompt_tts
or prompt_ringtone
for more specific usage.
Available In:
Parameters
prompt_type |
string | required | digits , speech or both . |
media_list |
list | required | List of media elements to play. See play parameters for the list structure. |
initial_timeout |
number | optional | Initial timeout in seconds. Default to 4 seconds. |
volume |
number | optional | Volume value between -40dB and +40dB where 0 is unchanged. Default is 0 . |
- To collect digits:
digits_max |
number | required | Max digits to collect. |
digits_terminators |
string | optional | DTMF digits that will end the recording. Default not set. |
digits_timeout |
number | optional | Timeout in seconds between each digit. |
- To collect speech:
end_silence_timeout |
number | optional | How much silence to wait for end of speech. Default to 1 second. |
speech_timeout |
number | optional | Maximum time to collect speech. Default to 60 seconds. |
speech_language |
string | optional | Language to detect. Default to en-US . |
speech_hints |
array | optional | Array of expected phrases to detect. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptResult
object.
Examples
Ask user to enter their PIN and collect the digits.
media_list = [
{ 'type': 'tts', 'text': 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' }
]
result = await call.prompt(prompt_type='digits', media_list=media_list, digits_max=4, digits_terminators='#')
if result.successful:
pin = result.result # pin entered by the user
prompt_async
Asynchronous version of prompt
. It does not wait the collection to completes but returns a Relay.Calling.PromptAction
you can interact with.
Available In:
Parameters
See prompt
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptAction
object.
Examples
Ask user to enter their PIN and collect the digits.
media_list = [
{ 'type': 'tts', 'text': 'Welcome at SignalWire. Please, enter your PIN and then # to proceed' }
{ 'type': 'audio', 'url': 'https://cdn.signalwire.com/default-music/welcome.mp3' }
]
action = await call.prompt_async(prompt_type='digits', media_list=media_list, digits_max=4, digits_terminators='#')
# .. do other important things while collecting user digits..
if action.completed:
result = action.result # => PromptResult object
prompt_audio
This is a helper function that refines the use of prompt
.
This function simplifies playing an audio file while collecting user's input from the call, such as digits
and speech
.
Available In:
Parameters
You can set all the properties that prompt
accepts replacing media_list
with:
url |
string | required | Http(s) URL to audio resource to play. |
The SDK will build the media_list for you.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptResult
object.
Examples
Collect user's digits while playing an Mp3 file.
result = await call.prompt_audio(prompt_type='digits', url='https://cdn.signalwire.com/default-music/welcome.mp3', digits_max=4)
if result.successful:
digits = result.result # digits entered by the user
prompt_audio_async
Asynchronous version of prompt_audio
. It does not wait the collection to completes but returns a Relay.Calling.PromptAction
you can interact with.
Available In:
Parameters
See prompt_audio
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptAction
object.
Examples
Ask user to enter their PIN and collect the digits.
action = await call.prompt_audio_async(prompt_type='digits', url='https://cdn.signalwire.com/default-music/welcome.mp3', digits_max=4)
# .. do other important things while collecting user digits..
if action.completed:
result = action.result # => PromptResult object
prompt_ringtone
This is a helper function that refines the use of prompt
.
This function simplifies playing TTS while collecting user's input from the call, such as digits
and speech
.
Available In:
Parameters
You can set all the properties that prompt
accepts replacing media_list
with:
name |
string | required | The name of the ringtone. See ringtones for the supported values. |
duration |
number | optional | Duration of ringtone to play. Default to 1 ringtone iteration. |
The SDK will build the media_list for you.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptResult
object.
Examples
Play US ringtone for 30 seconds while collect digits.
result = await call.prompt_ringtone(prompt_type='digits', name='us', duration=30, digits_max=4)
if result.successful:
digits = result.result # digits entered by the user
prompt_ringtone_async
Asynchronous version of prompt_ringtone
. It does not wait the collection to completes but returns a Relay.Calling.PromptAction
you can interact with.
Available In:
Parameters
See prompt_ringtone
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptAction
object.
Examples
Play US ringtone for 30 seconds while collect digits in asynchronous.
action = await call.prompt_ringtone_async(prompt_type='digits', name='us', duration=30, digits_max=4)
# .. do other important things while collecting user digits..
if action.completed:
result = action.result # => PromptResult object
prompt_tts
This is a helper function that refines the use of prompt
.
This function simplifies playing TTS while collecting user's input from the call, such as digits
and speech
.
Available In:
Parameters
You can set all the properties that prompt
accepts replacing media_list
with:
text |
string | required | Text-to-speech string to play. |
language |
string | optional | Default to en-US . |
gender |
string | optional | male or female . Default to female . |
The SDK will build the media_list for you.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptResult
object.
Examples
Ask user to enter their PIN and collect the digits.
result = await call.prompt_tts(prompt_type='digits', text='Please, enter your 3 digit PIN', digits_max=3)
if result.successful:
pin = result.result # PIN entered by the user
prompt_tts_async
Asynchronous version of prompt_tts
. It does not wait the collection to completes but returns a Relay.Calling.PromptAction
you can interact with.
Available In:
Parameters
See prompt_tts
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptAction
object.
Examples
Ask user to enter their PIN and collect the digits.
action = await call.prompt_tts_async(prompt_type='digits', text='Please, enter your 3 digit PIN', gender='male', digits_max=3)
# .. do other important things while collecting user digits..
if action.completed:
result = action.result # => PromptResult object
record
Start recording the call and waits until the recording ends or fails.
Available In:
Parameters
beep |
boolean | optional | Default to false . |
stereo |
boolean | optional | Default to false . |
record_format |
string | optional | mp3 or wav . Default mp3 . |
direction |
string | optional | listen , speak or both . Default to speak . |
initial_timeout |
number | optional | How long to wait in seconds until something is heard in the recording. Disable with 0 . Default 5.0 . |
end_silence_timeout |
number | optional | How long to wait in seconds until caller has stopped speaking. Disable with 0 . Default 1.0 . |
terminators |
string | optional | DTMF digits that will end the recording. Default #* . |
Returns
coroutine
- Coroutine that will return a Relay.Calling.RecordResult
object.
Examples
Start recording audio in the call for both direction in stereo mode, if successful, grab
url
,duration
andsize
from the RecordResult object.
result = await call.record(stereo=True, direction='both')
if result.successful:
print(f'Url: {result.url}')
print(f'Duration: {result.duration}')
print(f'Size: {result.size}')
record_async
Asynchronous version of record
. It does not wait the end of recording but returns a Relay.Calling.RecordAction
you can interact with.
Available In:
Parameters
See record
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.RecordAction
object.
Examples
Start recording audio in the call for both direction in stereo mode and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.record_async(stereo=True, direction='both')
await asyncio.sleep(5)
await action.stop()
send_digits
This method sends DTMF digits to the other party on the call.
Available In:
Parameters
digits |
string | required | String of DTMF digits to send. Allowed digits are 1234567890*#ABCD and wW for short and long waits. If any invalid characters are present, the entire operation is rejected. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.SendDigitsResult
object.
Examples
Send some digits.
result = await call.send_digits('123')
send_digits_async
Asynchronous version of send_digits
. It does not wait for the sending event to complete, and immediately returns a Relay.Calling.SendDigitsAction
object you can interact with.
Available In:
Parameters
See send_digits
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.SendDigitsAction
Examples
Send some digits and stop the operation after 3 seconds.
import asyncio # to use sleep
action = await call.send_digits_async('1W2W3W4w5w6W7W8W9')
await asyncio.sleep(3)
await action.stop()
tap
Intercept call media and stream it to the specify endpoint. It waits until the end of the call.
Available In:
Parameters
audio_direction |
string | required | listen what the caller hears, speak what the caller says or both . |
target_type |
string | required | Protocol to use: rtp or ws , defaults to rtp . |
target_ptime |
number | optional | Packetization time in ms. It will be the same as the tapped media if not set. |
codec |
string | optional | Codec to use. It will be the same as the tapped media if not set. |
- To
tap
through RTP:
target_addr |
string | required | RTP IP v4 address. |
target_port |
number | required | RTP port. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.TapResult
object.
Examples
Tapping audio from the call, if successful, print both source and destination devices from the
TapResult
object.
result = await call.tap(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234)
if result.successful:
# Print source and destination devices..
print(result.source_device)
print(result.destination_device)
tap_async
Asynchronous version of tap
. It does not wait the end of tapping but returns a Relay.Calling.TapAction
you can interact with.
Available In:
Parameters
See tap
for the parameter list.
Returns
coroutine
- Coroutine that will return a Relay.Calling.TapAction
object.
Examples
Tapping audio from the call and then stop it using the
TapAction
object.
import asyncio # to use sleep
action = await call.tap_async(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234)
# Do other things while tapping the media and then stop it..
await asyncio.sleep(3)
await action.stop()
wait_for
Wait for specific events on the Call or returns false
if the Call ends without getting them.
Available In:
Parameters
*events |
list of strings | required | One or more Relay.Calling.Call state events |
Returns
coroutine
- Coroutine object that will be resolved with true
or false
.
Examples
Wait for
ending
orended
events.
success = await call.waitFor('ending', 'ended')
wait_for_answered
This is a helper function that refines the use of wait_for
. This simplifies waiting for the answered state.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return true
or false
.
Examples
Wait for the
answered
event.
success = await call.wait_for_answered()
wait_for_ended
This is a helper function that refines the use of wait_for
. This simplifies waiting for the ended state.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return true
or false
.
Examples
Wait for the
ended
event.
success = await call.wait_for_ended()
wait_for_ending
This is a helper function that refines the use of wait_for
. This simplifies waiting for the ending state.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return true
or false
.
Examples
Wait for the
ending
event.
success = await call.waitForEnding()
wait_for_ringing
This is a helper function that refines the use of wait_for
. This simplifies waiting for the ringing state.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return true
or false
.
Examples
Wait for
ending
orended
events.
success = await call.wait_for_ringing()
Events
All these events can be used to track the calls lifecycle and instruct SignalWire on what to do for each different state.
State Events
To track the state of a call.
stateChange |
Event dispatched when Call state changes. |
created |
The call has been created in Relay. |
ringing |
The call is ringing and has not yet been answered. |
answered |
The call has been picked up. |
ending |
The call is hanging up. |
ended |
The call has ended. |
Connect Events
To track the connect state of a call.
connect.stateChange |
Event dispatched when the Call connect state changes. |
connect.connecting |
Currently calling the phone number(s) to connect. |
connect.connected |
The calls are being connected together. |
connect.failed |
The last call connection attempt failed. |
connect.disconnected |
The call was either never connected or the last call connection completed. |
Play Events
To track a playback state.
play.stateChange |
Event dispatched when the state of a playing changes. |
play.playing |
A playback in playing on the call. |
play.error |
A playback failed to start. |
play.finished |
The playback has ended. |
Record Events
To track a recording state.
record.stateChange |
Event dispatched when the state of a recording changes. |
record.recording |
The call is being recorded. |
record.no_input |
The recording failed due to no input. |
record.finished |
The recording has ended. |
Prompt Events
To track a prompt state.
prompt |
The prompt action on the call has ended. |
Fax Events
To track a fax state.
fax.stateChange |
Event dispatched when the state of a fax changes. |
fax.error |
Faxing failed. |
fax.finished |
Faxing has finished. |
fax.page |
A fax page has been sent or received. |
Detect Events
To track a detector state.
detect.error |
The detector has failed. |
detect.finished |
The detector has finished. |
detect.update |
There is a notification from the detector (eg: a new DTMF). |
Tap Events
To track a tapping state.
tap.tapping |
The tap action has started on the call. |
tap.finished |
Tap has finished. |
Digits Events
To track a send digits action state.
sendDigits.finished |
Digits have been sent. |
Ringtones
Here you can find all the accepted values for the ringtone to play, based on short country codes:
name |
at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, tw, ve, za |
Relay.Calling.ConnectAction
This object returned from connect_async
method that represents a connecting attempt that is currently active on a call.
Properties
result |
Relay.Calling.ConnectResult |
Final result of connecting. |
state |
string | Current state of connecting attempt. |
completed |
boolean | Whether the connection attempt has completed. |
payload |
dict | Payload sent to Relay to start the connect. |
Relay.Calling.ConnectResult
This object returned from connect
method that represents the final result of a connection between your call and a remote one.
Properties
successful |
boolean | Whether the call has been connected successfully. |
event |
Relay.Event |
Last event that completed the operation. |
call |
Relay.Calling.Call |
Remote Call connected with yours. |
Relay.Calling.DetectAction
This object returned from one of the asynchronous detect methods that represents a running detector on the call.
Properties
result |
Relay.Calling.DetectResult |
Final detector result. |
completed |
boolean | Whether the action has finished. |
payload |
dict | Payload sent to Relay to start this detector. |
control_id |
string | UUID to identify the detector. |
Methods
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Trying to detect a machine and stop the action after 5 seconds.
import asyncio # to use sleep
action = await call.detect_answering_machine_async()
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
Relay.Calling.DetectResult
This object returned from one of the synchronous detect methods that represents the final result of a detector.
Properties
successful |
boolean | Whether the detector has finished successfully. |
event |
Relay.Event |
Last event that completed the operation. |
type |
string | The detector type: fax , machine or digit . |
result |
string | The final detector result. |
Relay.Calling.DialResult
This object is returned by the dial
method.
Properties
successful |
boolean | Whether the remote party has picked up your call. |
event |
Relay.Event |
Last event that completed the operation. |
call |
Relay.Calling.Call |
Reference to the Call. |
Relay.Calling.FaxAction
This object returned from faxReceiveAsync
and faxSendAsync
methods represents a receiving or sending Fax on the call.
Properties
result |
Relay.Calling.FaxResult |
Final result for the fax action. |
completed |
boolean | Whether the action has finished. |
payload |
dict | Payload sent to Relay to start faxing. |
control_id |
string | UUID to identify the fax action. |
Methods
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Start sending fax and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.fax_send_async('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')
# For demonstration purposes only..
await asyncio.sleep(5)
await action.stop()
Relay.Calling.FaxResult
This object returned from faxReceive
and faxSend
methods that represents the final result of a sent or received Fax.
Properties
successful |
boolean | Whether the fax has been sent or received successfully. |
event |
Relay.Event |
Last event that completed the operation. |
direction |
string | send or receive . |
identity |
string | Identity used to send the fax. |
remote_identity |
string | Remote identity. |
document |
string | Document URL. |
pages |
number | Number of sent/received pages. |
Relay.Calling.HangupResult
This object is returned by the hangup
method.
Properties
successful |
boolean | Whether the call has been hung up successfully. |
event |
Relay.Event |
Last event that completed the operation. |
reason |
string | The hangup reason. |
Relay.Calling.PlayAction
This object returned from one of asynchronous play methods that represents a playing currently active on a call.
Properties
result |
Relay.Calling.PlayResult |
Final result of playing. |
state |
string | Current state of playing. |
completed |
boolean | Whether the playing has finished. |
payload |
dict | Payload sent to Relay to start playing. |
control_id |
string | UUID to identify the playing. |
Methods
pause
Pause the playback immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayPauseResult
object.
Examples
Start playing an audio file and pause it after 5 seconds.
import asyncio # to use sleep
action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3')
await asyncio.sleep(5)
pause_result = await action.pause()
resume
Resume the playback immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayResumeResult
object.
Examples
Start playing an audio file, stop it and then resume it after 5 seconds.
import asyncio # to use sleep
action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3')
await asyncio.sleep(5)
pause_result = await action.pause()
await asyncio.sleep(5)
resume_result = await action.resume()
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Play an Mp3 file and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3')
await asyncio.sleep(5)
await action.stop()
volume
Control the volume of the playback.
Available In:
Parameters
volume |
number | required | Volume value between -40dB and +40dB where 0 is unchanged. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PlayVolumeResult
object.
Examples
Start playing an audio file and increase the playback volume.
action = await call.play_audio_async('https://cdn.signalwire.com/default-music/welcome.mp3')
result = await action.volume(5.0)
Relay.Calling.PlayPauseResult
This object is returned by pause
method and represents the final result of a play pause operation.
Properties
successful |
boolean | Whether the playing has been paused successfully. |
Relay.Calling.PlayResult
This object returned from one of the synchronous play methods that represents the final result of a playing.
Properties
successful |
boolean | Whether the playing has completed successfully. |
event |
Relay.Event |
Last event that completed the operation. |
Relay.Calling.PlayResumeResult
This object is returned by resume
method and represents the final result of a play resume operation.
Properties
successful |
boolean | Whether the playing has resumed successfully. |
Relay.Calling.PlayVolumeResult
This object is returned by volume
method and represents the final result of a volume control operation.
Properties
successful |
boolean | Whether the playing volume has been changed successfully. |
Relay.Calling.PromptAction
This object returned from one of asynchronous prompt methods that represents a prompt attempt that is currently active on a call.
Properties
result |
Relay.Calling.PromptResult |
Final result of this prompt. |
state |
string | Current state. |
completed |
boolean | Whether the prompt attempt has finished. |
payload |
dict | Payload sent to Relay to start prompt. |
control_id |
string | UUID to identify the prompt. |
Methods
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Ask user to enter a PIN and force-stop the action after 5 seconds.
import asyncio # to use sleep
action = await call.play_tts_async(text='Welcome to SignalWire!', gender='male')
await asyncio.sleep(5)
await action.stop()
volume
Control the volume of the playback.
Available In:
Parameters
volume |
number | required | Volume value between -40dB and +40dB where 0 is unchanged. |
Returns
coroutine
- Coroutine that will return a Relay.Calling.PromptVolumeResult
object.
Examples
Start the prompt and increase the playback volume.
action = await call.play_tts_async(text='Please, enter your 3 digit PIN.', gender='male')
volume_result = await action.volume(5.0)
Relay.Calling.PromptResult
This object returned from one of the synchronous prompt methods that represents the final result of a prompting attempt.
Properties
successful |
boolean | Whether the attempt has completed successfully. |
event |
Relay.Event |
Last event that completed the operation. |
type |
string | digit or speech . |
result |
string | Result of prompt attempt. |
terminator |
string | Digit that terminated the prompt. |
confidence |
number | Confidence of the result on a speech prompt. |
Relay.Calling.PromptVolumeResult
This object is returned by volume
method and represents the final result of a volume control operation.
Properties
successful |
boolean | Whether the volume has been changed successfully. |
Relay.Calling.RecordAction
This object returned from record_async
method that represents a recording currently active on a call.
Properties
result |
Relay.Calling.RecordResult |
Final result of recording. |
state |
string | Current state of recording. |
completed |
boolean | Whether the recording has finished. |
payload |
dict | Payload sent to Relay to start recording. |
control_id |
string | UUID to identify the recording. |
Methods
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Start recording the call and stop it after 10 seconds.
import asyncio # to use sleep
action = await call.record_async(stereo=True)
await asyncio.sleep(10)
await action.stop()
Relay.Calling.RecordResult
This object returned from record
method that represents the final result of a recording.
Properties
successful |
boolean | Whether the recording has completed successfully. |
event |
Relay.Event |
Last event that completed the operation. |
url |
string | HTTPS URL to the recording file. |
duration |
number | Duration of the recording in seconds. |
size |
number | Size of the recording. |
Relay.Calling.SendDigitsAction
This object is returned by the sendDigitsAsync
method and represents a send digits action currently active on a call.
Properties
result |
Relay.Calling.SendDigitsResult |
Final result of the action. |
state |
string | Current state of the action. |
completed |
boolean | Whether the action has finished. |
payload |
dict | Payload sent to Relay to start the action. |
control_id |
string | UUID to identify the action. |
Relay.Calling.SendDigitsResult
This object is returned by the sendDigits
method and represents the final result of the action.
Properties
successful |
boolean | Whether the action has completed successfully. |
event |
Relay.Event |
Last event that completed the operation. |
Relay.Calling.TapAction
This object returned from tapAsync
method that represents the running media tapping active on a call.
Properties
result |
Relay.Calling.TapResult |
Final tap result. |
state |
string | Current state of tapping. |
completed |
boolean | Whether the tapping has finished. |
payload |
dict | Payload sent to Relay to start tapping. |
control_id |
string | UUID to identify the action. |
source_device |
dict | Source device sending media. |
Methods
stop
Stop the action immediately.
Available In:
Parameters
None
Returns
coroutine
- Coroutine that will return a Relay.Calling.StopResult
object.
Examples
Start tapping using RTP and stop it after 5 seconds.
import asyncio # to use sleep
action = await call.tap_async(audio_direction='listen', target_type='rtp', target_addr='192.168.1.1', target_port=1234)
# Do other things while tapping the media and then stop it..
await asyncio.sleep(5)
await action.stop()
Relay.Calling.TapResult
This object returned from tap
method that represents the final result of a tapping.
Properties
successful |
boolean | Whether the tapping has completed successfully. |
event |
Relay.Event |
Last event that completed the operation. |
tap |
dict | Object with payload for this action. |
source_device |
dict | Source device sending media. |
destination_device |
dict | Destination device receiving media. |
Relay.Consumer
A Relay Consumer is a simple object that runs in its own process along side your application to handle calling and messaging events in realtime. Relay Consumers abstract all the setup of connecting to Relay and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of Relay Consumers like a background worker system for all your calling and messaging needs.
Creating Consumers
A Relay Consumer is a simple object, customized by specifying contexts and event handlers to respond to incoming events.
A consumer has 2 required properties: project
, token
, and usually requires at least one contexts
for incoming events. Project and Token are used to authenticate your Consumer to your SignalWire account. Contexts are a list of contexts you want this Consumer to listen for. Learn more about Contexts.
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['default']
async def ready(self):
print('Your consumer is ready!')
async def on_incoming_call(self, call):
result = await call.answer()
if result.successful:
print('Call answered..')
# Run your consumer..
consumer = CustomConsumer()
consumer.run()
Initializing Consumers
Within setup
method you set the project
, token
and contexts
. You can also do any initialization work before processing messages. This is useful to do any one-off work that you wouldn't want to do for each and every event, such as setting up logging or connecting to a datastore.
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['support', 'office']
async def on_incoming_call(self, call):
pass
# Run your consumer..
consumer = CustomConsumer()
consumer.run()
Properties
client |
Relay.Client |
The underlying Relay client object. |
Event Handlers
Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer.
ready
Executed once your Consumer is connected to Relay and the session has been established.
Available In:
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['default']
async def ready(self):
result = await self.client.calling.dial(from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY')
if result.successful:
# Call has been answered and is now active. Use 'result.call' to access the Call object.
print(result.call)
# Run your consumer..
consumer = CustomConsumer()
consumer.run()
on_incoming_call
Executed when you receive an inbound call, passes in the inbound Call
object.
Available In:
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['default']
async def on_incoming_call(self, call):
result = await call.answer()
if result.successful:
print('Call answered..')
# Run your consumer..
consumer = CustomConsumer()
consumer.run()
on_task
Executed with your message sent through a Relay.Task
.
Available In:
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def on_task(self, message):
print('Handle inbound task in the office context')
print(message)
consumer = CustomConsumer()
consumer.run()
on_incoming_message
Executed when you receive an inbound SMS or MMS, passes in the inbound Message
object.
Available In:
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def on_incoming_message(self, message):
print('Handle inbound message')
print(message)
consumer = CustomConsumer()
consumer.run()
on_message_state_change
Executed when a message state changes, passes in the inbound Message
object.
Available In:
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def on_message_state_change(self, message):
print('A message state changed')
print(message)
consumer = CustomConsumer()
consumer.run()
Cleaning Up on Exit
When a Relay Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service.
Just implement a teardown
method in your consumer and it will be called during the shutdown procedure.
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
def teardown(self):
print('Consumer teardown..')
async def on_task(self, message):
pass
async def on_incoming_call(self, call):
pass
consumer = CustomConsumer()
consumer.run()
Running Consumers
Running a consumer is just like running any Python script, simply execute the script as a separate process and ensure you have .run()
at the end of your script. The process will stay up until you shut it down.
Shutting Down Consumers
In order to gracefully shut down a Relay consumer process, send it the SIGTERM
signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process, so using those systems will make things easier.
Relay.Event
This object represents the last Relay event that completed an operation on the Call.
Properties
name |
string | The event name. |
payload |
dict | Raw JSON object of the Relay event. |
Relay.Messaging
This represents the API interface for the Messaging Relay Service. This object is used to make requests related to managing SMS and MMS messages.
Methods
send
Send an outbound SMS or MMS message.
Available In:
Parameters
context |
string | required | The context to receive inbound events. |
from_number |
string | required | The phone number to place the message from. Must be a SignalWire phone number or short code that you own. |
to_number |
string | required | The phone number to send to. |
body |
string | required | The content of the message. Optional if media is present. |
media |
list | required | List of URLs to send in the message. Optional if body is present. |
tags |
list | optional | List of strings to tag the message with for searching in the UI. |
Returns
coroutine
- Coroutine that will be fulfilled with a Relay.Messaging.SendResult
object.
Examples
Send a message in the context office.
result = await client.messaging.send(context='office', from_number='+1XXXXXXXXXX', to_number='+1YYYYYYYYYY', body='Welcome at SignalWire!')
if result.successful:
print(f'Message ID: {result.message_id}')
Relay.Messaging.Message
An object representing an SMS or MMS message. It is the parameter of both onIncomingMessage
and onMessageStateChange
Consumer handlers.
Properties
id |
string | The unique identifier of the message. |
context |
string | The context of the message. |
from_number |
string | The phone number the message comes from. |
to_number |
string | The destination number of the message. |
direction |
string | The direction of the message: inbound or outbound . |
state |
string | The current state of the message. See Relay.Messaging.Message State Events for all the possible states. |
body |
string | The content of the message. |
media |
list | List of URLs media. |
tags |
list | List of strings with message tags. |
segments |
number | Number of segments of the message. |
reason |
string | Reason why the message was not sent. Present only in case of failure. |
Events
State Events
To track the state of a message.
queued |
The message has been queued in Relay. |
initiated |
Relay has initiate the process to send the message. |
sent |
Relay has sent the message. |
delivered |
The message has been successfully delivered. Due to the nature of SMS and MMS, receiving a delivered event is not guaranteed, even if the message is delivered successfully. |
undelivered |
The message has not been delivered. Due to the nature of SMS and MMS, receiving a undelivered event is not guaranteed, even if the message fails to be delivered. |
failed |
The call has failed. |
Relay.Messaging.SendResult
This object returned from send
method that represents the result of a send operation.
Properties
successful |
boolean | Whether the send operation has successfully queued the message. |
message_id |
string | The ID of the message. |
Relay.Task
A Relay.Task
is simple way to send jobs to your Relay.Consumers
from a short lived process, like a web framework. Relay Tasks allow you to pass commands down to your Consumers without blocking your short lived request. Think of a Relay Task as a way to queue a job for your background workers to processes asynchronously.
Creating Tasks
A Task is a simple object with 2 required arguments: project
and token
. Project and Token are used to send the Task to your Consumers. Once created, the Task has only one method deliver
to send jobs to your Consumer.
from signalwire.relay.task import Task
task = Task(project='<my-project>', token='<my-token>')
success = task.deliver('context-here', { 'key': 'random data' })
Methods
deliver
Send a job to your Consumer
in a specific context.
Available In:
Parameters
context |
string | required | Context where to send the Task. |
message |
dict | required | Dict with your custom data that will be sent to your Consumer's onTask method. |
Returns
coroutine
- Coroutine that will be fulfilled with a boolean value.
Examples
Deliver a task to your Consumer with a message to then make an outbound Call.
from signalwire.relay.task import Task
project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
task = Task(project=project, token=token)
data = {
'action': 'call',
'from': '+18881112222'
'to': '+18881113333'
}
success = task.deliver('office', data)
if success:
print('Task delivered')
else:
print('Task not delivered')
Examples
Follow the examples to see how's easy to use the Relay SDK to interact with inbound or outbound calls.
Outbound Calls
Using a Relay Consumer to make an outbound call and say "Welcome to SignalWire!", then hangup.
import logging
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def ready(self):
logging.info('CustomConsumer is ready!')
# Replace numbers with yours!
dial_result = await self.client.calling.dial(to_number='+18991114443', from_number='+18991114444')
if dial_result.successful is False:
logging.info('Outbound call not answered or failed')
return
# Take the Call object from "dial_result"
call = dial_result.call
await call.play_tts(text='Welcome to SignalWire!')
logging.info('Hanging up..')
await call.hangup()
consumer = CustomConsumer()
consumer.run()
Connect inbound calls with a series of devices
Using a Relay Consumer to manage inbound calls from the
office
context. Answer the call, try to connect it with 3 devices and wait until the remote call will be hanged up.
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
self.devices = [
{ 'to_number': '+18991114443' },
{ 'to_number': '+18991114444' },
{ 'to_number': '+18991114445' }
]
async def on_incoming_call(self, call):
result = await call.answer()
if result.successful is False:
print('Error answering the call')
return
result = await call.connect(device_list=self.devices)
if result.successful:
remote_call = result.call
# Wait until the remote leg is ended..
await remote_call.wait_for_ended()
await call.hangup()
consumer = CustomConsumer()
consumer.run()
Send an SMS
Using a Relay Consumer to send SMS.
import logging
from signalwire.relay.consumer import Consumer
class CustomConsumer(Consumer):
def setup(self):
self.project = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
self.token = 'PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
self.contexts = ['office']
async def ready(self):
logging.info('CustomConsumer is ready!')
# Replace numbers with yours!
result = await self.client.messaging.send(context='office', to_number='+18991114443', from_number='+18991114444', body='Welcome to SignalWire!')
if result.successful:
logging.info(f'Message sent. ID: {result.message_id}')
consumer = CustomConsumer()
consumer.run()