CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-twilio

Twilio API client and TwiML generator for comprehensive telecommunications services

Overview
Eval results
Files

twiml-generation.mddocs/

TwiML Generation

XML markup language generation for controlling voice calls and messaging flows. Provides Python classes that generate TwiML XML for call routing, text-to-speech, user input collection, and message handling.

Capabilities

Voice Response Generation

Create TwiML responses for voice calls with support for speech synthesis, call routing, user input collection, and call control.

class VoiceResponse:
    """Main class for generating voice TwiML responses"""
    
    def __init__(self):
        """Initialize a new voice response"""
    
    def say(
        self,
        message: str = None,
        voice: str = None,
        language: str = None,
        loop: int = None
    ) -> Say:
        """
        Text-to-speech synthesis.
        
        Args:
            message (str): Text to speak
            voice (str): Voice to use ('man', 'woman', 'alice')
            language (str): Language code (e.g., 'en-US', 'es-ES')
            loop (int): Number of times to repeat
            
        Returns:
            Say: Say verb element
        """
    
    def play(
        self,
        url: str = None,
        loop: int = None,
        digits: str = None
    ) -> Play:
        """
        Play audio file from URL.
        
        Args:
            url (str): URL of audio file to play
            loop (int): Number of times to repeat
            digits (str): DTMF digits to send during playback
            
        Returns:
            Play: Play verb element
        """
    
    def dial(
        self,
        number: str = None,
        action: str = None,
        method: str = None,
        timeout: int = None,
        hangup_on_star: bool = None,
        time_limit: int = None,
        caller_id: str = None,
        record: str = None,
        trim: str = None,
        recording_status_callback: str = None,
        recording_status_callback_method: str = None,
        recording_status_callback_event: list = None,
        answer_on_bridge: bool = None,
        ring_tone: str = None,
        recording_track: str = None,
        sequential: bool = None
    ) -> Dial:
        """
        Dial phone numbers, SIP addresses, or clients.
        
        Args:
            number (str): Phone number to dial
            action (str): Webhook URL after dial completes
            method (str): HTTP method for action URL
            timeout (int): Ring timeout in seconds
            hangup_on_star (bool): Hang up when caller presses *
            time_limit (int): Maximum call duration in seconds
            caller_id (str): Caller ID to display
            record (str): Record the call ('record-from-answer')
            
        Returns:
            Dial: Dial verb element
        """
    
    def gather(
        self,
        input: str = None,
        action: str = None,
        method: str = None,
        timeout: int = None,
        finish_on_key: str = None,
        num_digits: int = None,
        partial_result_callback: str = None,
        partial_result_callback_method: str = None,
        language: str = None,
        hints: str = None,
        barge_in: bool = None,
        debug: bool = None,
        action_on_empty_result: bool = None,
        speech_timeout: str = None,
        enhanced: bool = None,
        speech_model: str = None,
        profanity_filter: bool = None
    ) -> Gather:
        """
        Collect user input via DTMF or speech.
        
        Args:
            input (str): Input type ('dtmf', 'speech', 'dtmf speech')
            action (str): Webhook URL to send results
            method (str): HTTP method for action URL
            timeout (int): Input timeout in seconds
            finish_on_key (str): Key to end input (default: #)
            num_digits (int): Number of digits to collect
            language (str): Speech recognition language
            hints (str): Speech recognition hints
            barge_in (bool): Allow input during nested verbs
            
        Returns:
            Gather: Gather verb element
        """
    
    def record(
        self,
        action: str = None,
        method: str = None,
        timeout: int = None,
        finish_on_key: str = None,
        max_length: int = None,
        play_beep: bool = None,
        trim: str = None,
        recording_status_callback: str = None,
        recording_status_callback_method: str = None,
        transcribe: bool = None,
        transcribe_callback: str = None
    ) -> Record:
        """
        Record caller's voice.
        
        Args:
            action (str): Webhook URL after recording
            method (str): HTTP method for action URL
            timeout (int): Silence timeout in seconds
            finish_on_key (str): Key to stop recording
            max_length (int): Maximum recording length in seconds
            play_beep (bool): Play beep before recording
            trim (str): Trim silence ('trim-silence')
            transcribe (bool): Enable transcription
            
        Returns:
            Record: Record verb element
        """
    
    def pause(self, length: int = None) -> Pause:
        """
        Pause execution.
        
        Args:
            length (int): Pause duration in seconds
            
        Returns:
            Pause: Pause verb element
        """
    
    def redirect(
        self,
        url: str = None,
        method: str = None
    ) -> Redirect:
        """
        Redirect to new TwiML URL.
        
        Args:
            url (str): New TwiML URL
            method (str): HTTP method ('GET' or 'POST')
            
        Returns:
            Redirect: Redirect verb element
        """
    
    def hangup(self) -> Hangup:
        """
        End the call.
        
        Returns:
            Hangup: Hangup verb element
        """
    
    def reject(self, reason: str = None) -> Reject:
        """
        Reject incoming call.
        
        Args:
            reason (str): Rejection reason ('rejected', 'busy')
            
        Returns:
            Reject: Reject verb element
        """
    
    def enqueue(
        self,
        name: str = None,
        action: str = None,
        method: str = None,
        wait_url: str = None,
        wait_url_method: str = None,
        workflow_sid: str = None
    ) -> Enqueue:
        """
        Place caller in queue.
        
        Args:
            name (str): Queue name
            action (str): Webhook URL after dequeue
            wait_url (str): TwiML URL while waiting
            workflow_sid (str): TaskRouter workflow SID
            
        Returns:
            Enqueue: Enqueue verb element
        """
    
    def leave(self) -> Leave:
        """
        Leave current queue.
        
        Returns:
            Leave: Leave verb element
        """
    
    def to_xml(self) -> str:
        """
        Generate XML string.
        
        Returns:
            str: Complete TwiML XML document
        """

