REST Client

View as MarkdownOpen in Claude

What Is the REST Client?

The SignalWireClient 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

1#!/usr/bin/env python3
2"""REST client quick start."""
3
4from signalwire.rest import SignalWireClient
5
6client = SignalWireClient(
7 project="your-project-id",
8 token="your-api-token",
9 host="your-space.signalwire.com",
10)
11
12# List AI agents in your fabric
13agents = client.fabric.ai_agents.list()
14print(agents)
15
16# Search for available phone numbers
17available = client.phone_numbers.search(area_code="512")
18print(available)

Authentication

Constructor Arguments

LanguageSyntax
PythonSignalWireClient(project="...", token="...", host="...")
TypeScriptnew RestClient({ projectId: '...', apiToken: '...', spaceName: '...' })
1client = SignalWireClient(
2 project="your-project-id",
3 token="your-api-token",
4 host="your-space.signalwire.com",
5)

Environment Variables

All credentials can be provided via environment variables:

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

Namespaced Resources

The client exposes all SignalWire APIs through typed namespace properties:

1client.fabric # AI agents, SWML scripts, subscribers, call flows
2client.calling # REST-based call control (37 commands)
3client.phone_numbers # Search, purchase, manage numbers
4client.video # Rooms, sessions, recordings, conferences
5client.datasphere # Document management and semantic search
6client.compat # Twilio-compatible LAML API
7client.logs # Message, voice, fax, conference logs
8client.registry # 10DLC brand/campaign management
9client.queues # Call queue management
10client.recordings # Recording management
11client.project # Project-level token management
12client.mfa # Multi-factor authentication
13client.lookup # Phone number carrier/CNAM lookup
14client.pubsub # PubSub token management
15client.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")
Getclient.fabric.ai_agents.get("id")
Updateclient.fabric.ai_agents.update("id", name="y")
Deleteclient.fabric.ai_agents.delete("id")
1# List resources
2result = client.phone_numbers.list(page_size=10)
3
4# Create a resource
5new = client.fabric.ai_agents.create(name="my-agent", type="ai_agent")
6
7# Get a single resource
8agent = client.fabric.ai_agents.get("resource-id")
9
10# Update a resource
11client.fabric.ai_agents.update("resource-id", name="updated-name")
12
13# Delete a resource
14client.fabric.ai_agents.delete("resource-id")

Fabric Namespace

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

1# AI agents
2agents = client.fabric.ai_agents.list()
3agent = client.fabric.ai_agents.create(name="support-bot", type="ai_agent")
4
5# SWML scripts
6scripts = client.fabric.swml_scripts.list()
7
8# SWML webhooks
9webhooks = client.fabric.swml_webhooks.list()
10
11# Subscribers
12subs = client.fabric.subscribers.list()
13
14# Subscriber SIP endpoints
15endpoints = client.fabric.subscribers.list_sip_endpoints("subscriber-id")
16client.fabric.subscribers.create_sip_endpoint("subscriber-id", username="ext100")
17
18# Call flows with versioning
19flows = client.fabric.call_flows.list()
20versions = client.fabric.call_flows.list_versions("flow-id")
21client.fabric.call_flows.deploy_version("flow-id", version_id="v2")
22
23# Tokens (subscriber, guest, invite, embed)
24token = client.fabric.tokens.create_subscriber_token(subscriber_id="sub-id")
25guest = client.fabric.tokens.create_guest_token(name="Guest User")

Phone Numbers

Search, purchase, and manage phone numbers:

1# Search for available numbers
2available = client.phone_numbers.search(
3 area_code="512",
4 quantity=5,
5)
6
7# List your numbers
8numbers = client.phone_numbers.list()
9
10# Get a specific number
11number = client.phone_numbers.get("number-id")
12
13# Update number configuration
14client.phone_numbers.update("number-id", name="Support Line")

Calling Namespace

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

1# Initiate a call
2result = client.calling.dial(
3 call_id="call-id",
4 devices=[[{"type": "phone", "params": {"to_number": "+15559876543"}}]],
5)
6
7# Play audio on a call
8client.calling.play(call_id="call-id", play=[
9 {"type": "tts", "text": "Hello from REST!"}
10])
11
12# Record a call
13client.calling.record(call_id="call-id", record={"audio": {}})
14
15# Control playback
16client.calling.play_pause(call_id="call-id", control_id="ctrl-id")
17client.calling.play_resume(call_id="call-id", control_id="ctrl-id")
18client.calling.play_stop(call_id="call-id", control_id="ctrl-id")
19
20# AI commands
21client.calling.ai_message(call_id="call-id", message_text="New instruction")
22client.calling.ai_hold(call_id="call-id")
23client.calling.ai_unhold(call_id="call-id")
24
25# End a call
26client.calling.end(call_id="call-id", reason="hangup")

Video Namespace

Manage video rooms, conferences, sessions, and recordings:

