Webhook Setup

Receive every missed call in real time as a call.missed JSON POST - payload, headers, HTTPS rules, the 5-second reply window and the test button.

2 min read

A webhook sends each missed call to your URL as it happens, as one JSON POST per call.

1. Add your URL#

In the portal open Webhook, paste your URL, optionally add a secret, and save. You can also do this with the webhook subscriptions API:

curl -X POST https://voice-api.edesy.in/v1/webhooks/subscriptions \
  -H "Authorization: Bearer vp_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://crm.example.com/webhooks/missed-call",
    "secret": "a-long-random-string",
    "event_types": ["call.missed"]
  }'

Rules for the URL:

  • It must use HTTPS.
  • It must be publicly reachable. Private and internal addresses are refused, and redirects are not followed, except the one a Google Apps Script web app makes to script.googleusercontent.com (see Send Leads to Google Sheets).

2. Handle the request#

POST https://crm.example.com/webhooks/missed-call
Content-Type: application/json
X-Edesy-Signature: sha256=3b9f...   (only when a secret is set)
{
  "event": "call.missed",
  "timestamp": "2026-10-18T07:50:33Z",
  "data": {
    "call_sid": "CA_e5353a30-5f34-4582-bb9c-830ab7b513ef",
    "from": "+918273237781",
    "to": "+919484958085",
    "direction": "inbound",
    "status": "missed",
    "sip_status": 486,
    "phone_number_id": "5e229f03-af3c-47f5-be45-5b11583a7c55",
    "phone_number_name": "Campaign"
  }
}
Field Meaning
event Always call.missed for a missed call
timestamp When the event was sent, UTC, RFC 3339
data.call_sid Unique id of the call. Retries and replays carry the same value; use it to drop duplicates
data.from The caller's number in E.164 (+91...)
data.to Your number that was called
data.direction inbound
data.status missed
data.sip_status 486, the busy signal the caller received
data.phone_number_id Id of your number, as used in the API
data.phone_number_name The name you gave the number; handy as the campaign or lead source

3. Reply fast#

Reply with any 2xx status within 5 seconds. Anything else (a non-2xx code, a timeout, a connection error) counts as a failure and is retried; see Retries and Replay.

Do slow work (CRM calls, emails, callbacks) after you reply, for example by putting the event on a queue.

4. Send a test#

Press Send test on the Webhook page (or call POST /webhooks/subscriptions/:id/test). We post this to your URL and show the status code your server returned:

{
  "event": "webhook.test",
  "timestamp": "2026-10-18T07:00:00Z",
  "data": { "message": "Test event from Edesy." }
}

Your handler should answer 2xx for webhook.test too, and ignore it.

5. Watch the delivery log#

The Webhook page lists recent deliveries with their status, attempt count, the response code and error, and the exact JSON we sent. In the missed-call log every call also shows a delivery status: delivered, pending (still retrying), failed (all attempts used), withheld (wallet too low when the call came in) or not_sent (no webhook was set).

Cost#

On pay as you go each event delivered to your webhook costs Rs 0.30 (+GST). Events that fail on every attempt are refunded, and replays are not charged. See Pricing and Wallet.

Next#

Was this page helpful? Suggest an edit