# Dial sub-elements
class Number:
    """Phone number to dial within <Dial>"""
    def __init__(
        self,
        number: str,
        send_digits: str = None,
        url: str = None,
        method: str = None,
        status_callback_event: list = None,
        status_callback: str = None,
        status_callback_method: str = None,
        byoc: str = None,
        machine_detection: str = None,
        machine_detection_timeout: int = None,
        amd_status_callback: str = None,
        amd_status_callback_method: str = None
    ): ...

class Conference:
    """Conference room within <Dial>"""
    def __init__(
        self,
        name: str,
        muted: bool = None,
        beep: str = None,
        start_conference_on_enter: bool = None,
        end_conference_on_exit: bool = None,
        wait_url: str = None,
        wait_method: str = None,
        max_participants: int = None,
        record: str = None,
        region: str = None,
        whisper: str = None,
        trim: str = None,
        status_callback_event: list = None,
        status_callback: str = None,
        status_callback_method: str = None,
        recording_status_callback: str = None,
        recording_status_callback_method: str = None,
        recording_status_callback_event: list = None,
        event_callback_url: str = None,
        jitter_buffer_size: str = None,
        coach: str = None,
        call_sid_to_coach: str = None
    ): ...

class Queue:
    """Queue within <Dial>"""
    def __init__(
        self,
        name: str,
        url: str = None,
        method: str = None,
        reservation_sid: str = None,
        post_work_activity_sid: str = None
    ): ...

class Sip:
    """SIP address within <Dial>"""
    def __init__(
        self,
        uri: str,
        username: str = None,
        password: str = None
    ): ...

class Client:
    """Twilio Client within <Dial>"""
    def __init__(
        self,
        identity: str,
        url: str = None,
        method: str = None,
        status_callback_event: list = None,
        status_callback: str = None,
        status_callback_method: str = None
    ): ...

Voice TwiML examples:

from twilio.twiml.voice_response import VoiceResponse

# Basic text-to-speech
response = VoiceResponse()
response.say("Hello, welcome to our service!")
print(response)
# Output: <Response><Say>Hello, welcome to our service!</Say></Response>

# Play audio with loop
response = VoiceResponse()
response.play("https://example.com/music.mp3", loop=3)

# Collect DTMF input
response = VoiceResponse()
gather = response.gather(num_digits=4, action="/process-input", method="POST")
gather.say("Please enter your 4-digit PIN followed by the pound key")
response.say("We didn't receive any input. Goodbye!")

# Make outbound call
response = VoiceResponse()
dial = response.dial("+15559876543", timeout=30, caller_id="+15551234567")

# Conference call
response = VoiceResponse()
dial = response.dial()
dial.conference("My Conference Room", 
                start_conference_on_enter=True,
                end_conference_on_exit=True)

# Record voicemail
response = VoiceResponse()
response.say("Please leave a message after the beep")
response.record(max_length=30, 
               action="/handle-recording",
               finish_on_key="#")

