curl --request POST \
--url https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry', 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}/deliveries/{delivery_id}/retry",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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}/deliveries/{delivery_id}/retry")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"attempts": 1,
"call_id": "9d2f7a3c-8e4b-4f1d-a6c7-2b3c4d5e6f70",
"created_at": "2026-09-10T14:04:36Z",
"delivered_at": "2026-09-10T14:04:36Z",
"endpoint_id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"event": "call.ended",
"id": "6a0d5e4f-3c2b-4a19-8e7d-6c5b4a392817",
"last_status_code": 200,
"max_attempts": 8,
"status": "succeeded"
}{
"detail": "Invalid or expired API key"
}{
"detail": "Delivery not found."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Retry a delivery
Queue another attempt now, even if the automatic retries were used up.
The payload is re-signed with the endpoint’s current secret and sent with
the same X-Contour-Delivery-Id.
curl --request POST \
--url https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry', 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}/deliveries/{delivery_id}/retry",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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}/deliveries/{delivery_id}/retry")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.contourvoice.com/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"attempts": 1,
"call_id": "9d2f7a3c-8e4b-4f1d-a6c7-2b3c4d5e6f70",
"created_at": "2026-09-10T14:04:36Z",
"delivered_at": "2026-09-10T14:04:36Z",
"endpoint_id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"event": "call.ended",
"id": "6a0d5e4f-3c2b-4a19-8e7d-6c5b4a392817",
"last_status_code": 200,
"max_attempts": 8,
"status": "succeeded"
}{
"detail": "Invalid or expired API key"
}{
"detail": "Delivery not found."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Authorizations
Your organization's API key (sk_cont_...), sent as Authorization: Bearer sk_cont_.... Keep it server-side.
Response
Successful Response
Attempts made so far.
The call this event is about.
One of call.started, call.ended, call.analyzed, or test for sample events.
Delivery id. Sent as X-Contour-Delivery-Id and as id in the body on every attempt; deduplicate on it.
Attempts allowed before the delivery is marked failed.
One of pending, in_flight, succeeded, failed, cancelled. pending means a retry is scheduled; failed means every attempt was used.
When your server first answered 2xx.
Error from the most recent attempt.
HTTP status from the most recent attempt.
When the next retry is due, while status is pending.