Calls

Place outbound calls from your Indian number, stream them to your agent, check call status, hang up, and receive status webhooks.

3 min read

Place an outbound call from a number you own, then track it with status webhooks or by polling.

Method Path What it does
POST /calls Place an outbound call
GET /calls/{callSid} Get a call
DELETE /calls/{callSid} Hang up
POST GET DELETE /Accounts/{accountSid}/Calls[/{callSid}] The same three endpoints, account-scoped

The /Accounts/{accountSid}/Calls routes behave exactly like /calls and return the same response. accountSid is your account SID (AC_…) or workspace ID; any other value returns 403 FORBIDDEN.

Base URL https://voice-api.edesy.in/v1, Bearer API key. See Authentication.

Place a call#

POST /calls

The from number must be one you own and have registered for outbound.

Field Type Required Notes
from string Yes Your number, E.164
to string or object Yes E.164, or { "type": "phone", "number": "+91…" }
stream_url string One of Stream call audio to your WebSocket agent
application_id string One of A saved application; application_sid is accepted as an alias
url string One of A URL that returns call instructions (method: GET or POST)
text string One of Text to speak (max 2000 characters), with optional voice and language
stream_sample_rate integer No 8000 or 16000, for stream_url
status_callback string No URL for status webhooks
status_method string No POST (default) or GET
timeout integer No Seconds to ring, 5 to 600
caller_name string No Max 50 characters
machine_detection string No Enable or DetectMessageEnd
custom_parameters object No Your own key-values, returned with the call; tag is an alias

Send exactly one of stream_url, application_id, url or text. Unknown fields are ignored and listed in meta.ignored_fields, so check that list if a setting seems to have no effect.

curl -X POST https://voice-api.edesy.in/v1/calls \
  -H "Authorization: Bearer vp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+917969002802",
    "to": "+919812345678",
    "stream_url": "wss://agent.example.com/ws",
    "status_callback": "https://example.com/hooks/call-status",
    "timeout": 60,
    "custom_parameters": { "lead_id": "L-5521" }
  }'

Response 201:

{
  "data": {
    "call_sid": "f4590c42-1a14-4a5f-b526-32f2a4c09018",
    "sid": "f4590c42-1a14-4a5f-b526-32f2a4c09018",
    "account_sid": "AC_1a2b3c4d",
    "from": "+917969002802",
    "to": "+919812345678",
    "direction": "outbound",
    "status": "queued",
    "created_at": "2026-10-08T09:31:02Z",
    "custom_parameters": { "lead_id": "L-5521" }
  },
  "meta": { "request_id": "req_8c1d", "timestamp": "2026-10-08T09:31:02Z" }
}

sid is the same value as call_sid. Once known, the call also carries answered_at, ended_at, duration, price (amount, currency), hangup_cause and answered_by.

Get a call#

GET /calls/{callSid} returns the same data object with the latest status.

Hang up#

DELETE /calls/{callSid} ends an active call and returns 204 with no body. A call that has already ended returns 409 CALL_ENDED.

Status webhooks#

Set status_callback on the call, or save one on the application, and the platform reports each status change:

CallStatus Meaning
initiated The call is being set up
ringing The callee's phone is ringing
in-progress Answered
completed Ended normally
busy The line was busy
no-answer Not answered before timeout
failed The call couldn't be connected
stream-failed The audio stream to your stream_url failed; ErrorMessage says why

POST sends JSON and GET sends query parameters:

{
  "CallSid": "f4590c42-1a14-4a5f-b526-32f2a4c09018",
  "From": "+917969002802",
  "To": "+919812345678",
  "CallStatus": "in-progress",
  "Direction": "outbound",
  "Timestamp": "2026-10-08T09:31:09Z",
  "Custom": { "lead_id": "L-5521" }
}

Duration is added when the call ends. Match events to calls by CallSid, or by your custom_parameters in Custom.

  • Delivery times out after 30 seconds and is retried up to 5 times, so make your handler idempotent.
  • Requests carry User-Agent: VoicePlatform-Webhook/1.0.
  • If a signing secret is set on your account, each request also carries X-Webhook-Timestamp and X-Webhook-Signature: v1=<hex>, an HMAC-SHA256 of "<timestamp>.<body>". Recompute it and reject mismatches.

Errors#

HTTP code When
400 VALIDATION_ERROR Invalid body or no call instructions; details.errors lists each field
402 INSUFFICIENT_BALANCE Wallet balance is too low
403 NUMBER_NOT_OWNED from isn't a number on your account
403 FORBIDDEN accountSid in the path isn't yours
404 NOT_FOUND No call with that SID
409 CALL_ENDED The call has already ended
503 SERVICE_UNAVAILABLE No carrier capacity right now; retry with backoff

See Error Codes for the error format.

Was this page helpful? Suggest an edit