Programmatic phone calls
Guide: Programmatic phone calls
Place a real outbound PSTN phone call with any of your agents from your own backend. Telenow dials the number, the agent runs the full voice pipeline, and the call appears in your history with a transcript and (optionally) a recording — just like a call placed from the dashboard.
This is the phone counterpart to Programmatic web calls: web calls run in a browser, phone calls go out over the carrier network.
Shortcut: with the backend SDKs this whole guide is one call —
tn.calls.create({ agentId, to })(Node) ortn.create_call(agent_id, to)(Python).
Prerequisites
- An agent (any agent in your organization can place calls).
- A phone number purchased and assigned to that agent — it becomes the caller ID. See Phone numbers.
- Authentication: an API key (recommended for server‑to‑server) or a user JWT +
X-Org-Id.
Calls are always attributed and run through your Do‑Not‑Call list, whichever auth you use.
1. Place the call
POST /api/sessions/initiate-call
curl -X POST https://api.telenow.ai/api/sessions/initiate-call \
-H "x-api-key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{
"agentId": "…",
"mobileNumber": "+14155550123",
"firstResponse": "Hi, this is Acme calling about your appointment.",
"machineDetection": "hangup"
}'
Prefer a user token? Send
Authorization: Bearer <token>andX-Org-Id: <orgId>instead of the API key (get the token fromPOST /api/auth/login).
| Field | Type | Notes |
|---|---|---|
agentId | UUID | Required. The agent that runs the call |
mobileNumber | string | Required. Destination in E.164 |
firstResponse | string | Optional. Overrides the agent's opener (the first line it speaks) for this call only, and forces the agent to speak first. Omit to use the agent's configured outbound opener |
machineDetection | string | "true" (continue if a machine answers) or "hangup" (drop on machine) |
userId | UUID | Optional attribution |
callType | string | Optional |
Response:
{ "success": true, "data": { "sessionId": "…", "status": "active" } }
Numbers on your Do‑Not‑Call list are blocked automatically.
2. Monitor the call
- Webhooks (recommended): subscribe to
call.started,call.ended, andrecording.readyto be notified without polling. See Webhook events. - Poll:
GET /api/sessions/{sessionId}for live status,GET /api/sessions/{sessionId}/messagesfor the transcript so far. - History: after it ends, the call is under
GET /api/orgs/{orgId}/calls.
3. Transfer mid-call (optional)
You can hand the call off to a human or another number two ways:
- Let the agent decide — give the agent a native transfer tool so it transfers when the conversation calls for it. See Tools & function calling.
- Trigger it yourself —
POST /api/sessions/{id}/transferwarm‑transfers an active call.
Bulk dialing
To dial many contacts on a schedule (with calling windows, AMD, and retries), use Outbound campaigns / the Campaigns API instead of calling initiate-call in a loop.