1# Create a video room
2room = client.video.rooms.create(name="standup", max_participants=10)
3
4# List room sessions
5sessions = client.video.room_sessions.list()
6
7# Get session members
8members = client.video.room_sessions.list_members("session-id")
9
10# Manage conferences
11conf = client.video.conferences.create(name="team-conf")
12client.video.conferences.list_streams("conference-id")

Datasphere Namespace

Manage documents and run semantic search:

1# List documents
2docs = client.datasphere.documents.list()
3
4# Upload a document
5doc = client.datasphere.documents.create(
6 name="FAQ",
7 content="Your FAQ content here...",
8)
9
10# Semantic search
11results = client.datasphere.documents.search(
12 query_string="How do I reset my password?",
13 count=5,
14)
15
16# Manage chunks
17chunks = client.datasphere.documents.list_chunks("document-id")
18client.datasphere.documents.delete_chunk("document-id", "chunk-id")

Logs Namespace

Query message, voice, fax, and conference logs:

1# Voice call logs
2calls = client.logs.voice.list(page_size=20)
3call = client.logs.voice.get("log-id")
4events = client.logs.voice.list_events("log-id")
5
6# Message logs
7messages = client.logs.messages.list()
8
9# Fax logs
10faxes = client.logs.fax.list()
11
12# Conference logs
13confs = client.logs.conferences.list()

Registry Namespace (10DLC)

Manage 10DLC brands and campaigns for A2P messaging compliance:

1# List brands
2brands = client.registry.brands.list()
3
4# Create a brand
5brand = client.registry.brands.create(
6 entity_type="PRIVATE_PROFIT",
7 display_name="My Company",
8)
9
10# Create a campaign under a brand
11campaign = client.registry.brands.create_campaign(
12 "brand-id",
13 description="Customer notifications",
14 usecase="MIXED",
15)
16
17# Assign numbers to campaigns
18order = client.registry.campaigns.create_order(
19 "campaign-id",
20 phone_number_ids=["number-id-1"],
21)

Compatibility (LAML) Namespace

Twilio-compatible REST API for migrating existing applications:

1# List calls
2calls = client.compat.calls.list()
3
4# Send an SMS
5msg = client.compat.messages.create(
6 To="+15559876543",
7 From="+15551234567",
8 Body="Hello from SignalWire!",
9)
10
11# Manage phone numbers
12numbers = client.compat.phone_numbers.list()
13
14# Start call recording
15client.compat.calls.start_recording("call-sid")

Other Resources

1# Queue management
2queues = client.queues.list()
3members = client.queues.list_members("queue-id")
4next_member = client.queues.get_next_member("queue-id")
5
6# Recordings
7recordings = client.recordings.list()
8
9# Phone number lookup
10info = client.lookup.phone_number("+15551234567")
11
12# Multi-factor authentication
13client.mfa.sms(to="+15551234567", from_="+15550000000", message="Your code: {code}")
14client.mfa.verify(request_id="req-id", token="123456")
15
16# SIP profile
17profile = client.sip_profile.get()
18client.sip_profile.update(username="my-sip-user")
19
20# Verified caller IDs
21callers = client.verified_callers.list()

Pagination

For endpoints that return paginated results, use PaginatedIterator:

1from signalwire.rest._pagination import PaginatedIterator
2
3# Iterate all phone numbers across pages
4for number in PaginatedIterator(
5 client._http,
6 "/api/relay/rest/phone_numbers",
7 data_key="data",
8):
9 print(number["name"], number["number"])

The iterator automatically follows links.next URLs to fetch subsequent pages.

Error Handling

REST errors raise SignalWireRestError:

1from signalwire.rest import SignalWireClient, SignalWireRestError
2
3client = SignalWireClient()
4
5try:
6 client.phone_numbers.get("nonexistent-id")
7except SignalWireRestError as e:
8 print(f"HTTP {e.status_code}: {e.body}")
9 print(f"URL: {e.method} {e.url}")

Practical Example: Provision and Configure

1#!/usr/bin/env python3
2"""Provision a phone number and assign it to an AI agent."""
3
4from signalwire.rest import SignalWireClient, SignalWireRestError
5
6client = SignalWireClient()
7
8# Search for a local number
9available = client.phone_numbers.search(area_code="512", quantity=1)
10numbers = available.get("data", [])
11
12if not numbers:
13 print("No numbers available")
14 exit(1)
15
16# Purchase the first available number
17number_id = numbers[0]["id"]
18print(f"Purchasing: {numbers[0].get('number', number_id)}")
19
20# List AI agents
21agents = client.fabric.ai_agents.list()
22agent_list = agents.get("data", [])
23
24if agent_list:
25 agent_id = agent_list[0]["id"]
26 print(f"Found agent: {agent_list[0].get('name', agent_id)}")
27
28# Query recent call logs
29logs = client.logs.voice.list(page_size=5)
30for log in logs.get("data", []):
31 print(f" Call: {log.get('from')} -> {log.get('to')} ({log.get('status')})")