Place calls via API
After this page, your backend can trigger a real phone call with one POST. Qalyb dials the number, runs the agent, and reports back via the API and webhooks when the call completes.
+971501234567)Place the call
One POST does it. The endpoint is scoped to the agent that will run the call: POST /v1/agents/{id}/calls.
curl -X POST https://api.qalyb.ai/v1/agents/agt_abc123/calls \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+971501234567",
"variables": {
"customer_name": "Layla",
"appointment_window": "Sunday afternoon"
}
}'From the TypeScript SDK:
import { Qalyb } from '@qalyb/sdk';
const qalyb = new Qalyb({ apiKey: process.env.QALYB_API_KEY! });
const call = await qalyb.agents.startCall('agt_abc123', {
phoneNumber: '+971501234567',
variables: {
customer_name: 'Layla',
appointment_window: 'Sunday afternoon',
},
});
console.log(call.id, call.status);What you get back
You get back a call record immediately. The call is now queued — Qalyb dials within a second or two and transitions through ringing, in_progress, then completed or failed.
{
"id": "call_abc123",
"agentId": "agt_abc123",
"phoneNumber": "+971501234567",
"status": "queued",
"createdAt": "2026-05-09T12:34:56Z"
}Fetch a call later
GET /v1/calls/{id} returns the latest status, duration, and (when available) the transcript turns.
curl https://api.qalyb.ai/v1/calls/call_abc123 \
-H "Authorization: Bearer sk-live-..."List calls for an agent
GET /v1/agents/{id}/calls returns recent calls scoped to the agent. Filter with status and limit (max 100).
curl "https://api.qalyb.ai/v1/agents/agt_abc123/calls?limit=20" \
-H "Authorization: Bearer sk-live-..."Polling vs. webhooks
For one-off scripts, polling GET /v1/calls/{id} works fine. For production, register a webhook on call.completed and call.failed instead — much less noisy and you get the transcript URL in the same payload.
Variables and personalization
The variables object is interpolated into the agent's system prompt with {{name}} placeholders. Use it to inject anything dynamic — customer names, order IDs, dates — without forking your agent for every campaign.
Common errors
| Status | Meaning |
|---|---|
400 | Phone number isn't valid E.164, or the agent isn't a voice agent. |
401 | API key missing or revoked. |
402 | Account doesn't have enough credit for the destination country. |
404 | Agent ID doesn't exist in this workspace. |
