API documentation
Create AI agents, buy numbers and place calls over REST. Get a key from the Developers page.
Authentication
Send your key as a Bearer token. Use ak_test_… keys while building: no real calls are made.
Base URL: https://api-production-9c6d.up.railway.app/api/v1 Authorization: Bearer ak_test_...
Errors are {"detail": "..."} with a standard HTTP status. A 429 includes Retry-After.
Place a call
Send an Idempotency-Key so a network retry never dials twice.
curl -X POST https://api-production-9c6d.up.railway.app/api/v1/calls \
-H "Authorization: Bearer ak_test_..." \
-H "Idempotency-Key: 7d1c0c5e-..." \
-H "Content-Type: application/json" \
-d '{"direction":"outbound","to_number":"+919876543210","from_number":"+14155550100","ai_agent_id":"<id>"}'Inbound calls
Customers call a number you own; the AI agent attached to it answers. Provision or register a number, attach an agent, then subscribe to call.started, call.ended and call.transcript_ready webhooks to get each call and its transcript. Poll GET /calls?direction=inbound if you prefer. A number with no agent rejects calls cleanly.
curl -X PATCH https://api-production-9c6d.up.railway.app/api/v1/phone-numbers/<number id> \
-H "Authorization: Bearer ak_live_..." \
-H "Content-Type: application/json" \
-d '{"ai_agent_id":"<agent id>"}'Scopes: numbers:read, numbers:write (also lets the key edit agents), calls:read.
Testing without dialling
A ak_test_ key never reaches the phone network. POST /calls with either direction returns a completed call and fires call.started and call.ended (with test_mode: true) to your webhooks, so you can build and verify your handlers first.
Endpoints
/callsPlace an outbound AI call (test keys: simulate either direction)/calls?direction=inbound|outbound&status=…List and filter calls/calls/{id}/transcriptTurn-by-turn transcript/ai-agentsCreate an AI agent (prompt, language, voice)/ai-agents/{id}Update or activate an agent/ai-agents/{id}/toolsEnable tools such as transfer_call or create_ticket/phone-numbers/availableSearch numbers you can buy/phone-numbers/provisionBuy a number and attach an agent (real cost)/phone-numbersRegister a number you already own/phone-numbers/{id}Route inbound calls to another agent, or none/phone-numbers/{id}Stop routing a number (does not release it at Twilio)/customersCreate a customer/campaignsCreate an outbound campaign/campaigns/{id}/launchStart dialling a campaignWebhooks
Events: call.startedcall.endedcall.transcript_readyticket.createdmessage.receivedcampaign.completed
Each delivery has X-Timestamp and X-Signature (HMAC-SHA256 of timestamp.body with your signing secret). Reject anything older than 5 minutes. Failed deliveries are retried with backoff.
const expected = crypto
.createHmac("sha256", SIGNING_SECRET)
.update(`${req.headers["x-timestamp"]}.${rawBody}`)
.digest("hex")
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-signature"]))) reject()Calling Indian numbers for commercial purposes requires TRAI DLT registration and DND scrubbing. You are responsible for consent.