Documentation
Everything you need to integrate AgentPhone with your AI agent. Send and receive SMS/MMS, use hosted voice AI, and build conversational agents with real phone numbers.
https://agentphone.primary.netAuth: Bearer API_KEYQuick Start
Get your AI agent sending and receiving messages in three steps. You'll need your phone number ID and API key from the dashboard.
Set your webhook
In the dashboard, configure the webhook URL where inbound messages will be sent.
Handle inbound messages
Your agent receives a POST with the message. Reply inline or use the send endpoint.
// Your webhook handler receives:
{
"event": "message.inbound",
"from": "+15551234567",
"body": "Hello agent",
"channel": "sms"
}
// Reply inline:
{ "reply": "Hi there!", "action": "respond" }Send outbound messages
Use your API key to send SMS/MMS from your number at any time.
curl -X POST https://agentphone.primary.net/api/numbers/YOUR_NUMBER_ID/send/sms \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"+15559876543","body":"Hello!"}'Authentication
All API requests require a Bearer token. Generate an API key from your dashboard and include it in the Authorization header.
curl https://agentphone.primary.net/api/numbers/YOUR_NUMBER_ID/send/sms \
-H "Authorization: Bearer agp_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"to": "+15559876543", "body": "Hello!"}'Send SMS / MMS
Send outbound messages from your provisioned phone number using your API key.
/api/numbers/:id/send/smsSend an SMS or MMS message from your phone number.
Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body
{
"to": "+15559876543",
"body": "Hello from my AI agent!"
}Response
{
"messageId": "msg_abc123",
"status": "queued",
"to": "+15559876543",
"body": "Hello from my AI agent!"
}/api/numbers/:id/send/smsSend an MMS message with media attachments.
Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body
{
"to": "+15559876543",
"body": "Check out this image",
"media": [
"https://example.com/photo.png"
]
}Response
{
"messageId": "msg_def456",
"status": "queued",
"to": "+15559876543",
"body": "Check out this image"
}Receiving Messages (Webhooks)
When someone texts your AgentPhone number, we send a POST request to your configured webhook URL with this payload:
{
"event": "message.inbound",
"channel": "sms",
"from": "+15551234567",
"to": "+15559876543",
"body": "Hello agent",
"media": [],
"timestamp": "2026-02-24T15:30:00.000Z",
"message_id": "msg_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"signature": "hmac-sha256-hex-string..."
}| Field | Type | Description |
|---|---|---|
event | string | "message.inbound" |
channel | string | "sms" or "mms" |
from | string | Sender's phone number (E.164 format) |
to | string | Your AgentPhone number |
body | string | Message text content |
media | string[] | Media URLs for MMS attachments. Empty for plain SMS. |
timestamp | string | ISO 8601 timestamp |
message_id | string | Unique message identifier |
signature | string | HMAC-SHA256 signature for verification (see below) |
Responding to Messages
Your webhook handler should return a JSON response telling AgentPhone what to do. You have up to 10 seconds (configurable) to respond.
{
"reply": "Hello! How can I help you today?",
"action": "respond"
}{
"action": "ignore"
}| Field | Type | Description |
|---|---|---|
reply | string | Text to send back to the sender. |
media | string[] | Optional. Public URLs for MMS attachments. |
action | string | "respond" to reply, "ignore" to acknowledge silently. |
{"action":"ignore"} immediately, then use the POST /api/numbers/:id/send/sms endpoint to reply asynchronously when ready.Webhook Verification
Every webhook includes a signature field and an X-AgentPhone-Signature header containing an HMAC-SHA256 hex digest. Verify this to confirm the request came from AgentPhone.
import crypto from "crypto";
function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex")
);
}
app.post("/webhook", (req, res) => {
const sig = req.headers["x-agentphone-signature"];
if (!verifyWebhook(JSON.stringify(req.body), sig, WEBHOOK_SECRET)) {
return res.status(401).json({ error: "Invalid signature" });
}
res.json({ reply: "Got it!", action: "respond" });
});import hmac, hashlib
def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)
@app.post("/webhook")
async def handle(request: Request):
raw = await request.body()
sig = request.headers.get("X-AgentPhone-Signature", "")
if not verify_webhook(raw, sig, WEBHOOK_SECRET):
raise HTTPException(401, "Invalid signature")
return {"reply": "Got it!", "action": "respond"}Voice AI API
AgentPhone provides hosted AI APIs for speech-to-text, text-to-speech, and chat completions. These are OpenAI-compatible, so you can use existing SDKs by changing the base URL.
from openai import OpenAI
client = OpenAI(
api_key="agp_your_api_key_here",
base_url="https://agentphone.primary.net/api/v1"
)
# Chat completion
response = client.chat.completions.create(
model="Qwen3-Next-80B",
messages=[{"role": "user", "content": "Hello!"}]
)
# Speech-to-text
with open("audio.wav", "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-large-v3",
file=f
)
# Text-to-speech
audio = client.audio.speech.create(
input="Hello world",
voice="tara"
)import OpenAI from "openai";
const client = new OpenAI({
apiKey: "agp_your_api_key_here",
baseURL: "https://agentphone.primary.net/api/v1",
});
const completion = await client.chat.completions.create({
model: "Qwen3-Next-80B",
messages: [{ role: "user", content: "Hello!" }],
});Speech-to-Text
Whisper large-v3. Supports wav, mp3, webm, and more.
Text-to-Speech
Orpheus TTS with 24 natural voices. Returns wav audio.
Chat Completions
Qwen3-Next-80B. Supports streaming.
Speech-to-Text
Transcribe audio files using our hosted Whisper model.
/api/v1/audio/transcriptionsTranscribe an audio file. Accepts multipart/form-data with the audio file.
Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: multipart/form-dataRequest Body
file: <audio file (wav, mp3, webm, etc.)>
model: "whisper-large-v3" (optional)Response
{
"text": "Hello, how can I help you today?"
}Text-to-Speech
Generate speech audio from text using our hosted Orpheus TTS model with 24 available voices.
/api/v1/audio/speechConvert text to speech audio.
Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body
{
"input": "Hello, welcome to AgentPhone!",
"voice": "tara"
}Response
Content-Type: audio/wav
(binary audio data)/api/v1/voicesList all available TTS voices.
Headers
Authorization: Bearer YOUR_API_KEYResponse
{
"voices": [
{ "id": "tara", "name": "Tara" },
{ "id": "leah", "name": "Leah" },
{ "id": "jess", "name": "Jess" },
...
]
}Chat Completions
Access our hosted LLM for chat completions. OpenAI-compatible API.
/api/v1/chat/completionsGenerate a chat completion using our hosted model.
Headers
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Body
{
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "What is AgentPhone?" }
],
"stream": false
}Response
{
"id": "chatcmpl-abc123",
"choices": [
{
"message": {
"role": "assistant",
"content": "AgentPhone is a phone carrier for AI agents..."
}
}
]
}/api/v1/modelsList available models.
Headers
Authorization: Bearer YOUR_API_KEYResponse
{
"data": [
{ "id": "Qwen3-Next-80B", "object": "model" }
]
}Errors
All errors return a consistent JSON structure.
{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}| Status | Meaning |
|---|---|
400 | Bad Request — invalid or missing parameters |
401 | Unauthorized — invalid or missing API key |
404 | Not Found — resource does not exist |
429 | Rate Limited — too many requests |
500 | Server Error |
Pricing
$29/month per number
Includes 2,000 SMS segments and 300 voice minutes per month.
Voice AI APIs billed at $0.03/minute.
Overage rates (if enabled)