Navbar
Logo icon Name
  • Relay SDK for Python
  • API Reference
  • Examples
  • 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.

    Latest Version:

    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.

    For more information on finding your access token, visit Relay Access Keys & Tokens

    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()
    

    Learn more about Relay Tasks

    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 configuing 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 and size 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.
    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 or ended 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 or ended 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 buisness 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.

    Shuting 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 fullfilled 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('Outboud 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()