client.webhook_endpoints
URLs that receive signed events. These methods are on client.webhook_endpoints, where client is a MoreVoice client (see the Python SDK). On AsyncMoreVoice the same methods are awaited. Each one returns the response object and raises an exception when the API answers with an error.
create()
Section titled “create()”Create a webhook endpoint. Starts sending the selected events to url, signed with a new secret (whsec_…, Standard Webhooks). The response carries the secret: this is the only time it is shown (rotate it to get a new one). With signing: ed25519 the events are signed with a new Ed25519 key pair instead (v1a): no secret is returned, and you verify with public_key. Live endpoints need https; private and local addresses are refused.
def create(self, body: _m.WebhookEndpointCreateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookEndpointclient.webhook_endpoints.create() · await async_client.webhook_endpoints.create() · POST /webhook_endpoints · API reference
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
url |
string |
yes | An https URL (http is accepted in test mode). Private and local addresses are refused. |
enabled_events |
string[] |
yes | An event type (call.ended), a group (call.*) or "*" for every event. At least one. |
api_version |
"2026-11-01" |
no | Render payloads in this API version (default: the current one). |
description |
string |
no | — |
max_in_flight |
integer |
no | Deliveries in flight at once (1–100, default 10). |
metadata |
MetadataInput |
no | Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
signing |
"hmac" | "ed25519" |
no | How deliveries are signed (Standard Webhooks). hmac (default): v1,<HMAC-SHA256> with a shared secret (whsec_…) returned once. ed25519: v1a,<Ed25519 signature>; you verify with the endpoint’s public_key (whpk_…) and no secret is ever shared. |
Returns
Section titled “Returns”WebhookEndpoint:
| Field | Type | Description |
|---|---|---|
id |
string |
A webhook endpoint ID (prefix we_). |
object |
"webhook_endpoint" |
Always webhook_endpoint. |
url |
string |
Where events are POSTed. |
description |
string |
— |
enabled_events |
string[] |
The event types sent to this endpoint; ["*"] means every event. |
status |
"enabled" | "disabled" | "auto_disabled" |
auto_disabled: every delivery failed for 72 hours, so sending stopped (and your admins were told). Set status: enabled to resume. |
disabled_reason |
string | null |
— |
disabled_at |
string | null |
— |
api_version |
string |
The API version event payloads are rendered in. legacy: an endpoint moved from the old webhook settings, which keeps getting the previous body ({id, event, createdAt, data}). |
campaign_id |
string | null |
cmp_… ID. |
legacy_headers |
boolean |
Also sends the previous X-Webhook-* headers (moved endpoints, for one deprecation cycle). |
max_in_flight |
integer |
Deliveries in flight to this endpoint at once; more wait their turn. |
metadata |
Metadata |
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
previous_secret_expires_at |
string | null |
While a rotated secret still signs (alongside the new one): until when. |
signing |
"hmac" | "ed25519" |
How deliveries are signed (Standard Webhooks). hmac (default): v1,<HMAC-SHA256> with a shared secret (whsec_…) returned once. ed25519: v1a,<Ed25519 signature>; you verify with the endpoint’s public_key (whpk_…) and no secret is ever shared. |
public_key |
string | null |
ed25519 endpoints: the Ed25519 public key (whpk_ + base64 of 32 bytes) that verifies v1a signatures; also as PEM at GET /v1/webhook_endpoints/{id}/public_key. Null for hmac. |
previous_public_key |
string | null |
After a rotation of an ed25519 key: the previous public key, which still signs alongside until previous_secret_expires_at. |
livemode |
boolean |
true in live mode, false in test mode. |
created |
string |
An ISO-8601 timestamp in UTC. |
updated |
string |
An ISO-8601 timestamp in UTC. |
secret |
string |
The signing secret (whsec_…) of an hmac endpoint. Returned only when the endpoint is created and when its secret is rotated: store it then. ed25519 endpoints never return one. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint = client.webhook_endpoints.create({ "description": "CRM sync", "enabled_events": [ "call.ended", "call.analyzed", ], "url": "https://hooks.example.com/webhooks",})print(webhook_endpoint)delete()
Section titled “delete()”Delete a webhook endpoint. Stops all deliveries to the endpoint at once; its queued deliveries are dropped.
def delete(self, id: str, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.DeletedWebhookEndpointclient.webhook_endpoints.delete() · await async_client.webhook_endpoints.delete() · DELETE /webhook_endpoints/{id} · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Returns
Section titled “Returns”DeletedWebhookEndpoint:
| Field | Type | Description |
|---|---|---|
id |
string |
A webhook endpoint ID (prefix we_). |
object |
"webhook_endpoint" |
Always webhook_endpoint. |
deleted |
true |
— |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
deleted_webhook_endpoint = client.webhook_endpoints.delete("we_7Hk2Lm9Qp")print(deleted_webhook_endpoint)list()
Section titled “list()”List webhook endpoints. Your webhook endpoints in this mode, newest first. Signing secrets are never listed.
def list(self, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.WebhookEndpoint]client.webhook_endpoints.list() · await async_client.webhook_endpoints.list() · GET /webhook_endpoints · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer |
no | How many objects to return, 1–100 (default 20). |
starting_after |
string |
no | A cursor (next_cursor) or object ID: return the objects after it (older). |
ending_before |
string |
no | A cursor or object ID: return the objects before it (newer). |
Returns
Section titled “Returns”A page of results (WebhookEndpointList): data, has_more and next_cursor.
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for webhook_endpoint in client.webhook_endpoints.list(): print(webhook_endpoint)replay()
Section titled “replay()”Replay events to an endpoint. Queues a new delivery to this endpoint for every stored event since since that it subscribes to (optionally only types, or only the events whose deliveries to it never succeeded). At most 10 000 events; narrow the window otherwise. Events keep their ids, so receivers can deduplicate.
def replay(self, id: str, body: _m.WebhookEndpointReplayParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookReplayclient.webhook_endpoints.replay() · await async_client.webhook_endpoints.replay() · POST /webhook_endpoints/{id}/replay · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
since |
string |
yes | Replay events created at or after this time (events are kept 30 days). |
only_failed |
boolean |
no | Only events whose deliveries to this endpoint never succeeded. |
types |
string[] |
no | Only these types (within the endpoint’s own enabled_events). |
until |
string |
no | …and up to this time (default: now). |
Returns
Section titled “Returns”WebhookReplay:
| Field | Type | Description |
|---|---|---|
object |
"webhook_replay" |
Always webhook_replay. |
endpoint_id |
string |
A webhook endpoint ID (prefix we_). |
since |
string |
An ISO-8601 timestamp in UTC. |
until |
string |
An ISO-8601 timestamp in UTC. |
types |
string[] |
— |
only_failed |
boolean |
— |
events_queued |
integer |
New deliveries queued (one per event; at most 10000). They keep their event ids, so receivers can deduplicate. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_replay = client.webhook_endpoints.replay("we_7Hk2Lm9Qp", { "only_failed": True, "since": "2026-11-03T00:00:00Z",})print(webhook_replay)retrieve()
Section titled “retrieve()”Retrieve a webhook endpoint. Returns a webhook endpoint: its URL, the events it receives, its status (and why it was disabled, if it was) and its API version. The signing secret is shown only when the endpoint is created and when the secret is rotated.
def retrieve(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpointclient.webhook_endpoints.retrieve() · await async_client.webhook_endpoints.retrieve() · GET /webhook_endpoints/{id} · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Returns
Section titled “Returns”WebhookEndpoint:
| Field | Type | Description |
|---|---|---|
id |
string |
A webhook endpoint ID (prefix we_). |
object |
"webhook_endpoint" |
Always webhook_endpoint. |
url |
string |
Where events are POSTed. |
description |
string |
— |
enabled_events |
string[] |
The event types sent to this endpoint; ["*"] means every event. |
status |
"enabled" | "disabled" | "auto_disabled" |
auto_disabled: every delivery failed for 72 hours, so sending stopped (and your admins were told). Set status: enabled to resume. |
disabled_reason |
string | null |
— |
disabled_at |
string | null |
— |
api_version |
string |
The API version event payloads are rendered in. legacy: an endpoint moved from the old webhook settings, which keeps getting the previous body ({id, event, createdAt, data}). |
campaign_id |
string | null |
cmp_… ID. |
legacy_headers |
boolean |
Also sends the previous X-Webhook-* headers (moved endpoints, for one deprecation cycle). |
max_in_flight |
integer |
Deliveries in flight to this endpoint at once; more wait their turn. |
metadata |
Metadata |
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
previous_secret_expires_at |
string | null |
While a rotated secret still signs (alongside the new one): until when. |
signing |
"hmac" | "ed25519" |
How deliveries are signed (Standard Webhooks). hmac (default): v1,<HMAC-SHA256> with a shared secret (whsec_…) returned once. ed25519: v1a,<Ed25519 signature>; you verify with the endpoint’s public_key (whpk_…) and no secret is ever shared. |
public_key |
string | null |
ed25519 endpoints: the Ed25519 public key (whpk_ + base64 of 32 bytes) that verifies v1a signatures; also as PEM at GET /v1/webhook_endpoints/{id}/public_key. Null for hmac. |
previous_public_key |
string | null |
After a rotation of an ed25519 key: the previous public key, which still signs alongside until previous_secret_expires_at. |
livemode |
boolean |
true in live mode, false in test mode. |
created |
string |
An ISO-8601 timestamp in UTC. |
updated |
string |
An ISO-8601 timestamp in UTC. |
secret |
string |
The signing secret (whsec_…) of an hmac endpoint. Returned only when the endpoint is created and when its secret is rotated: store it then. ed25519 endpoints never return one. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint = client.webhook_endpoints.retrieve("we_7Hk2Lm9Qp")print(webhook_endpoint)retrieve_public_key()
Section titled “retrieve_public_key()”Retrieve a webhook endpoint’s public key. The Ed25519 public key that verifies an ed25519 endpoint’s v1a signatures, as whpk_… (Standard Webhooks) and as SPKI PEM, with the previous key while a rotation overlaps. An hmac endpoint has none (409 resource_conflict).
def retrieve_public_key(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpointPublicKeyclient.webhook_endpoints.retrieve_public_key() · await async_client.webhook_endpoints.retrieve_public_key() · GET /webhook_endpoints/{id}/public_key · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Returns
Section titled “Returns”WebhookEndpointPublicKey:
| Field | Type | Description |
|---|---|---|
object |
"webhook_endpoint_public_key" |
Always webhook_endpoint_public_key. |
endpoint_id |
string |
A webhook endpoint ID (prefix we_). |
algorithm |
"ed25519" |
Always ed25519. |
signature_version |
"v1a" |
The webhook-signature entries these keys verify (v1a,<base64 signature>). |
public_key |
string | null |
The current key: whpk_ + base64 of the 32-byte Ed25519 public key (Standard Webhooks format). Null while an endpoint switched back to hmac still overlaps with its last Ed25519 key. |
public_key_pem |
string | null |
The same key as SPKI PEM, for libraries that load PEM. |
previous_public_key |
string | null |
After a rotation: the previous key, which still signs alongside the current one until previous_expires_at. |
previous_public_key_pem |
string | null |
— |
previous_expires_at |
string | null |
— |
livemode |
boolean |
true in live mode, false in test mode. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint_public_key = client.webhook_endpoints.retrieve_public_key("we_7Hk2Lm9Qp")print(webhook_endpoint_public_key)rotate_secret()
Section titled “rotate_secret()”Rotate a webhook endpoint’s secret. Creates a new signing secret and returns it (this once). The previous secret keeps signing alongside it for expire_previous_in_hours (default 24), so webhook-signature carries both signatures until your receivers switch. An ed25519 endpoint gets a new key pair instead: the response carries the new public_key and the previous one (no secret). signing switches the scheme with the same overlap.
def rotate_secret(self, id: str, body: _m.WebhookEndpointRotateSecretParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookEndpointclient.webhook_endpoints.rotate_secret() · await async_client.webhook_endpoints.rotate_secret() · POST /webhook_endpoints/{id}/rotate_secret · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
expire_previous_in_hours |
number |
no | How long the previous secret keeps signing alongside the new one (0–72 hours, default 24; 0 stops it at once). |
signing |
"hmac" | "ed25519" |
no | Switch the scheme with this rotation (default: keep the endpoint’s). During the overlap webhook-signature carries both a v1 and a v1a entry, so receivers can move over without missing an event. |
Returns
Section titled “Returns”WebhookEndpoint:
| Field | Type | Description |
|---|---|---|
id |
string |
A webhook endpoint ID (prefix we_). |
object |
"webhook_endpoint" |
Always webhook_endpoint. |
url |
string |
Where events are POSTed. |
description |
string |
— |
enabled_events |
string[] |
The event types sent to this endpoint; ["*"] means every event. |
status |
"enabled" | "disabled" | "auto_disabled" |
auto_disabled: every delivery failed for 72 hours, so sending stopped (and your admins were told). Set status: enabled to resume. |
disabled_reason |
string | null |
— |
disabled_at |
string | null |
— |
api_version |
string |
The API version event payloads are rendered in. legacy: an endpoint moved from the old webhook settings, which keeps getting the previous body ({id, event, createdAt, data}). |
campaign_id |
string | null |
cmp_… ID. |
legacy_headers |
boolean |
Also sends the previous X-Webhook-* headers (moved endpoints, for one deprecation cycle). |
max_in_flight |
integer |
Deliveries in flight to this endpoint at once; more wait their turn. |
metadata |
Metadata |
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
previous_secret_expires_at |
string | null |
While a rotated secret still signs (alongside the new one): until when. |
signing |
"hmac" | "ed25519" |
How deliveries are signed (Standard Webhooks). hmac (default): v1,<HMAC-SHA256> with a shared secret (whsec_…) returned once. ed25519: v1a,<Ed25519 signature>; you verify with the endpoint’s public_key (whpk_…) and no secret is ever shared. |
public_key |
string | null |
ed25519 endpoints: the Ed25519 public key (whpk_ + base64 of 32 bytes) that verifies v1a signatures; also as PEM at GET /v1/webhook_endpoints/{id}/public_key. Null for hmac. |
previous_public_key |
string | null |
After a rotation of an ed25519 key: the previous public key, which still signs alongside until previous_secret_expires_at. |
livemode |
boolean |
true in live mode, false in test mode. |
created |
string |
An ISO-8601 timestamp in UTC. |
updated |
string |
An ISO-8601 timestamp in UTC. |
secret |
string |
The signing secret (whsec_…) of an hmac endpoint. Returned only when the endpoint is created and when its secret is rotated: store it then. ed25519 endpoints never return one. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint = client.webhook_endpoints.rotate_secret("we_7Hk2Lm9Qp", { "expire_previous_in_hours": 24,})print(webhook_endpoint)test()
Section titled “test()”Send a test event. Sends one sample event of type to the endpoint now, signed like a real delivery, and reports how it answered. Samples are not stored and never retried.
def test(self, id: str, body: _m.WebhookEndpointTestParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookEndpointTestclient.webhook_endpoints.test() · await async_client.webhook_endpoints.test() · POST /webhook_endpoints/{id}/test · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
type |
"call.created" | "call.started" | "call.ringing" | "call.answered" | "call.transferred" | "call.ended" | "call.analyzed" | "call.cost_finalized" | … |
no | The event type to send a sample of (default test). |
Returns
Section titled “Returns”WebhookEndpointTest:
| Field | Type | Description |
|---|---|---|
object |
"webhook_endpoint_test" |
Always webhook_endpoint_test. |
endpoint_id |
string |
A webhook endpoint ID (prefix we_). |
event_id |
string |
The sample’s id (the webhook-id header). Samples are not stored. |
type |
"call.created" | "call.started" | "call.ringing" | "call.answered" | "call.transferred" | "call.ended" | "call.analyzed" | "call.cost_finalized" | … |
— |
delivered |
boolean |
The endpoint answered 2xx. |
response_status |
integer | null |
The HTTP status it answered (null: no answer, e.g. a timeout or a refused address). |
duration_ms |
integer | null |
— |
error |
string | null |
— |
response_excerpt |
string | null |
The first 2 KB of its answer. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint_test = client.webhook_endpoints.test("we_7Hk2Lm9Qp", { "type": "call.ended",})print(webhook_endpoint_test)update()
Section titled “update()”Update a webhook endpoint. Change the URL, the events, the description, the API version or the status. status: enabled resumes an endpoint that was disabled (or auto-disabled after 72 hours of failures).
def update(self, id: str, body: _m.WebhookEndpointUpdateParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpointclient.webhook_endpoints.update() · await async_client.webhook_endpoints.update() · PATCH /webhook_endpoints/{id} · API reference
Parameters
Section titled “Parameters”| Name | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | A webhook endpoint ID (we_…). |
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
api_version |
"2026-11-01" |
no | Render payloads in this API version (default: the current one). |
description |
string |
no | — |
enabled_events |
string[] |
no | — |
max_in_flight |
integer |
no | Deliveries in flight at once (1–100, default 10). |
metadata |
MetadataInput |
no | Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
status |
"enabled" | "disabled" |
no | disabled stops deliveries; enabled resumes them (also after an auto-disable). |
url |
string |
no | An https URL (http is accepted in test mode). Private and local addresses are refused. |
Returns
Section titled “Returns”WebhookEndpoint:
| Field | Type | Description |
|---|---|---|
id |
string |
A webhook endpoint ID (prefix we_). |
object |
"webhook_endpoint" |
Always webhook_endpoint. |
url |
string |
Where events are POSTed. |
description |
string |
— |
enabled_events |
string[] |
The event types sent to this endpoint; ["*"] means every event. |
status |
"enabled" | "disabled" | "auto_disabled" |
auto_disabled: every delivery failed for 72 hours, so sending stopped (and your admins were told). Set status: enabled to resume. |
disabled_reason |
string | null |
— |
disabled_at |
string | null |
— |
api_version |
string |
The API version event payloads are rendered in. legacy: an endpoint moved from the old webhook settings, which keeps getting the previous body ({id, event, createdAt, data}). |
campaign_id |
string | null |
cmp_… ID. |
legacy_headers |
boolean |
Also sends the previous X-Webhook-* headers (moved endpoints, for one deprecation cycle). |
max_in_flight |
integer |
Deliveries in flight to this endpoint at once; more wait their turn. |
metadata |
Metadata |
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |
previous_secret_expires_at |
string | null |
While a rotated secret still signs (alongside the new one): until when. |
signing |
"hmac" | "ed25519" |
How deliveries are signed (Standard Webhooks). hmac (default): v1,<HMAC-SHA256> with a shared secret (whsec_…) returned once. ed25519: v1a,<Ed25519 signature>; you verify with the endpoint’s public_key (whpk_…) and no secret is ever shared. |
public_key |
string | null |
ed25519 endpoints: the Ed25519 public key (whpk_ + base64 of 32 bytes) that verifies v1a signatures; also as PEM at GET /v1/webhook_endpoints/{id}/public_key. Null for hmac. |
previous_public_key |
string | null |
After a rotation of an ed25519 key: the previous public key, which still signs alongside until previous_secret_expires_at. |
livemode |
boolean |
true in live mode, false in test mode. |
created |
string |
An ISO-8601 timestamp in UTC. |
updated |
string |
An ISO-8601 timestamp in UTC. |
secret |
string |
The signing secret (whsec_…) of an hmac endpoint. Returned only when the endpoint is created and when its secret is rotated: store it then. ed25519 endpoints never return one. |
Example
Section titled “Example”from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint = client.webhook_endpoints.update("we_7Hk2Lm9Qp", { "enabled_events": [ "call.*", ], "status": "enabled",})print(webhook_endpoint)