Twilio Conversations API: Multi-Channel Chat and Messaging Platform
In this tutorial, you will learn about Twilio Conversations API: Multi. We cover key concepts, practical examples, and best practices to help you master this topic.
Twilio Conversations API provides a multi-channel conversation platform where participants can join via SMS, WhatsApp, chat, or voice, with unified message history and per-conversation Webhook management.
What You'll Learn
How to create and manage conversations, add participants from different channels (SMS, WhatsApp, in-app chat), send and receive messages, configure conversation Webhooks, manage conversation state (active, inactive, closed), and handle participant events.
Why It Matters
Modern users expect to switch between channels without losing context. Conversations API unifies SMS, WhatsApp, chat, and voice into single threaded conversations. DodaTech uses it for customer support where users can start on WhatsApp and continue via SMS.
Real-World Use
A DodaTech customer starts a support conversation on WhatsApp. Mid-conversation they switch to SMS. The Conversations API maintains the same thread with full history. The support agent sees the unified conversation in one interface.
flowchart LR
A["Customer\nWhatsApp"] --> B["Conversations\nAPI"]
C["Customer\nSMS"] --> B
D["Customer\nIn-App Chat"] --> B
B --> E["Your App\nWebhook"]
E --> F["Agent\nUnified View"]
F --> G["Reply via\nAny Channel"]
style A fill:#25D366,color:#fff
style C fill:#dbeafe,stroke:#2563eb
style B fill:#f22f46,color:#fff
style F fill:#bbf7d0,stroke:#16a34a
Creating a Conversation
import os
from twilio.rest import Client
client = Client(
os.environ["TWILIO_ACCOUNT_SID"],
os.environ["TWILIO_AUTH_TOKEN"]
)
# Create a conversation
def create_conversation(friendly_name, service_sid=None):
params = {
"friendly_name": friendly_name
}
if service_sid:
params["chat_service_sid"] = service_sid
conversation = client.conversations.conversations.create(**params)
print(f"Conversation SID: {conversation.sid}")
print(f"Name: {conversation.friendly_name}")
print(f"State: {conversation.state}")
print(f"Created: {conversation.date_created}")
return conversation
conv = create_conversation("DodaTech Support - Order ORD-12345")
# Expected output:
# Conversation SID: CHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Name: DodaTech Support - Order ORD-12345
# State: active
# Created: 2026-06-28 10:00:00
Adding Participants via Different Channels
# Add an SMS participant
def add_sms_participant(conversation_sid, phone_number, messaging_service_sid):
participant = client.conversations \
.conversations(conversation_sid) \
.participants.create(
messaging_binding_address=phone_number,
messaging_binding_proxy_address=messaging_service_sid
)
print(f"SMS Participant SID: {participant.sid}")
print(f"Identity: {participant.identity or phone_number}")
print(f"Type: SMS")
return participant
# Add a WhatsApp participant
def add_whatsapp_participant(conversation_sid, whatsapp_number):
participant = client.conversations \
.conversations(conversation_sid) \
.participants.create(
messaging_binding_address=f"whatsapp:{whatsapp_number}",
messaging_binding_proxy_address="whatsapp:+14155238886"
)
print(f"WhatsApp Participant: {participant.sid}")
return participant
# Add a chat participant (in-app)
def add_chat_participant(conversation_sid, identity):
participant = client.conversations \
.conversations(conversation_sid) \
.participants.create(
identity=identity
)
print(f"Chat Participant: {participant.sid} ({identity})")
return participant
# Expected output:
# SMS Participant SID: MBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Identity: +14155551234
# Type: SMS
Sending Messages to a Conversation
# Send a message to the conversation (appears on all channels)
def send_message_to_conversation(conversation_sid, author, body):
message = client.conversations \
.conversations(conversation_sid) \
.messages.create(
author=author,
body=body
)
print(f"Message SID: {message.sid}")
print(f"Author: {message.author}")
print(f"Body: {message.body}")
print(f"Index: {message.index}")
return message
msg = send_message_to_conversation(
conv.sid,
"DodaTech Support Agent",
"Hi there! I see your order ORD-12345 is on its way."
)
# Expected output:
# Message SID: IMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Author: DodaTech Support Agent
# Body: Hi there! I see your order ORD-12345 is on its way.
# Index: 1
# Retrieve conversation messages
def get_conversation_messages(conversation_sid, limit=20):
messages = client.conversations \
.conversations(conversation_sid) \
.messages.list(limit=limit)
print(f"Messages in conversation: {len(messages)}")
for msg in messages:
print(f" [{msg.index}] {msg.author}: {msg.body[:60]}")
return messages
# get_conversation_messages(conv.sid)
# Expected output:
# Messages in conversation: 2
# [1] DodaTech Support Agent: Hi there! I see your order ORD-12345...
# [2] +14155551234: Thanks! When will it arrive?
Managing Conversation State
def update_conversation_state(conversation_sid, new_state):
"""States: active, inactive, closed"""
valid_states = ["active", "inactive", "closed"]
if new_state not in valid_states:
raise ValueError(f"Invalid state: {new_state}")
conversation = client.conversations \
.conversations(conversation_sid) \
.update(state=new_state)
print(f"Conversation: {conversation.sid}")
print(f"State changed to: {conversation.state}")
return conversation
# Close a resolved conversation
update_conversation_state(conv.sid, "closed")
# Expected output:
# Conversation: CHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# State changed to: closed
# Set conversation timers
def set_conversation_timers(conversation_sid, after=86400):
"""Auto-close conversation after N seconds of inactivity."""
conversation = client.conversations \
.conversations(conversation_sid) \
.update(
timers_inactive=after,
timers_closed=after * 7 # Close after 7 days inactive
)
print(f"Timers set: inactive={after}s, closed={after*7}s")
return conversation
Common Mistakes
1. Not Configuring the Chat Service
Conversations require a Chat Service instance. Create one in the Console or via API before creating conversations. Without it, conversation creation fails with service SID errors.
2. Using Wrong Proxy Address for Participants
The messaging_binding_proxy_address must be a Messaging Service SID (MG...) or WhatsApp number. Using a regular phone number causes participant creation to fail.
3. Ignoring Participant Identity
In-app chat participants need unique identities (user IDs, emails). SMS/WhatsApp participants use their phone numbers as identity. Duplicate identities cause unexpected behavior.
4. Not Handling Webhook Events
Conversations send webhooks for new messages, participant changes, and state transitions. Without webhooks, your app doesn't know about new customer replies in real time.
5. Mixing Up Message Index and SID
Messages have both an index (sequential number within conversation) and a SID (unique for the message). Use index for display ordering and SID for API operations.
Practice Questions
- How is Conversations API different from regular SMS webhooks?
- How do participants from different channels join a single conversation?
- What states can a conversation have?
- How do you add an SMS user to a conversation?
Answers:
- SMS webhooks give isolated per-message callbacks. Conversations API unifies messages from SMS, WhatsApp, and chat into one thread with shared history, participants, and state management.
- Each participant is added with a channel binding. SMS participants use their phone number with a Messaging Service proxy. WhatsApp participants use WhatsApp numbers. Chat participants use identity strings.
- Active (messaging allowed), inactive (no new messages, timed), closed (resolved, no further messages). Conversations auto-transition based on timer settings.
- Call
participants.createwithmessaging_binding_address(customer phone) andmessaging_binding_proxy_address(your Messaging Service SID). The customer receives an SMS invite to join.
Challenge: Build a multi-channel support conversation system: create a Chat Service, create conversations for each support ticket, add participants via SMS and WhatsApp, receive and display messages from all channels in one view, manage conversation lifecycle with auto-close timers, and implement a webhook handler for real-time message delivery.
FAQ
Mini Project
Build a multi-channel support system: create a Chat Service, create a conversation for a mock support ticket, add a customer via SMS and an agent via chat, send messages from both channels, retrieve full message history, close the conversation, verify the auto-close timer, and implement webhooks for real-time updates.
What's Next
Twilio Functions — run Serverless backend logic with Twilio Functions.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro