Create a project at agentphone.ai to get your API key, then follow the Quick Start to provision a phone number and configure a webhook.
Currently, US and Canadian phone numbers are supported. You can request a specific area code when provisioning. International numbers are coming soon.
Every account starts with $5.00 in free credit — enough to provision a number and start making calls with no credit card required. Phone numbers cost $3.00/month each, and you can provision up to 10 numbers self-serve. Call recording is an optional add-on at $5.00/month. Need more numbers? Contact us and we’ll increase your limit.
You can request a preferred area code (US/CA only) using the areaCode parameter when provisioning. The exact number is automatically selected from available inventory.
The number is released back to the carrier pool and cannot be recovered. All message and conversation history is preserved for audit purposes.
No. Each phone number is attached to a single agent. Create separate numbers for different agents.
By default, the first attached number is used. To choose a specific number, pass fromNumberId in your POST /v1/calls request. Both numbers will still receive inbound calls and SMS independently — each number maintains its own conversation threads.
Yes. US carriers require all businesses sending SMS from 10-digit phone numbers to register through 10DLC (10-Digit Long Code). Receiving inbound SMS works immediately — no registration needed. To enable outbound SMS, schedule a call with us and we’ll handle the registration for you. Voice calls are not affected.
Yes! Web calls let users talk to your agent directly from the browser — no PSTN phone number required. Call POST /v1/calls/web with an agentId to get an access token, then pass it to the AgentPhone Web SDK on your frontend. Webhooks, transcripts, and agent.call_ended events work the same as phone calls. See Code Examples > Browser Web Call.
voiceMode: "webhook") — Caller speech is transcribed and sent to your webhook. You control every response with your own LLM or logic.voiceMode: "hosted") — A built-in LLM handles the conversation using your systemPrompt. No webhook or server needed.See the Calls guide for detailed call flows.
Use streaming NDJSON responses. Send an interim chunk like {"text": "Let me check on that.", "interim": true} immediately, then stream the real answer. TTS starts speaking on the first chunk — the caller hears natural speech instead of silence.
See Best Practices > Voice Latency for more detail.
Voice webhooks have a 30-second default timeout (configurable from 5–120 seconds per webhook via the timeout field). If your server doesn’t begin responding in time, the request is cancelled and the caller hears nothing for that turn.
This commonly happens when your webhook runs LLM tool calls (e.g., calendar lookup, database query) that take too long. The fix is to always stream an NDJSON interim chunk like {"text": "One moment, let me check.", "interim": true} immediately before doing any slow work.
See Calls > Troubleshooting for more causes and fixes.
Yes. Both voice modes support barge-in — the caller can interrupt mid-sentence. The platform handles interruptions automatically.
Yes. Set transferNumber on your agent (E.164 format, e.g. +14155551234) and callers can be cold-transferred mid-call.
{"action": "transfer"} in the voice response.To clear the transfer destination, send "transferNumber": "" in the update request.
Yes. Return {"digits": "1"} in your voice webhook response to press keypad digits. This sends DTMF tones to navigate automated phone systems. You can press multiple digits at once (e.g. "123") and use * or #. The field aliases press_digit and dtmf also work.
In hosted mode, the built-in LLM presses digits automatically when prompted by the phone system — no webhook logic required.
Use GET /v1/agents/voices to list all available voices. You can set the voice when creating an agent, updating an agent, or making an outbound call.
Call recording is an optional add-on ($5/month) that captures audio for all voice calls. Enable it from the Billing page in the dashboard. When active, completed calls include a recordingUrl in the API response. The recordingAvailable field tells you whether a recording exists even if the add-on is not currently enabled. See Calls > Call recording for details.
Use ngrok or localtunnel to expose your local server to the internet, then register the public URL as your webhook. See the Testing guide for a step-by-step walkthrough.
Webhooks are automatically retried with exponential backoff — up to 6 attempts over roughly 24 hours (immediate, 5 min, 30 min, 2h, 6h, 12h). Failed deliveries are logged and visible via GET /v1/webhooks/deliveries.
Yes, three ways: (1) the agent.call_ended webhook includes the complete transcript (not limited by contextLimit), (2) call GET /v1/calls/:id/transcript at any time, or (3) use GET /v1/calls/:id/transcript/stream to replay the full transcript as an SSE stream.
Yes. GET /v1/calls/:id/transcript/stream opens a Server-Sent Events stream that replays existing turns on connect and then delivers new turns as they happen in real time. The stream sends connected, turn, and ended events. It works for both live and completed calls — same URL. See Calls > Stream transcript (SSE) for the full event reference and code examples.
Each event is delivered to exactly one endpoint (the per-agent webhook if configured, otherwise the project default). However, retries can cause the same event to arrive multiple times. Always use the X-Webhook-ID header for idempotency.
Use HMAC-SHA256 with your webhook secret. The signed string is {timestamp}.{raw_body}. Always check the timestamp is within 5 minutes to prevent replay attacks. See Webhooks > Security for code examples in Python and Node.js.
conversationState?Custom metadata you store on a conversation via PATCH /v1/conversations/:id. This state is included in every webhook payload, enabling your AI backend to maintain context across messages without managing state yourself.
You’ll receive a 429 Too Many Requests response with a Retry-After header. Implement exponential backoff when retrying. See the Error Handling guide.
Check the error response format (all errors return a consistent JSON structure with message, code, type, and optional details). Retry transient errors (429, 500, 502) with exponential backoff. See the Error Handling guide for the full reference.
Official SDKs for TypeScript/JavaScript (npm install agentphone) and Python (pip install agentphone). Both support all API operations.
The AgentPhone MCP server lets AI assistants (Cursor, Claude Desktop, Windsurf) provision numbers, send SMS, and make calls through natural language. See the MCP guide.
Sign up at agentphone.ai and create an API key from your project settings.