Code Examples
Copy-paste examples to get up and running quickly. Each example is self-contained and production-ready.
JavaScript / Node.js
A complete script that provisions a number, registers a webhook, and queries conversations and calls.
sms-api.js
1 const API_KEY = "YOUR_API_KEY"; 2 const BASE_URL = "https://api.agentphone.to"; 3 4 const headers = { 5 Authorization: `Bearer ${API_KEY}`, 6 "Content-Type": "application/json", 7 }; 8 9 async function createNumber() { 10 const res = await fetch(`${BASE_URL}/v1/numbers`, { 11 method: "POST", 12 headers, 13 body: JSON.stringify({ country: "US" }), 14 }); 15 return res.json(); 16 } 17 18 async function registerWebhook(url) { 19 const res = await fetch(`${BASE_URL}/v1/webhooks`, { 20 method: "POST", 21 headers, 22 body: JSON.stringify({ url }), 23 }); 24 return res.json(); 25 } 26 27 async function listConversations() { 28 const res = await fetch(`${BASE_URL}/v1/conversations`, { headers }); 29 return res.json(); 30 } 31 32 async function listCalls() { 33 const res = await fetch(`${BASE_URL}/v1/calls`, { headers }); 34 return res.json(); 35 } 36 37 async function getCall(callId) { 38 const res = await fetch(`${BASE_URL}/v1/calls/${callId}`, { headers }); 39 return res.json(); 40 } 41 42 async function makeOutboundCall(agentId, toNumber, fromNumberId) { 43 const body = { agentId, toNumber }; 44 // Optional: pick which of the agent's numbers to call from. 45 // If omitted, the agent's first assigned number is used. 46 if (fromNumberId) body.fromNumberId = fromNumberId; 47 48 const res = await fetch(`${BASE_URL}/v1/calls`, { 49 method: "POST", 50 headers, 51 body: JSON.stringify(body), 52 }); 53 return res.json(); 54 } 55 56 // --- Usage --- 57 const number = await createNumber(); 58 console.log(`Created: ${number.phoneNumber}`); 59 60 const webhook = await registerWebhook("https://my-server.com/webhook"); 61 console.log(`Webhook secret: ${webhook.secret}`); 62 63 const convos = await listConversations(); 64 console.log(`${convos.total} conversations`); 65 66 const calls = await listCalls(); 67 console.log(`${calls.total} calls`); 68 69 if (calls.data.length > 0) { 70 const call = await getCall(calls.data[0].id); 71 console.log(`Call transcripts: ${call.transcripts.length}`); 72 }
Express.js Webhook Handler
Receives webhooks, verifies HMAC signatures, and routes SMS / voice events.
webhook.js
1 const express = require("express"); 2 const crypto = require("crypto"); 3 const app = express(); 4 5 const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; 6 7 app.use("/webhook", express.raw({ type: "application/json" })); 8 9 function verifyWebhook(payload, signature, secret) { 10 const expected = crypto 11 .createHmac("sha256", secret) 12 .update(payload) 13 .digest("hex"); 14 return signature === `sha256=${expected}`; 15 } 16 17 app.post("/webhook", (req, res) => { 18 const signature = req.headers["x-webhook-signature"]; 19 20 if (!verifyWebhook(req.body, signature, WEBHOOK_SECRET)) { 21 return res.status(401).send("Invalid signature"); 22 } 23 24 const payload = JSON.parse(req.body.toString()); 25 26 if (payload.event === "agent.message") { 27 const { channel, data } = payload; 28 29 if (channel === "sms") { 30 console.log(`SMS from ${data.from}: ${data.message}`); 31 processMessage(data).catch(console.error); 32 return res.status(200).send("OK"); 33 } 34 35 if (channel === "voice") { 36 console.log(`Voice from ${data.from}: ${data.transcript}`); 37 processVoice(data) 38 .then((response) => { 39 res.status(200).json({ text: response, voice: "Polly.Amy", hangup: false }); 40 }) 41 .catch(() => { 42 res.status(200).json({ text: "Sorry, I encountered an error." }); 43 }); 44 return; 45 } 46 } 47 48 res.status(200).send("OK"); 49 }); 50 51 async function processMessage(message) { 52 // Your message processing logic (AI agent, database, queue, etc.) 53 } 54 55 async function processVoice(data) { 56 // Your voice processing logic — return a string to speak 57 return "Thanks for calling! How can I help?"; 58 } 59 60 app.listen(3000, () => console.log("Webhook server running on port 3000"));
Flask Webhook Handler
Python equivalent with HMAC verification and SMS/voice routing.
webhook.py
1 from flask import Flask, request, jsonify 2 import hmac 3 import hashlib 4 import os 5 6 app = Flask(__name__) 7 WEBHOOK_SECRET = os.environ.get("WEBHOOK_SECRET") 8 9 10 def verify_webhook(payload_body, signature, secret): 11 expected = hmac.new( 12 secret.encode(), payload_body, hashlib.sha256 13 ).hexdigest() 14 return hmac.compare_digest(f"sha256={expected}", signature) 15 16 17 @app.route("/webhook", methods=["POST"]) 18 def webhook(): 19 signature = request.headers.get("X-Webhook-Signature") 20 21 if not verify_webhook(request.data, signature, WEBHOOK_SECRET): 22 return jsonify({"error": "Invalid signature"}), 401 23 24 payload = request.json 25 26 if payload.get("event") == "agent.message": 27 channel = payload.get("channel") 28 data = payload.get("data", {}) 29 30 if channel == "sms": 31 print(f"SMS from {data['from']}: {data['message']}") 32 return jsonify({"status": "ok"}), 200 33 34 if channel == "voice": 35 transcript = data.get("transcript", "") 36 ai_response = get_ai_response(transcript) 37 return jsonify({"text": ai_response, "voice": "Polly.Amy", "hangup": False}), 200 38 39 return jsonify({"status": "ok"}), 200 40 41 42 def get_ai_response(transcript): 43 # Replace with your LLM call (OpenAI, Anthropic, etc.) 44 return f"I heard you say: {transcript}. How can I help?" 45 46 47 if __name__ == "__main__": 48 app.run(port=3000)
Voice Webhook with OpenAI
A voice-specific handler that pipes caller transcripts through GPT-4 and returns spoken responses.
voice_webhook.py
1 from flask import Flask, request, jsonify 2 import openai 3 import os 4 5 app = Flask(__name__) 6 openai.api_key = os.environ.get("OPENAI_API_KEY") 7 8 9 @app.route("/webhook", methods=["POST"]) 10 def webhook(): 11 payload = request.json 12 13 if payload.get("event") == "agent.message": 14 channel = payload.get("channel") 15 data = payload.get("data", {}) 16 17 if channel == "voice": 18 transcript = data.get("transcript", "") 19 try: 20 response = openai.ChatCompletion.create( 21 model="gpt-4", 22 messages=[ 23 {"role": "system", "content": "You are a helpful customer service assistant."}, 24 {"role": "user", "content": transcript}, 25 ], 26 max_tokens=150, 27 ) 28 ai_text = response.choices[0].message.content 29 return jsonify({"text": ai_text, "voice": "Polly.Amy", "hangup": False}), 200 30 except Exception as e: 31 print(f"AI error: {e}") 32 return jsonify({"text": "Sorry, I encountered an error."}), 200 33 34 if channel == "sms": 35 print(f"SMS from {data['from']}: {data['message']}") 36 return jsonify({"status": "ok"}), 200 37 38 return jsonify({"status": "ok"}), 200 39 40 41 if __name__ == "__main__": 42 app.run(port=3000)
Next.js API Route
Webhook handler as a Next.js Pages Router API route.
pages/api/webhook.js
1 import crypto from "crypto"; 2 3 const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; 4 5 function verifyWebhook(payload, signature, secret) { 6 const expected = crypto 7 .createHmac("sha256", secret) 8 .update(payload) 9 .digest("hex"); 10 return signature === `sha256=${expected}`; 11 } 12 13 export default async function handler(req, res) { 14 if (req.method !== "POST") { 15 return res.status(405).json({ error: "Method not allowed" }); 16 } 17 18 const signature = req.headers["x-webhook-signature"]; 19 const rawBody = JSON.stringify(req.body); 20 21 if (!verifyWebhook(rawBody, signature, WEBHOOK_SECRET)) { 22 return res.status(401).json({ error: "Invalid signature" }); 23 } 24 25 const payload = req.body; 26 27 if (payload.event === "agent.message") { 28 const { channel, data } = payload; 29 30 if (channel === "sms") { 31 await processMessage(data); 32 } 33 34 if (channel === "voice") { 35 const response = await processVoice(data); 36 return res.status(200).json({ text: response, voice: "Polly.Amy", hangup: false }); 37 } 38 } 39 40 res.status(200).json({ status: "ok" }); 41 } 42 43 async function processMessage(message) { 44 console.log(`Processing message: ${message.body}`); 45 } 46 47 async function processVoice(data) { 48 return "Thanks for calling! How can I help?"; 49 }
Python API Client
A standalone script that provisions a number, registers a webhook, and lists conversations.
sms_api.py
1 import requests 2 3 API_KEY = "YOUR_API_KEY" 4 BASE_URL = "https://api.agentphone.to" 5 headers = {"Authorization": f"Bearer {API_KEY}"} 6 7 # Create a phone number 8 number = requests.post( 9 f"{BASE_URL}/v1/numbers", 10 headers={**headers, "Content-Type": "application/json"}, 11 json={"country": "US"}, 12 ).json() 13 print(f"Created: {number['phoneNumber']}") 14 15 # Register webhook 16 webhook = requests.post( 17 f"{BASE_URL}/v1/webhooks", 18 headers={**headers, "Content-Type": "application/json"}, 19 json={"url": "https://my-server.com/webhook"}, 20 ).json() 21 print(f"Webhook secret: {webhook['secret']}") 22 23 # List conversations 24 convos = requests.get(f"{BASE_URL}/v1/conversations", headers=headers).json() 25 print(f"{convos['total']} conversations") 26 27 # Get a specific conversation 28 if convos["data"]: 29 conv = requests.get( 30 f"{BASE_URL}/v1/conversations/{convos['data'][0]['id']}", 31 headers=headers, 32 ).json() 33 print(f"Conversation with {conv['participant']}: {conv['messageCount']} messages") 34 35 # Make an outbound call (optionally pick which number to call from) 36 call = requests.post( 37 f"{BASE_URL}/v1/calls", 38 headers={**headers, "Content-Type": "application/json"}, 39 json={ 40 "agentId": "AGENT_ID", 41 "toNumber": "+14155551234", 42 # "fromNumberId": "NUMBER_ID", # optional — defaults to agent's first number 43 }, 44 ).json() 45 print(f"Call {call['id']}: {call['fromNumber']} -> {call['toNumber']}")
