# Webhooks

> Subscribe to masked-call lifecycle events instead of polling. Signed JSON is POSTed to your endpoint on every state transition.

Source: https://edesy.in/docs/number-masking/api-reference/webhooks

Subscribe to call lifecycle events instead of [polling](https://edesy.in/docs/number-masking/api-reference/get-call-status). We POST signed JSON to your endpoint at each state transition. Failed deliveries retry with exponential backoff, and every payload includes an **HMAC SHA-256 signature** for verification.

Configure your webhook endpoint URL on the [portal](https://masking.edesy.in).

## Events

| Event | Description |
|-------|-------------|
| `call.initiated` | Party A is being dialed. Call has not yet connected. |
| `call.ringing` | Party A's phone is ringing. |
| `call.answered` | Party A answered. We are now dialing Party B to bridge. |
| `call.bridged` | Both parties are connected and talking. |
| `call.completed` | Call ended normally. Includes duration and recording URL. |
| `call.failed` | Call failed. Includes `hangup_cause` for diagnostics. |
| `call.no-answer` | Party A did not answer within the timeout window. |
| `recording.ready` | Recording is processed and available for download. |

## Sample payload (`call.completed`)

```json
{
  "event": "call.completed",
  "call_sid": "d28be7cd-9840-4b23-9627-199f1ef81fc6",
  "data": {
    "caller_number": "917969002802",
    "target_number": "9876543210",
    "masked_number": "917969002802",
    "direction": "click_to_call",
    "status": "completed",
    "started_at": "2026-05-11T08:30:00Z",
    "answered_at": "2026-05-11T08:30:08Z",
    "ended_at": "2026-05-11T08:31:42Z",
    "duration_sec": 94,
    "bill_duration_sec": 120,
    "price": 3.0,
    "recording_url": "recordings/2026/05/11/d28be7cd.wav"
  }
}
```

## Verifying signatures

Each request includes an HMAC SHA-256 signature computed over the raw request body using your webhook signing secret (from the portal). Recompute the HMAC on your side and compare it to the signature header before trusting the payload. Always respond with a `2xx` status quickly; do any heavy processing asynchronously so deliveries are not retried unnecessarily.
