Update a webhook endpoint
Change the URL, the subscribed events, or disable it. Disabling stops delivery without losing the endpoint, its secret or its history. A live key or the dashboard only: a test key gets 403, because an endpoint receives live events too.
Requires the admin scope. A key with less gets 403 insufficient_scope.
Authorization: Bearer tone_live_… or tone_test_…. The prefix IS the environment: a test key reaches only the sandbox, and no request field bridges the two.
In: header
Path Parameters
The webhook endpoint's id.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/v1/integrations/webhooks/string" \ -H "Content-Type: application/json" \ -d '{ "description": "Production CRM sync", "enabled": true, "events": [ "call.completed", "call.failed" ], "url": "https://hooks.example.com/tone" }'{ "data": { "consecutiveFailures": 0, "createdAt": "2026-08-25T09:14:22Z", "description": "Production — order service", "disabledReason": null, "enabled": true, "events": [ "call.completed", "campaign.finished" ], "id": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451", "url": "https://hooks.acme.example/tone" }}The organization-level signing secret (endpoints created before per-endpoint secrets)
🔴 Only endpoints created before per-endpoint secrets sign with this. Every newer endpoint signs with its own — read it with GET /v1/integrations/webhooks/{id}/secret, which also answers correctly for an older endpoint. Compare x-tone-signature against an HMAC-SHA256 of {timestamp}.{raw body} — the RAW body, before any JSON parsing. A live key or the dashboard only: a test key gets 403, because an endpoint receives live events too.
Prepaid balance and estimated talk time remaining
Everything is prepaid and in paise. The estimate divides the balance by your per-minute rate, so it is a guide, not a quota. Subscribe to wallet.balance.low rather than polling this.