Outbound IVR Calls

POST /v1/ivr/calls - call an Indian number and run a published IVR flow with per-call variables, a reference ID, a signed status callback and an idempotency key.

4 min read

Base URL
https://voice-api.edesy.in/v1/ivr
Auth
Authorization: Bearer sk_...Get a key

POST/v1/ivr/calls calls an Indian phone number and runs one of your published IVR flows on the call. Pass per-call variables (used as {{var.name}}), your own reference_id, and a status_callback_url that receives the signed result when the call ends. An Idempotency-Key header makes retries safe. DNC and 09:00-21:00 IST calling hours are enforced.

POSThttps://voice-api.edesy.in/v1/ivr/calls202 Accepted

Request body#

Field Type Required Notes
flow_id string (UUID) Required The flow must be published
to string Required Indian number: 9800000000, 919800000000 or +919800000000
from string Optional One of your numbers. Default: your first number assigned to IVR
variables object Optional Strings, numbers or booleans. Used as {{var.<name>}}. See limits
reference_id string Optional Your own ID, up to 128 characters. Echoed in callbacks and available as {{reference_id}}
status_callback_url string Optional https:// only, up to 2048 characters. Receives the call result
ring_timeout_sec integer Optional 10 to 60. Default 45

Headers#

Header Notes
Authorization: Bearer sk_... or X-API-Key: sk_... Required
Idempotency-Key Optional, up to 128 characters. See idempotency
Content-Type: application/json Required

Example#

curl -X POST https://voice-api.edesy.in/v1/ivr/calls \
  -H "Authorization: Bearer $EDESY_API_KEY" \
  -H "Idempotency-Key: order-A123-confirm" \
  -H "Content-Type: application/json" \
  -d '{
    "flow_id": "5b1c2f0e-0000-4000-8000-000000000000",
    "to": "+919800000000",
    "variables": { "order_id": "A123", "name": "Ravi", "amount": 499 },
    "reference_id": "crm-lead-42",
    "status_callback_url": "https://crm.example.com/ivr/status"
  }'
Response202
{
  "data": {
    "call_sid": "a1b2c3d4-0000-4000-8000-000000000000",
    "call_log_id": "7f3e2d1c-0000-4000-8000-000000000000",
    "status": "queued",
    "reference_id": "crm-lead-42"
  }
}

How it works#

  1. Edesy checks the flow is published, the number is valid and not on your do-not-call list, the time is within calling hours, your wallet has balance, and you are under the concurrency limit.
  2. The call is queued and dialled from from (or your default IVR number).
  3. When the person answers, the flow runs with your variables filled in.
  4. HTTP Request nodes in the flow call your API as the caller presses keys.
  5. When the call ends, Edesy POSTs the result to status_callback_url.

Idempotency#

Send Idempotency-Key: <unique string> to make retries safe:

  • The same key and body within 24 hours returns the original response and does not dial again.
  • The same key with a different body returns 422 idempotency_key_reused.
  • A repeat while the first request is still being processed returns 409 idempotency_key_in_use.

Errors#

HTTP code Meaning
400 invalid_request Body is not valid JSON
400 validation_error Bad field, variables, callback URL or Idempotency-Key
400 invalid_phone to is not a valid Indian number
400 no_caller_id No from and no number assigned to IVR
402 insufficient_balance Top up your wallet
403 from_not_owned from is not one of your numbers
404 flow_not_found No such flow in this workspace
409 flow_not_published Publish the flow first
409 idempotency_key_in_use The same key is still being processed
422 idempotency_key_reused Same key, different body
422 dnc_suppressed The number is on your do-not-call list
422 outside_calling_hours Outside 09:00-21:00 IST
429 concurrency_limit Too many of your API calls are in progress
502 carrier_error The carrier rejected the call

Get a call#

GEThttps://voice-api.edesy.in/v1/ivr/calls/{call_sid}200 OK

Returns the call log for any IVR call (API, inbound, test or order automation): status, duration, price, dtmf_path, variables, reference_id, call_outcome, and http_requests (every HTTP request the flow made during the call). Secret-looking header values are masked. Unknown calls return 404 not_found.

To list API calls, use GET/v1/ivr/call-logs?source=api&reference_id=crm-lead-42. See Logs API.

Status callback#

When the call ends, Edesy sends POST to your status_callback_url. It is signed like HTTP Request nodes and makes up to 5 attempts, with backoff, if your endpoint fails.

Status callback payload
{
  "event": "ivr.call.completed",
  "timestamp": "2026-10-28T10:15:00Z",
  "data": {
    "call_sid": "a1b2c3d4-0000-4000-8000-000000000000",
    "call_log_id": "7f3e2d1c-0000-4000-8000-000000000000",
    "reference_id": "crm-lead-42",
    "flow_id": "5b1c2f0e-0000-4000-8000-000000000000",
    "flow_version": 3,
    "from": "918000000000",
    "to": "919800000000",
    "status": "completed",
    "hangup_cause": "normal",
    "sip_status": 0,
    "call_outcome": "answered",
    "duration_sec": 42,
    "price": 1.5,
    "currency": "INR",
    "dtmf_path": ["1"],
    "variables": { "order_id": "A123" },
    "http_requests": [ { "node_id": "http-1", "status": "delivered", "response_code": 200 } ],
    "answers": [ { "question_key": "city", "question": "Which city are you calling from?", "transcript": "Lucknow", "status": "captured", "attempt": 1 } ]
  }
}
Field Values
event ivr.call.completed, ivr.call.no-answer, ivr.call.busy, ivr.call.canceled, ivr.call.failed
hangup_cause normal for an answered call. Otherwise the reason: busy, rejected, no_answer, unavailable, invalid_number, call_blocked, network_timeout, carrier_error, caller_canceled, call_failed
sip_status The SIP response code for a call that did not connect. A 480 (switched off) is reported as no-answer, a 603 as busy
call_outcome answered, callee, unreachable, invalid_number, network (usually temporary; retry later), account or platform (Edesy could not place it)
answers Spoken answers from Ask nodes

Status callbacks are listed in HTTP Logs with the kind Status callback.

Limits#

Limit Value
Variables per call 20 keys. Name [a-zA-Z_][a-zA-Z0-9_]{0,63}, value up to 512 characters, 4 KB in total
Concurrent API calls 10 per workspace by default. Ask support to raise it
Calling hours 09:00-21:00 IST
Do-not-call list Numbers on your DNC list are refused with dnc_suppressed
Ring timeout 10 to 60 seconds, default 45

Pricing#

Rs 1.50 per minute, billed per started minute from your wallet. Unanswered calls are free. Prices exclude 18% GST. See Pricing.

Was this page helpful?