REST Client

View as MarkdownOpen in Claude

What Is the REST Client?

The RestClient provides a synchronous Python interface to all SignalWire REST APIs. It organizes the platform’s HTTP endpoints into namespaced resource objects with standard CRUD operations.

When to Use REST vs Relay vs Agents

ApproachBest For
AgentBase (SWML)AI-driven voice agents
Relay ClientReal-time call control over WebSocket
REST ClientResource management, provisioning, log queries, admin tasks

Use the REST client for tasks like purchasing phone numbers, managing fabric resources, querying call logs, or any operation that doesn’t require real-time event handling.

Quick Start

#!/usr/bin/env python3
"""REST client quick start."""
from signalwire.rest import RestClient
client = RestClient(
project="your-project-id",
token="your-api-token",
host="your-space.signalwire.com",
)
# List AI agents in your fabric
agents = client.fabric.ai_agents.list()
print(agents)
# Search for available phone numbers
available = client.phone_numbers.search(areacode="512")
print(available)

Authentication

Constructor Arguments

LanguageSyntax
PythonRestClient(project="...", token="...", host="...")
TypeScriptnew RestClient({ project: '...', token: '...', host: '...' })
client = RestClient(
project="your-project-id",
token="your-api-token",
host="your-space.signalwire.com",
)

Environment Variables

All credentials can be provided via environment variables:

VariablePurpose
SIGNALWIRE_PROJECT_IDProject ID
SIGNALWIRE_API_TOKENAPI token
SIGNALWIRE_SPACESpace hostname
# With env vars set, no arguments needed
client = RestClient()

Namespaced Resources

The client exposes all SignalWire APIs through typed namespace properties:

client.fabric # AI agents, SWML scripts, subscribers, call flows
client.calling # REST-based call control (37 commands)
client.phone_numbers # Search, purchase, manage numbers
client.video # Rooms, sessions, recordings, conferences
client.datasphere # Document management and semantic search
client.messages # Send SMS/MMS, redact sent messages
client.projects # Subprojects and signing keys
client.logs # Message, voice, fax, conference logs
client.registry # 10DLC brand/campaign management
client.queues # Call queue management
client.recordings # Recording management
client.project # Project-level token management
client.mfa # Multi-factor authentication
client.lookup # Phone number carrier/CNAM lookup
client.pubsub # PubSub token management
client.chat # Chat token management

CRUD Pattern

Most resources follow a standard CRUD pattern:

OperationPython
Listclient.phone_numbers.list()
Createclient.fabric.ai_agents.create(name="x", prompt=...)
Getclient.fabric.ai_agents.get("id")
Updateclient.fabric.ai_agents.update("id", name="y")
Deleteclient.fabric.ai_agents.delete("id")
# List resources
result = client.phone_numbers.list(page_size=10)
# Create a resource
new = client.fabric.ai_agents.create(
name="my-agent", prompt={"text": "You are a helpful assistant."}
)
# Get a single resource
agent = client.fabric.ai_agents.get("resource-id")
# Update a resource
client.fabric.ai_agents.update("resource-id", name="updated-name")
# Delete a resource
client.fabric.ai_agents.delete("resource-id")

Fabric Namespace

Manage SignalWire Fabric resources — AI agents, SWML scripts, subscribers, and call flows:

# AI agents
agents = client.fabric.ai_agents.list()
agent = client.fabric.ai_agents.create(
name="support-bot", prompt={"text": "You are a support agent."}
)
# SWML scripts
scripts = client.fabric.swml_scripts.list()
# SWML webhooks
webhooks = client.fabric.swml_webhooks.list()
# Subscribers
subs = client.fabric.subscribers.list()
# Subscriber SIP endpoints
endpoints = client.fabric.subscribers.list_sip_endpoints("subscriber-id")
client.fabric.subscribers.create_sip_endpoint(
"subscriber-id", username="ext100", password="a-strong-password"
)
# Call flows with versioning
flows = client.fabric.call_flows.list()
versions = client.fabric.call_flows.list_versions("flow-id")
client.fabric.call_flows.deploy_version("flow-id", {"call_flow_version_id": "v2"})
# Tokens (subscriber, guest, invite, embed)
token = client.fabric.tokens.create_subscriber_token(reference="sub-id")
guest = client.fabric.tokens.create_guest_token(allowed_addresses=["address-id"])

Phone Numbers

Search, purchase, and manage phone numbers:

# Search for available numbers
available = client.phone_numbers.search(
areacode="512",
max_results=5,
)
# List your numbers
numbers = client.phone_numbers.list()
# Get a specific number
number = client.phone_numbers.get("number-id")
# Update number configuration
client.phone_numbers.update("number-id", name="Support Line")

Calling Namespace

REST-based call control with 37+ commands. All commands are dispatched via POST:

# Initiate a call
result = client.calling.dial(
from_="+15559876543",
to="+15551234567",
)
# Play audio on a call
client.calling.play(call_id="call-id", play=[
{"type": "tts", "text": "Hello from REST!"}
])
# Record a call
client.calling.record(call_id="call-id", audio={})
# Control playback
client.calling.play_pause(call_id="call-id", control_id="ctrl-id")
client.calling.play_resume(call_id="call-id", control_id="ctrl-id")
client.calling.play_stop(call_id="call-id", control_id="ctrl-id")
# AI commands
client.calling.ai_message(call_id="call-id", message_text="New instruction")
client.calling.ai_hold(call_id="call-id")
client.calling.ai_unhold(call_id="call-id")
# End a call
client.calling.end(call_id="call-id", reason="hangup")

