Receives webhook notifications for call events from the Voice Platform.
Every webhook request is signed by the Voice Platform so that the receiving endpoint can verify that the request was sent by Sinch and was not altered in transit.
The signature is carried in the Authorization header, using the service authentication scheme. The header value is the service identifier and the signature, separated by a colon:
Authorization: service <serviceId>:<signature>| Element | Description |
|---|---|
<serviceId> | Identifier of the service the webhook belongs to. Matches the serviceId segment of the ce-source header and the call.serviceId field of the request body. |
<signature> | Base64-encoded HMAC-SHA256 hash of the canonical request string, keyed with the service secret. |
signature = Base64( HMAC-SHA256( secretBytes, UTF8(stringToSign) ) )secretBytes is the 16-byte binary value of the service secret, and the signed message is the UTF-8 encoding of stringToSign.
The service secret is issued as a Base64 string, for example F5wrP9SKYU6w8sbZXkp7GA==. Base64-decoding it yields the 16 bytes of secretBytes. The decoded bytes are used as the HMAC key — signing with the characters of the Base64 string instead produces a different, invalid signature.
stringToSign is the concatenation of five parts. Each of the first four parts is terminated by a single line feed (\n); the last part is not followed by a line feed.
POST
{contentMd5}
{contentType}
x-timestamp:{timestamp}
{path}| Part | Value |
|---|---|
| Method | The HTTP method, always POST for webhook requests. |
{contentMd5} | Base64( MD5( UTF8(body) ) ) — the Base64-encoded MD5 digest of the raw request body. Empty when the request carries no body. |
{contentType} | The full value of the Content-Type header, including its parameters, for example application/json; charset=utf-8. Empty when the request carries no body. |
{timestamp} | The verbatim value of the x-timestamp request header, an ISO 8601 UTC timestamp with seven fractional-second digits, for example 2026-04-01T12:00:00.0000000Z. The literal prefix x-timestamp: is part of the canonical string. |
{path} | The absolute path of the configured webhook URL, without scheme, host, query string or fragment, for example /voice-webhooks. |
The MD5 digest acts as a checksum of the body inside the canonical string. The integrity and authenticity guarantee is provided by the HMAC-SHA256 signature computed over that string.
The CloudEvents (ce-*) headers are not covered by the signature.
A request delivered to https://example.com/voice-webhooks with the body
{"event":"call.incoming","call":{"callId":"01AN4Z07BY79KA1307SR9X4MV3"}}Content-Type: application/json; charset=utf-8 and x-timestamp: 2026-04-01T12:00:00.0000000Z produces the canonical string
POST
CH5/FnzqzRJ81QlTLGAhAw==
application/json; charset=utf-8
x-timestamp:2026-04-01T12:00:00.0000000Z
/voice-webhooksWith the service secret F5wrP9SKYU6w8sbZXkp7GA==, the resulting header is
Authorization: service a74b1566-0f18-4f8e-9c23-8e6b5df8fd3e:EWFtVTrykdhMTdyYSbn40GBJpf5UBeggO9T99sdwLyY=- Split the
Authorizationheader value into the service identifier and the signature. - Rebuild
stringToSignfrom the received request, using the raw request body exactly as delivered, before any parsing, re-serialization or whitespace normalization. - Recompute the signature with the secret of the identified service and compare it to the received value using a constant-time comparison.
- Reject the request when the two values differ.
- Reject requests whose
x-timestamplies outside an accepted clock-skew window, to limit replay of previously valid requests.
Identifies the type of call event that triggered this webhook notification. Call-related webhook events always start with call. followed by the type of event that triggered them. Events triggered by the webhook SVAML command are dynamic and follow the pattern call.webhook.<webhookName>.
| Enum Value | Description |
|---|---|
| call.incoming | Triggered when an inbound call arrives on a service configured with a webhook URL. |
| call.answered | Triggered when an outbound call is answered by the recipient. |
| call.busy | Triggered when the outbound call recipient is busy. |
| call.rejected | Triggered when the outbound call is rejected by the recipient. |
| call.timeout | Triggered when the outbound call was not answered within the dial timeout. |
| call.hangup | Triggered when the call is disconnected. |
| call.failed | Triggered when the call could not be set up. |
| call.amd.human | Triggered when answering machine detection determines that a human answered the call. |
| call.amd.machine | Triggered when answering machine detection determines that a machine answered the call. |
| call.amd.beep | Triggered when answering machine detection detects a voicemail beep. |
| call.amd.unknown | Triggered when answering machine detection cannot determine whether a human, machine, or beep was detected. |
| call.message.finished | Triggered when all messages in a |
| call.recording.finished | Triggered when a recording is successfully stopped. This event does not guarantee that the recorded file has been delivered to the configured destination yet. |
| call.recording.failed | Triggered when recording could not be started. |
| call.menu | Triggered when a menu completes and input is received from the user or the menu fails. |
- Endpoint which enables consuming the Voice API globally - Redirected by Sinch to the closest region.https://voice.api.sinch.com/call.webhook
- North America 1 - Easthttps://us1.voice.api.sinch.com/call.webhook
- South America 1 - Easthttps://br1.voice.api.sinch.com/call.webhook
- Europe 1 - Centralhttps://eu1.voice.api.sinch.com/call.webhook
- Asia Pacific 1 - Southeasthttps://sg1.voice.api.sinch.com/call.webhook
- https://au1.voice.api.sinch.comhttps://au1.voice.api.sinch.com/call.webhook
{ "event": "call.incoming", "call": { "callId": "01AN4Z07BY79KA1307SR9X4MV3", "projectId": "5c5bf2b1-35ae-4825-ab89-457e07bb60e6", "serviceId": "a74b1566-0f18-4f8e-9c23-8e6b5df8fd3e", "sessionId": "01AN4Z07BY79KA1307SR9X4MV2", "direction": "INBOUND", "originationType": "PHONE", "callType": "PHONE", "from": { … }, "to": { … }, "callResult": "INITIATED", "startTime": "2025-06-01T10:00:00Z", "callRate": { … }, "callResourceUrl": "https://voice.api.sinch.com/v2/projects/5c5bf2b1-35ae-4825-ab89-457e07bb60e6/calls/01AN4Z07BY79KA1307SR9X4MV3" } }
Success. A SVAML document returned in response to a webhook.
Note: callName and events only take effect in responses to webhooks triggered by an incoming call. In responses to other webhook types, they are ignored.
{ "callName": "incoming", "commands": [ { … } ] }