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

bash
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"}
  }'
json
{"message": "done", "status": "queued", "execution_id": "b8f0c9a2-3e5d-4c1b-9f7a-2d6e8c4b1a90"}
FieldRequiredMeaning
agent_idyesThe agent that makes the call
recipient_phone_numberyesE.164, for example +919876500123
from_phone_numbernoCaller ID, E.164. See Inbound and numbers
user_datanoVariables for the prompt and welcome message
scheduled_atnoWhen to call, ISO 8601 with a UTC offset
retry_confignoAutomatic retries, below
agent_datanoPer-call overrides: engine, webhook_url, pre_call_webhook_url
bypass_call_guardrailsnotrue 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

json
{"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

PhaseStatuses
Not dialled yetscheduled, queued, rescheduled
Liveinitiated, ringing, in-progress
Line dropped, post-call work runningcall-disconnected
Finalcompleted, 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

json
{"retry_config": {"enabled": true, "max_retries": 2,
                  "retry_on_statuses": ["no-answer", "busy", "failed"],
                  "retry_on_voicemail": false,
                  "retry_intervals_minutes": [30, 60, 120]}}
FieldDefault
enabledfalse
max_retries3 (never more than 3)
retry_on_statusesno-answer, busy, failed
retry_on_voicemailfalse
retry_intervals_minutes30, 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

bash
curl -X POST https://api.sevennadi.si/call/b8f0c9a2-3e5d-4c1b-9f7a-2d6e8c4b1a90/stop \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"
json
{"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.

SituationWhat you get
Number is on your do-not-call list400 Call not placed: suppressed: the number is on the account's do-not-call list
Number is registered and dnd_check is block400 Call not placed: dnd: the number is on a do-not-disturb registry
Daily cap for the number reached429 Call not placed: frequency cap: already 3 outbound attempts to this number today
Outside the agent's calling hours200. 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 registered200 with a warnings list
Account restricted to verified numbers403 naming the unverified number
A rule fails later, at dial timeThe 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

StatusMessage
400agent_id is required, recipient_phone_number is required
400recipient_phone_number must be in E.164 format, e.g. +919876543210
400Invalid from_phone_number
404Agent 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 queued until it is requeued, or until a cleanup job marks it error.
  • The daily cap is enforced only in live telephony mode and never counts mock engine calls.