Video Namespace

Manage video rooms, conferences, sessions, and recordings:

# Create a video room
room = client.video.rooms.create(name="standup", max_members=10)
# List room sessions
sessions = client.video.room_sessions.list()
# Get session members
members = client.video.room_sessions.list_members("session-id")
# Manage conferences
conf = client.video.conferences.create(name="team-conf")
client.video.conferences.list_streams("conference-id")

Datasphere Namespace

Manage documents and run semantic search:

# List documents
docs = client.datasphere.documents.list()
# Upload a document
doc = client.datasphere.documents.create(
name="FAQ",
content="Your FAQ content here...",
)
# Semantic search
results = client.datasphere.documents.search(
query_string="How do I reset my password?",
count=5,
)
# Manage chunks
chunks = client.datasphere.documents.list_chunks("document-id")
client.datasphere.documents.delete_chunk("document-id", "chunk-id")

Logs Namespace

Query message, voice, fax, and conference logs:

# Voice call logs
calls = client.logs.voice.list(page_size=20)
call = client.logs.voice.get("log-id")
events = client.logs.voice.list_events("log-id")
# Message logs
messages = client.logs.messages.list()
# Fax logs
faxes = client.logs.fax.list()
# Conference logs
confs = client.logs.conferences.list()

Registry Namespace (10DLC)

Manage 10DLC brands and campaigns for A2P messaging compliance:

# List brands
brands = client.registry.brands.list()
# Create a brand
brand = client.registry.brands.create(
entity_type="PRIVATE_PROFIT",
display_name="My Company",
)
# Create a campaign under a brand
campaign = client.registry.brands.create_campaign(
"brand-id",
description="Customer notifications",
usecase="MIXED",
)
# Assign numbers to campaigns
order = client.registry.campaigns.create_order(
"campaign-id",
phone_number_ids=["number-id-1"],
)

Messages

Send an SMS or MMS and redact a sent message’s body:

# Send a message
msg = client.messages.create(
to="+15559876543",
from_="+15551234567",
body="Your table is ready.",
)
# Redact the body after delivery
client.messages.update(msg["id"], body="")

To query message history, use client.logs.messages instead.

Other Resources

# Queue management
queues = client.queues.list()
members = client.queues.list_members("queue-id")
next_member = client.queues.get_next_member("queue-id")
# Recordings
recordings = client.recordings.list()
# Phone number lookup
info = client.lookup.phone_number("+15551234567")
# Multi-factor authentication
client.mfa.sms(to="+15551234567", from_="+15550000000", message="Your code: {code}")
client.mfa.verify("req-id", token="123456")
# SIP profile
profile = client.sip_profile.get()
client.sip_profile.update(domain_identifier="my-sip-domain")
# Verified caller IDs
callers = client.verified_callers.list()

Pagination

list() returns a single page. Most list resources also expose paginate(), which follows links.next and yields every item across all pages:

# Iterate all phone numbers across pages
for number in client.phone_numbers.paginate():
print(number["name"], number["number"])

Timeouts and retries

Pass a RequestOptions to the client for a default timeout and retry policy, or to any method for a one-off override:

from signalwire.rest import RestClient, RequestOptions
client = RestClient(request_options=RequestOptions(timeout=10.0, retries=3))
numbers = client.phone_numbers.list(request_options=RequestOptions(timeout=60.0))

In TypeScript, every list resource has a paginate() method that returns an async iterator over all pages:

for await (const number of client.phoneNumbers.paginate()) {
console.log(number.name, number.number);
}

Error Handling

REST errors raise SignalWireRestError. A request that never reaches the server raises SignalWireRestTransportError, a subclass with status_code set to None, so one except covers both. The error carries the platform request_id for support correlation.

from signalwire.rest import RestClient, SignalWireRestError
client = RestClient()
try:
client.phone_numbers.get("nonexistent-id")
except SignalWireRestError as e:
print(f"HTTP {e.status_code}: {e.body}")
print(f"URL: {e.method} {e.url}")
print(f"Request ID: {e.request_id}")

Practical Example: Provision and Configure

#!/usr/bin/env python3
"""Provision a phone number and assign it to an AI agent."""
from signalwire.rest import RestClient, SignalWireRestError
client = RestClient()
# Search for a local number
available = client.phone_numbers.search(areacode="512", max_results=1)
numbers = available.get("data", [])
if not numbers:
print("No numbers available")
exit(1)
# Purchase the first available number
number_id = numbers[0]["id"]
print(f"Purchasing: {numbers[0].get('number', number_id)}")
# List AI agents
agents = client.fabric.ai_agents.list()
agent_list = agents.get("data", [])
if agent_list:
agent_id = agent_list[0]["id"]
print(f"Found agent: {agent_list[0].get('name', agent_id)}")
# Query recent call logs
logs = client.logs.voice.list(page_size=5)
for log in logs.get("data", []):
print(f" Call: {log.get('from')} -> {log.get('to')} ({log.get('status')})")