Python SDK
The official AgentPhone Python library provides convenient access to the AgentPhone API with both synchronous and asynchronous clients.
Installation
1 pip install agentphone
For async support:
1 pip install agentphone[async]
Quick start
1 from agentphone import AgentPhone 2 3 client = AgentPhone(api_key="YOUR_API_KEY") 4 5 # Create an agent 6 agent = client.agents.create(name="Support Bot") 7 8 # Buy a number and attach it 9 number = client.numbers.buy(country="US", agent_id=agent.id) 10 11 # Make an AI-powered call 12 call = client.calls.make( 13 agent_id=agent.id, 14 to_number="+15559876543", 15 system_prompt="You are a helpful support assistant.", 16 initial_greeting="Hi, this is Support Bot!", 17 )
Async usage
1 from agentphone import AsyncAgentPhone 2 3 async with AsyncAgentPhone(api_key="YOUR_API_KEY") as client: 4 agents = await client.agents.list() 5 call = await client.calls.make( 6 agent_id=agents.data[0].id, 7 to_number="+15559876543", 8 system_prompt="You are a helpful assistant.", 9 )
Resources
Agents
1 # List all agents 2 agents = client.agents.list(limit=20, offset=0) 3 4 # Create an agent with voice configuration 5 agent = client.agents.create( 6 name="Support Bot", 7 description="Handles customer inquiries", 8 voice_mode="hosted", # "hosted" for built-in AI, "webhook" for custom 9 system_prompt="You are a friendly support agent.", 10 begin_message="Hi! How can I help?", 11 voice="11labs-Brian", # see list_voices() 12 transfer_number="+15551234567", # optional: transfer calls here 13 voicemail_message="Leave a message after the beep.", 14 ) 15 16 # Get agent details 17 agent = client.agents.get(agent_id="agt_abc123") 18 19 # Update an agent 20 agent = client.agents.update( 21 agent_id="agt_abc123", 22 name="Updated Bot", 23 system_prompt="New prompt here.", 24 ) 25 26 # Delete an agent 27 client.agents.delete(agent_id="agt_abc123") 28 29 # Attach / detach a number 30 client.agents.attach_number(agent_id="agt_abc123", number_id="num_xyz789") 31 client.agents.detach_number(agent_id="agt_abc123", number_id="num_xyz789") 32 33 # List calls and conversations for an agent 34 calls = client.agents.list_calls(agent_id="agt_abc123", limit=20) 35 convos = client.agents.list_conversations(agent_id="agt_abc123", limit=20) 36 37 # List available voices 38 voices = client.agents.list_voices()
Per-agent webhooks
1 # Set a webhook for a specific agent (overrides project default) 2 webhook = client.agents.set_webhook( 3 agent_id="agt_abc123", 4 url="https://your-server.com/agent-hook", 5 context_limit=10, 6 timeout=30, 7 ) 8 9 # Get / delete an agent's webhook 10 webhook = client.agents.get_webhook(agent_id="agt_abc123") 11 client.agents.delete_webhook(agent_id="agt_abc123") 12 13 # View deliveries and send a test event 14 deliveries = client.agents.list_webhook_deliveries(agent_id="agt_abc123", limit=50) 15 client.agents.test_webhook(agent_id="agt_abc123")
Numbers
1 # List numbers 2 numbers = client.numbers.list(limit=20, offset=0) 3 4 # Buy a new number 5 number = client.numbers.buy( 6 country="US", 7 area_code="415", # optional, US/CA only 8 agent_id="agt_abc123", # optional: attach immediately 9 ) 10 11 # Get messages for a number 12 messages = client.numbers.get_messages(number_id="num_xyz789", limit=50) 13 14 # List calls for a number 15 calls = client.numbers.list_calls(number_id="num_xyz789", limit=20) 16 17 # Release a number (irreversible) 18 client.numbers.release(number_id="num_xyz789")
Messages
1 # Send an SMS or iMessage 2 client.messages.send( 3 agent_id="agt_abc123", 4 to_number="+15559876543", 5 body="Hello from my agent!", 6 media_url="https://example.com/image.png", # optional (MMS/iMessage) 7 number_id="num_xyz789", # optional: send from specific number 8 ) 9 10 # Send a tapback reaction (iMessage only) 11 client.messages.react( 12 message_id="msg_abc123", 13 reaction="love", # love, like, dislike, laugh, emphasize, question 14 )
Contacts
1 # List contacts 2 contacts = client.contacts.list(limit=50, search="Alice") 3 4 # Create a contact 5 contact = client.contacts.create( 6 phone_number="+15559876543", 7 name="Alice Smith", 8 email="[email protected]", 9 notes="VIP customer", 10 ) 11 12 # Get / update / delete 13 contact = client.contacts.get(contact_id="ct_abc123") 14 contact = client.contacts.update(contact_id="ct_abc123", name="Alice Johnson") 15 client.contacts.delete(contact_id="ct_abc123")
Conversations
1 # List all conversations 2 convos = client.conversations.list(limit=20, offset=0) 3 4 # Get a conversation with messages 5 convo = client.conversations.get( 6 conversation_id="conv_abc123", 7 message_limit=50, 8 ) 9 10 # Get messages with cursor pagination 11 messages = client.conversations.get_messages( 12 conversation_id="conv_abc123", 13 limit=50, 14 before="msg_older", # cursor pagination 15 after="msg_newer", 16 ) 17 18 # Update conversation metadata 19 convo = client.conversations.update( 20 conversation_id="conv_abc123", 21 metadata={"priority": "high", "assigned_to": "team-a"}, 22 )
Calls
1 # List calls with optional filters 2 calls = client.calls.list( 3 limit=20, 4 status="completed", # optional filter 5 direction="outbound", # optional filter 6 type="conversation", # optional filter 7 search="+1415", # optional search 8 ) 9 10 # Get a call with transcript 11 call = client.calls.get(call_id="call_abc123") 12 13 # Make an outbound call with built-in AI (no webhook needed) 14 call = client.calls.make( 15 agent_id="agt_abc123", 16 to_number="+15559876543", 17 system_prompt="You are a support agent helping with order inquiries.", 18 initial_greeting="Hello! How can I help you today?", 19 from_number_id="num_xyz789", # optional: call from specific number 20 voice="11labs-Brian", # optional: override agent voice 21 ) 22 23 # Make a webhook-based call (omit system_prompt, requires webhook configured) 24 call = client.calls.make( 25 agent_id="agt_abc123", 26 to_number="+15559876543", 27 initial_greeting="Hello!", 28 ) 29 30 # Create a web-based call (browser) 31 web_call = client.calls.create_web_call( 32 agent_id="agt_abc123", 33 metadata={"source": "dashboard"}, 34 ) 35 36 # Get transcript separately 37 transcript = client.calls.get_transcript(call_id="call_abc123") 38 39 # Stream transcript via Server-Sent Events 40 for event in client.calls.stream_transcript(call_id="call_abc123"): 41 if event["event"] == "turn": 42 print(f"[{event['data']['role']}] {event['data']['content']}") 43 elif event["event"] == "ended": 44 print(f"Call ended ({event['data']['durationSeconds']}s)")
Webhooks (project-level)
1 # Get webhook config 2 webhook = client.webhooks.get() 3 4 # Set or update webhook 5 webhook = client.webhooks.set( 6 url="https://your-server.com/webhook", 7 context_limit=10, # 0-50 recent messages in payloads 8 timeout=30, # response timeout in seconds (5-120) 9 ) 10 print(webhook.secret) # save this! 11 12 # View delivery history 13 deliveries = client.webhooks.list_deliveries(limit=50) 14 15 # Get delivery statistics 16 stats = client.webhooks.get_delivery_stats(hours=24) 17 print(f"Success rate: {stats.success_rate}%") 18 19 all_time = client.webhooks.get_all_time_stats() 20 21 # Test webhook 22 client.webhooks.test(agent_id="agt_abc123") # optional: test for specific agent 23 24 # Delete webhook 25 client.webhooks.delete()
Usage
1 # Get current usage summary (plan, limits, stats) 2 usage = client.usage.get() 3 print(f"Plan: {usage.plan.name}") 4 print(f"Numbers: {usage.numbers.used}/{usage.numbers.limit}") 5 print(f"Messages (30d): {usage.stats.messages_last_30d}") 6 print(f"Calls (30d): {usage.stats.calls_last_30d}") 7 8 # Daily breakdown 9 daily = client.usage.get_daily(days=30) 10 for day in daily.data: 11 print(f"{day.date}: {day.messages} msgs, {day.calls} calls") 12 13 # Monthly breakdown 14 monthly = client.usage.get_monthly(months=6)
Error handling
1 from agentphone import ( 2 AgentPhoneError, 3 AuthenticationError, 4 NotFoundError, 5 RateLimitError, 6 ) 7 8 try: 9 agent = client.agents.get(agent_id="bad-id") 10 except NotFoundError: 11 print("Agent not found") 12 except AuthenticationError: 13 print("Invalid API key") 14 except RateLimitError: 15 print("Too many requests") 16 except AgentPhoneError as e: 17 print(f"API error {e.status}: {e.message}")
Webhook verification
Verify incoming webhook signatures and parse events:
1 from agentphone import construct_event, verify_webhook, WebhookVerificationError 2 3 # Option 1: Verify signature only 4 try: 5 verify_webhook(payload, signature, secret) 6 except WebhookVerificationError: 7 print("Invalid signature") 8 9 # Option 2: Verify + parse into a typed event 10 event = construct_event(payload, signature, secret) 11 12 if event.event == "agent.message": 13 print(event.data.message) 14 print(event.data.from_number) 15 print(event.channel) # "sms", "imessage", or "voice" 16 for item in event.recent_history: # recent conversation context 17 print(f" [{item.direction}] {item.content}") 18 print(event.conversation_state) # custom metadata
Flask example
1 from flask import Flask, request, jsonify 2 from agentphone import construct_event 3 4 app = Flask(__name__) 5 6 @app.route("/webhook", methods=["POST"]) 7 def webhook(): 8 event = construct_event( 9 payload=request.data, 10 signature=request.headers.get("X-Webhook-Signature", ""), 11 secret="your_webhook_secret", 12 ) 13 14 # Respond to the caller 15 return jsonify({"response": f"Got your message: {event.data.message}"})
Advanced
Context manager
1 with AgentPhone(api_key="YOUR_API_KEY") as client: 2 agents = client.agents.list() 3 # session is automatically closed
Custom base URL and timeout
1 client = AgentPhone( 2 api_key="YOUR_API_KEY", 3 base_url="https://api.agentphone.to", 4 timeout=30.0, 5 )

