Handle Sinch voice call webhook
curl --request POST \
--url https://your-instance.example.com/api/webhook/calls/sinch \
--header 'Content-Type: application/json' \
--data '
{
"event": "ice",
"callId": "a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01",
"callResourceUrl": "https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01"
}
'import requests
url = "https://your-instance.example.com/api/webhook/calls/sinch"
payload = {
"event": "ice",
"callId": "a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01",
"callResourceUrl": "https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
event: 'ice',
callId: 'a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01',
callResourceUrl: 'https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01'
})
};
fetch('https://your-instance.example.com/api/webhook/calls/sinch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://your-instance.example.com/api/webhook/calls/sinch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'event' => 'ice',
'callId' => 'a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01',
'callResourceUrl' => 'https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.example.com/api/webhook/calls/sinch"
payload := strings.NewReader("{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://your-instance.example.com/api/webhook/calls/sinch")
.header("Content-Type", "application/json")
.body("{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-instance.example.com/api/webhook/calls/sinch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}"
response = http.request(request)
puts response.read_body{
"action": {
"name": "connectConf",
"conferenceId": "org-64a1b-room-42",
"cli": "+12362320246"
}
}{
"error": "Webhook processing failed"
}Webhooks
Handle Sinch voice call webhook
Inbound voice call webhook posted by Sinch for ICE (Incoming Call Event), ACE (Answered Call Event), and DiCE (Disconnect Event). For ICE the endpoint returns SVAML instructing Sinch how to route/record the call; for ACE and DiCE it updates the Call record and acknowledges receipt.
POST
/
api
/
webhook
/
calls
/
sinch
Handle Sinch voice call webhook
curl --request POST \
--url https://your-instance.example.com/api/webhook/calls/sinch \
--header 'Content-Type: application/json' \
--data '
{
"event": "ice",
"callId": "a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01",
"callResourceUrl": "https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01"
}
'import requests
url = "https://your-instance.example.com/api/webhook/calls/sinch"
payload = {
"event": "ice",
"callId": "a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01",
"callResourceUrl": "https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
event: 'ice',
callId: 'a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01',
callResourceUrl: 'https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01'
})
};
fetch('https://your-instance.example.com/api/webhook/calls/sinch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://your-instance.example.com/api/webhook/calls/sinch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'event' => 'ice',
'callId' => 'a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01',
'callResourceUrl' => 'https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.example.com/api/webhook/calls/sinch"
payload := strings.NewReader("{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://your-instance.example.com/api/webhook/calls/sinch")
.header("Content-Type", "application/json")
.body("{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-instance.example.com/api/webhook/calls/sinch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"event\": \"ice\",\n \"callId\": \"a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\",\n \"callResourceUrl\": \"https://calling.api.sinch.com/v1/calls/a8d3c4e0-9b2f-4e1a-b3c4-5f6a7b8c9d01\"\n}"
response = http.request(request)
puts response.read_body{
"action": {
"name": "connectConf",
"conferenceId": "org-64a1b-room-42",
"cli": "+12362320246"
}
}{
"error": "Webhook processing failed"
}Body
application/json
Response
SVAML response. For Incoming Call Event (ICE) the body carries a routing action (connectConf, hangup, etc.); for ACE/DiCE the body is empty.
SVAML response Sinch interprets to route the call. Only Incoming Call Event (ICE) returns a populated action; ACE / DiCE branches return an empty object or omit action.
One SVAML action (Sinch Voice Application Markup Language) instructing Sinch how to route the call.
Show child attributes
Show child attributes
Example:
{ "name": "connectConf" }