# Call screening with gather
response = VoiceResponse()
gather = response.gather(num_digits=1, action="/screen-response")
gather.say("Press 1 to accept this call, press 2 to send to voicemail")
response.hangup()

# Complex call flow
response = VoiceResponse()
gather = response.gather(input="speech dtmf", 
                        action="/handle-input",
                        speech_timeout="auto")
gather.say("Say or press a department: Sales, Support, or Billing")
response.redirect("/main-menu")

Messaging Response Generation

Create TwiML responses for SMS/MMS message handling with support for replies and redirects.

class MessagingResponse:
    """Main class for generating messaging TwiML responses"""
    
    def __init__(self):
        """Initialize a new messaging response"""
    
    def message(
        self,
        body: str = None,
        to: str = None,
        from_: str = None,
        action: str = None,
        method: str = None,
        status_callback: str = None
    ) -> Message:
        """
        Send reply message.
        
        Args:
            body (str): Message text content
            to (str): Recipient phone number
            from_ (str): Sender phone number
            action (str): Webhook URL after sending
            method (str): HTTP method for action URL
            status_callback (str): Delivery status webhook
            
        Returns:
            Message: Message element
        """
    
    def redirect(
        self,
        url: str = None,
        method: str = None
    ) -> Redirect:
        """
        Redirect to new TwiML URL.
        
        Args:
            url (str): New TwiML URL  
            method (str): HTTP method ('GET' or 'POST')
            
        Returns:
            Redirect: Redirect element
        """
    
    def to_xml(self) -> str:
        """
        Generate XML string.
        
        Returns:
            str: Complete TwiML XML document
        """

class Message:
    """Message element for replies"""
    def __init__(
        self,
        body: str = None,
        to: str = None,
        from_: str = None,
        action: str = None,
        method: str = None,
        status_callback: str = None
    ): ...
    
    def body(self, message: str) -> Body:
        """Set message body text"""
    
    def media(self, url: str) -> Media:
        """Add media attachment"""

class Body:
    """Message body text"""
    def __init__(self, message: str): ...

class Media:
    """Media attachment"""
    def __init__(self, url: str): ...

Messaging TwiML examples:

from twilio.twiml.messaging_response import MessagingResponse

# Simple reply
response = MessagingResponse()
response.message("Thanks for your message!")
print(response)
# Output: <Response><Message>Thanks for your message!</Message></Response>

# Reply with media
response = MessagingResponse()
message = response.message()
message.body("Here's the image you requested:")
message.media("https://example.com/image.jpg")

# Forward to another number
response = MessagingResponse()
response.message("Message forwarded", to="+15551234567")

# Auto-reply with redirect
response = MessagingResponse()
response.message("Processing your request...")
response.redirect("/process-message", method="POST")

# Conditional responses based on webhook data
response = MessagingResponse()
# This would typically be in a webhook handler
incoming_body = "HELP"  # From webhook parameters
if incoming_body.upper() == "HELP":
    response.message("Available commands: INFO, SUPPORT, STOP")
elif incoming_body.upper() == "STOP":
    response.message("You have been unsubscribed.")
else:
    response.message("Unknown command. Reply HELP for options.")

TwiML Base Classes

Base functionality shared across voice and messaging TwiML generation.

class TwiML:
    """Base class for all TwiML responses"""
    
    def __init__(self):
        """Initialize TwiML response"""
    
    def append(self, twiml: 'TwiML') -> 'TwiML':
        """
        Append another TwiML element.
        
        Args:
            twiml (TwiML): Element to append
        
        Returns:
            TwiML: Self for chaining
        """
    
    def to_xml(self) -> str:
        """
        Generate XML string representation.
        
        Returns:
            str: XML document string
        """
    
    def __str__(self) -> str:
        """String representation returns XML"""

class GenericNode:
    """Generic XML element for custom TwiML"""
    
    def __init__(
        self,
        name: str,
        body: str = None,
        **kwargs
    ):
        """
        Create custom XML element.
        
        Args:
            name (str): XML element name
            body (str): Element text content
            **kwargs: Element attributes
        """

Advanced TwiML usage:

from twilio.twiml.voice_response import VoiceResponse
from twilio.twiml import GenericNode

# Chaining TwiML elements
response = VoiceResponse()
response.say("Welcome").pause(1).say("Please hold")

