Guides
Outbound calling
Place a call, pass variables, schedule it, retry it, stop it, and understand why a call was not placed.
One request places one call. The API answers at once with an execution id; the call itself runs in the background and you follow it by polling the execution or by webhooks.
In the dashboard: the call button in Agent Studio, and Monitor → Call History for results.
Place a call
curl -X POST https://api.sevennadi.si/call \
-H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "3c90c3cc-0d44-4b50-8822-8dd25736052a",
"recipient_phone_number": "+919876500123",
"from_phone_number": "+918012345678",
"user_data": {"name": "Asha", "due_date": "20 October"}
}'{"message": "done", "status": "queued", "execution_id": "b8f0c9a2-3e5d-4c1b-9f7a-2d6e8c4b1a90"}| Field | Required | Meaning |
|---|---|---|
agent_id | yes | The agent that makes the call |
recipient_phone_number | yes | E.164, for example +919876500123 |
from_phone_number | no | Caller ID, E.164. See Inbound and numbers |
user_data | no | Variables for the prompt and welcome message |
scheduled_at | no | When to call, ISO 8601 with a UTC offset |
retry_config | no | Automatic retries, below |
agent_data | no | Per-call overrides: engine, webhook_url, pre_call_webhook_url |
bypass_call_guardrails | no | true skips the calling-hours check for this call |
The status in the response is always queued. The execution holds the real status.
Variables
Keys of user_data fill {name} and {{name}} placeholders in the welcome message and in the prompt. They are also available to function tools and graph conditions.
Schedule a call
{"agent_id": "3c90c3cc-0d44-4b50-8822-8dd25736052a",
"recipient_phone_number": "+919876500123",
"scheduled_at": "2026-10-14T10:30:00+05:30"}The time must carry an offset (+05:30, or Z) and be at least two minutes ahead. Otherwise: scheduled_at must include a UTC offset, e.g. +00:00 or Scheduled time should be at least 2 minutes in the future. The execution starts as scheduled.
Statuses
| Phase | Statuses |
|---|---|
| Not dialled yet | scheduled, queued, rescheduled |
| Live | initiated, ringing, in-progress |
| Line dropped, post-call work running | call-disconnected |
| Final | completed, no-answer, busy, failed, canceled, stopped, error, balance-low |
A normal call goes queued → initiated → ringing → in-progress → call-disconnected → completed. The transcript, cost, summary and extraction are final only at completed. Nothing leaves a final status.
Read it with GET /executions/{execution_id}; see Post-call data.
Concurrency
Your account has a limit on simultaneous calls, set by its plan. A call over the limit stays queued and is tried again every second until a line is free. On the own engine, calls also wait while the engine reports that it is full.
Automatic retries
{"retry_config": {"enabled": true, "max_retries": 2,
"retry_on_statuses": ["no-answer", "busy", "failed"],
"retry_on_voicemail": false,
"retry_intervals_minutes": [30, 60, 120]}}| Field | Default |
|---|---|
enabled | false |
max_retries | 3 (never more than 3) |
retry_on_statuses | no-answer, busy, failed |
retry_on_voicemail | false |
retry_intervals_minutes | 30, 60, 120. The last value repeats if there are more retries than intervals |
A retried call keeps its execution id. It goes back to scheduled and dials again after the interval. While retries are enabled, the execution and its webhooks carry retry_count and retry_config, and context_details.retry_history lists each failed attempt.
Stop a call
curl -X POST https://api.sevennadi.si/call/b8f0c9a2-3e5d-4c1b-9f7a-2d6e8c4b1a90/stop \
-H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"{"message": "done", "status": "stopped", "execution_id": "b8f0c9a2-3e5d-4c1b-9f7a-2d6e8c4b1a90"}A call that has not been dialled becomes stopped immediately. A live call is hung up by the worker shortly after and then becomes stopped; a call stopped mid-conversation keeps its transcript and is still billed. A call that already finished answers 400 with Execution is already completed (or its status).
POST /v2/agent/{agent_id}/stop stops every call of an agent that has not started dialling, and returns their ids in stopped_executions.
When a call is not placed
Compliance rules are checked when you create the call and again just before dialling. See Compliance.
| Situation | What you get |
|---|---|
| Number is on your do-not-call list | 400 Call not placed: suppressed: the number is on the account's do-not-call list |
Number is registered and dnd_check is block | 400 Call not placed: dnd: the number is on a do-not-disturb registry |
| Daily cap for the number reached | 429 Call not placed: frequency cap: already 3 outbound attempts to this number today |
| Outside the agent's calling hours | 200. The call is created rescheduled for the next allowed start; the response adds "rescheduled": true and scheduled_at |
dnd_check is warn and the number is registered | 200 with a warnings list |
| Account restricted to verified numbers | 403 naming the unverified number |
| A rule fails later, at dial time | The execution ends canceled with error_message starting Call not placed: |
Wallet balance
Balance is checked just before dialling. With a balance of zero or less, a single call ends balance-low with error_message Insufficient wallet balance, and nothing is charged. Calls that belong to a batch wait instead; see Batches. Costs are explained in Billing.
Other errors
| Status | Message |
|---|---|
| 400 | agent_id is required, recipient_phone_number is required |
| 400 | recipient_phone_number must be in E.164 format, e.g. +919876543210 |
| 400 | Invalid from_phone_number |
| 404 | Agent not found |
To make a request safe to repeat, send an Idempotency-Key; see Idempotency.
Limitations
- Real dialling needs the operator to run live telephony with provider credentials. In mock telephony mode nothing is dialled; see Testing without a phone.
- The balance is not re-checked during a call, so a long call can take the wallet below zero.
- A call whose background job failed permanently stays
queueduntil it is requeued, or until a cleanup job marks iterror. - The daily cap is enforced only in live telephony mode and never counts
mockengine calls.