curl --request POST \
--url https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event": "call.ended"
}
'import requests
url = "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test"
payload = { "event": "call.ended" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({event: 'call.ended'})
};
fetch('https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test', 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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test",
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' => 'call.ended'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test"
payload := strings.NewReader("{\n \"event\": \"call.ended\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event\": \"call.ended\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event\": \"call.ended\"\n}"
response = http.request(request)
puts response.read_body{
"delivery_id": "6a0d5e4f-3c2b-4a19-8e7d-6c5b4a392817",
"status": "succeeded",
"status_code": 200
}{
"detail": "Invalid or expired API key"
}{
"detail": "Webhook endpoint not found."
}{
"detail": "event must be one of call.started, call.ended, call.analyzed."
}Send a test event
POST a sample event to this endpoint right now and report what happened.
No call is placed. The sample carries call_id: "call_test_00000000" and
metadata: {"test": true} so your handler can recognize it, and it is
signed with the endpoint’s real secret, so a 401 from your server usually
means your signature check is the problem. One attempt, no retries; the
send appears in the delivery log with event: test.
curl --request POST \
--url https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event": "call.ended"
}
'import requests
url = "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test"
payload = { "event": "call.ended" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({event: 'call.ended'})
};
fetch('https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test', 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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test",
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' => 'call.ended'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test"
payload := strings.NewReader("{\n \"event\": \"call.ended\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event\": \"call.ended\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/test")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event\": \"call.ended\"\n}"
response = http.request(request)
puts response.read_body{
"delivery_id": "6a0d5e4f-3c2b-4a19-8e7d-6c5b4a392817",
"status": "succeeded",
"status_code": 200
}{
"detail": "Invalid or expired API key"
}{
"detail": "Webhook endpoint not found."
}{
"detail": "event must be one of call.started, call.ended, call.analyzed."
}Authorizations
Your organization's API key (sk_cont_...), sent as Authorization: Bearer sk_cont_.... Keep it server-side.
Path Parameters
Body
Which sample event to send. One of call.started, call.ended, call.analyzed.
Response
Successful Response
The delivery row recorded for this send.
succeeded or failed. Test sends are never retried.
Why it failed. HTTP 401 usually means your signature check rejected it; other values describe connection problems.
HTTP status your server returned, or null if it never answered.