# Using generic nodes for custom elements
response = VoiceResponse()
custom = GenericNode("CustomElement", "Custom content", attr="value")
response.append(custom)

# Building complex nested structures
response = VoiceResponse()
gather = response.gather(action="/process")
gather.say("Press 1 for sales")
gather.pause(1)
gather.say("Press 2 for support")
response.say("No input received")
response.hangup()

# Multiple dial targets
response = VoiceResponse()
dial = response.dial()
dial.number("+15551111111", status_callback="/call-progress")
dial.number("+15552222222", status_callback="/call-progress")
dial.client("alice")

# XML output customization
response = VoiceResponse()
response.say("Hello")
xml_string = response.to_xml()
print(xml_string)  # Pretty-printed XML

Fax Response Generation

Create TwiML responses for fax transmission and reception handling.

class FaxResponse:
    """Main class for generating fax TwiML responses"""
    
    def __init__(self):
        """Initialize a new fax response"""
    
    def receive(
        self,
        action: str = None,
        method: str = None,
        media_type: str = None,
        store_media: bool = None,
        page_size: str = None
    ) -> Receive:
        """
        Receive incoming fax transmission.
        
        Args:
            action (str): Webhook URL after fax reception
            method (str): HTTP method for action URL
            media_type (str): Media type ('application/pdf', 'image/tiff')
            store_media (bool): Store received fax media
            page_size (str): Page size for received fax
            
        Returns:
            Receive: Receive verb element
        """
    
    def reject(self, reason: str = None) -> Reject:
        """
        Reject incoming fax.
        
        Args:
            reason (str): Rejection reason
            
        Returns:
            Reject: Reject verb element
        """
    
    def to_xml(self) -> str:
        """
        Generate XML string.
        
        Returns:
            str: Complete TwiML XML document
        """

class Receive:
    """Fax receive element"""
    def __init__(
        self,
        action: str = None,
        method: str = None,
        media_type: str = None,
        store_media: bool = None,
        page_size: str = None
    ): ...

Fax TwiML examples:

from twilio.twiml.fax_response import FaxResponse

# Receive incoming fax
response = FaxResponse()
response.receive(
    action="/fax-received",
    method="POST",
    media_type="application/pdf",
    store_media=True
)
print(response)
# Output: <Response><Receive action="/fax-received" method="POST" mediaType="application/pdf" storeMedia="true"/></Response>

# Reject fax
response = FaxResponse()
response.reject(reason="busy")
print(response)
# Output: <Response><Reject reason="busy"/></Response>

TwiML Integration Patterns

Webhook Integration

TwiML responses are typically generated in webhook handlers that respond to Twilio HTTP requests.

from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

@app.route("/voice", methods=['GET', 'POST'])
def voice_handler():
    """Handle incoming voice calls"""
    response = VoiceResponse()
    
    # Access Twilio parameters
    from_number = request.values.get('From')
    to_number = request.values.get('To')
    call_sid = request.values.get('CallSid')
    
    response.say(f"Hello, you called {to_number} from {from_number}")
    
    return str(response)

@app.route("/sms", methods=['GET', 'POST'])  
def sms_handler():
    """Handle incoming SMS messages"""
    from twilio.twiml.messaging_response import MessagingResponse
    
    response = MessagingResponse()
    
    # Access message parameters
    from_number = request.values.get('From')
    body = request.values.get('Body', '').strip()
    
    if body.lower() == 'hello':
        response.message("Hi there! How can I help you?")
    else:
        response.message("Thanks for your message!")
    
    return str(response)

Dynamic TwiML Generation

Build TwiML responses based on database queries or external APIs.

def create_menu_twiml(menu_options):
    """Generate dynamic menu TwiML"""
    response = VoiceResponse()
    
    gather = response.gather(num_digits=1, action="/handle-menu")
    gather.say("Please select from the following options:")
    
    for i, option in enumerate(menu_options, 1):
        gather.say(f"Press {i} for {option}")
    
    response.say("Invalid selection. Please try again.")
    response.redirect("/main-menu")
    
    return response

# Usage
menu_items = ["Sales", "Support", "Billing", "Directory"]
twiml = create_menu_twiml(menu_items)

Install with Tessl CLI

npx tessl i tessl/pypi-twilio

docs

advanced-services.md

authentication-jwt.md

core-communications.md

index.md

infrastructure.md

rest-client.md

twiml-generation.md

webhooks-validation.md

tile.json