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#
- Verify the signature
- Send leads to Edesy CRM with no code