curl --request PUT \
--url https://api.example.com/v1/public/webhook/subscription/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Payment Events Webhook",
"description": "Receives payment events with custom authentication",
"url": "https://api.example2.com/webhooks/payments",
"active": true,
"enable_signed_webhooks": true,
"events": [],
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
}
}
'import requests
url = "https://api.example.com/v1/public/webhook/subscription/{id}"
payload = {
"name": "Payment Events Webhook",
"description": "Receives payment events with custom authentication",
"url": "https://api.example2.com/webhooks/payments",
"active": True,
"enable_signed_webhooks": True,
"events": [],
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Payment Events Webhook',
description: 'Receives payment events with custom authentication',
url: 'https://api.example2.com/webhooks/payments',
active: true,
enable_signed_webhooks: true,
events: [],
headers: {'X-Custom-Header': 'custom-value', Authorization: 'Bearer your-api-token-here'}
})
};
fetch('https://api.example.com/v1/public/webhook/subscription/{id}', 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.example.com/v1/public/webhook/subscription/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Payment Events Webhook',
'description' => 'Receives payment events with custom authentication',
'url' => 'https://api.example2.com/webhooks/payments',
'active' => true,
'enable_signed_webhooks' => true,
'events' => [
],
'headers' => [
'X-Custom-Header' => 'custom-value',
'Authorization' => 'Bearer your-api-token-here'
]
]),
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.example.com/v1/public/webhook/subscription/{id}"
payload := strings.NewReader("{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.example.com/v1/public/webhook/subscription/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/public/webhook/subscription/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "6a27a76692d9e3a8ffd7e62d",
"organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17",
"scope": "ORGANIZATION",
"created_user_id": "google-oauth2|101090478854418701727",
"name": "Payment Events Webhook",
"url": "https://api.example2.com/webhooks/payments",
"events": [],
"active": true,
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
},
"description": "Receives payment events with custom authentication",
"request_timeout_ms": 1000,
"retry_policy": {
"retryStrategy": "FIXED_DELAY",
"maxRetryAttempts": 3,
"maxRetryDelayMs": 10000
},
"signing_enabled": true,
"created_at": "2026-06-09T10:15:00.000Z",
"updated_at": "2026-06-09T11:42:00.000Z"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"error": "Authentication",
"message": "Authentication failed",
"traceId": "e679120f-1d1c-41d2-947c-34e194d5a4a1"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}Update a subscription
Replaces the full configuration of an existing subscription (full-replacement PUT semantics - send every field you want to keep, or it may be cleared/reset). The required enable_signed_webhooks also drives the signing lifecycle. Returns the updated subscription - including a new one-time signing secret only if this call just enabled signing on a previously-unsigned subscription.
curl --request PUT \
--url https://api.example.com/v1/public/webhook/subscription/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Payment Events Webhook",
"description": "Receives payment events with custom authentication",
"url": "https://api.example2.com/webhooks/payments",
"active": true,
"enable_signed_webhooks": true,
"events": [],
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
}
}
'import requests
url = "https://api.example.com/v1/public/webhook/subscription/{id}"
payload = {
"name": "Payment Events Webhook",
"description": "Receives payment events with custom authentication",
"url": "https://api.example2.com/webhooks/payments",
"active": True,
"enable_signed_webhooks": True,
"events": [],
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Payment Events Webhook',
description: 'Receives payment events with custom authentication',
url: 'https://api.example2.com/webhooks/payments',
active: true,
enable_signed_webhooks: true,
events: [],
headers: {'X-Custom-Header': 'custom-value', Authorization: 'Bearer your-api-token-here'}
})
};
fetch('https://api.example.com/v1/public/webhook/subscription/{id}', 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.example.com/v1/public/webhook/subscription/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Payment Events Webhook',
'description' => 'Receives payment events with custom authentication',
'url' => 'https://api.example2.com/webhooks/payments',
'active' => true,
'enable_signed_webhooks' => true,
'events' => [
],
'headers' => [
'X-Custom-Header' => 'custom-value',
'Authorization' => 'Bearer your-api-token-here'
]
]),
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.example.com/v1/public/webhook/subscription/{id}"
payload := strings.NewReader("{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.example.com/v1/public/webhook/subscription/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/public/webhook/subscription/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Payment Events Webhook\",\n \"description\": \"Receives payment events with custom authentication\",\n \"url\": \"https://api.example2.com/webhooks/payments\",\n \"active\": true,\n \"enable_signed_webhooks\": true,\n \"events\": [],\n \"headers\": {\n \"X-Custom-Header\": \"custom-value\",\n \"Authorization\": \"Bearer your-api-token-here\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "6a27a76692d9e3a8ffd7e62d",
"organization_id": "ddd6f1d8-b232-497e-bf1e-ea7317622d17",
"scope": "ORGANIZATION",
"created_user_id": "google-oauth2|101090478854418701727",
"name": "Payment Events Webhook",
"url": "https://api.example2.com/webhooks/payments",
"events": [],
"active": true,
"headers": {
"X-Custom-Header": "custom-value",
"Authorization": "Bearer your-api-token-here"
},
"description": "Receives payment events with custom authentication",
"request_timeout_ms": 1000,
"retry_policy": {
"retryStrategy": "FIXED_DELAY",
"maxRetryAttempts": 3,
"maxRetryDelayMs": 10000
},
"signing_enabled": true,
"created_at": "2026-06-09T10:15:00.000Z",
"updated_at": "2026-06-09T11:42:00.000Z"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"error": "Authentication",
"message": "Authentication failed",
"traceId": "e679120f-1d1c-41d2-947c-34e194d5a4a1"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}{
"status": 400,
"type": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {},
"timestamp": "2023-11-07T05:31:56Z",
"path": "/v1/public/webhook/subscription",
"trace_id": "341b5325-a0be-4533-85dd-6f697476dfc3"
}Authorizations
API key passed as a Bearer token in the Authorization header: Authorization: Bearer <YOUR_API_KEY>.
Path Parameters
The subscription ID.
Body
Display name for the subscription (non-blank; unique per organization).
"Payment Events Webhook"
Destination endpoint that receives event POSTs. Must match ^https?://.*.
^https?://.*"https://api.example.com/webhooks/payments"
Whether deliveries are attempted (true) or paused (false).
true
HMAC signing toggle. Must be true or false (omitting it returns 400). On create, true generates a whsec_ signing secret returned once in the response; false creates an unsigned subscription. On update it also drives the signing lifecycle (enable or disable signing).
true
Event types to subscribe to, each in the case-sensitive Service.Event pattern (e.g. CallHandler.CallStarted). An empty array or ["*"] subscribes to all events.
[]
Custom HTTP headers sent with each delivery (string->string map; e.g. auth tokens for your receiving endpoint).
Show child attributes
Show child attributes
{ "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" }
Free-text description (max 1500 chars).
1500"Receives payment events with custom authentication"
Scope the subscription to specific agents (scope = AGENT).
Scope the subscription to specific workspaces (scope = WORKSPACE).
Response
OK. Includes a new secret only if this update just enabled signing.
Subscription ID. Required for GET / PUT / DELETE.
"6a27a76692d9e3a8ffd7e62d"
Owning organization (resolved from your API key).
"ddd6f1d8-b232-497e-bf1e-ea7317622d17"
Resolved delivery scope.
ORGANIZATION, WORKSPACE, AGENT "ORGANIZATION"
User that created the subscription.
"google-oauth2|101090478854418701727"
"Payment Events Webhook"
"https://api.example.com/webhooks/payments"
[]
true
Custom HTTP headers forwarded with each delivery; omitted when unset.
Show child attributes
Show child attributes
{ "X-Custom-Header": "custom-value", "Authorization": "Bearer your-api-token-here" }
Free-text description; omitted when unset.
"Receives payment events with custom authentication"
Agent scope; omitted when unset.
Workspace scope; omitted when unset.
Per-attempt delivery timeout in ms (default 1000).
1000
Delivery retry configuration.
Show child attributes
Show child attributes
Whether the subscription has a signing secret. Always present.
true
HMAC signing secret, prefixed whsec_. Present only at issuance when signing is enabled. Never returned by read endpoints.
"whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"2026-06-09T10:15:00.000Z"
"2026-06-09T10:15:00.000Z"

