Skip to content

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 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.

client.webhook_endpoints
def create(self, body: _m.WebhookEndpointCreateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookEndpoint

client.webhook_endpoints.create() · await async_client.webhook_endpoints.create() · POST /webhook_endpoints · API reference

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.

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.
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 a webhook endpoint. Stops all deliveries to the endpoint at once; its queued deliveries are dropped.

client.webhook_endpoints
def delete(self, id: str, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.DeletedWebhookEndpoint

client.webhook_endpoints.delete() · await async_client.webhook_endpoints.delete() · DELETE /webhook_endpoints/{id} · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).

DeletedWebhookEndpoint:

Field Type Description
id string A webhook endpoint ID (prefix we_).
object "webhook_endpoint" Always webhook_endpoint.
deleted true —
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 webhook endpoints. Your webhook endpoints in this mode, newest first. Signing secrets are never listed.

client.webhook_endpoints
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

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).

A page of results (WebhookEndpointList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for webhook_endpoint in client.webhook_endpoints.list():
print(webhook_endpoint)

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.

client.webhook_endpoints
def replay(self, id: str, body: _m.WebhookEndpointReplayParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.WebhookReplay

client.webhook_endpoints.replay() · await async_client.webhook_endpoints.replay() · POST /webhook_endpoints/{id}/replay · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).
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).

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.
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 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.

client.webhook_endpoints
def retrieve(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpoint

client.webhook_endpoints.retrieve() · await async_client.webhook_endpoints.retrieve() · GET /webhook_endpoints/{id} · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).

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.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
webhook_endpoint = client.webhook_endpoints.retrieve("we_7Hk2Lm9Qp")
print(webhook_endpoint)

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).

client.webhook_endpoints
def retrieve_public_key(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpointPublicKey

client.webhook_endpoints.retrieve_public_key() · await async_client.webhook_endpoints.retrieve_public_key() · GET /webhook_endpoints/{id}/public_key · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).

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.
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 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.

client.webhook_endpoints
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.WebhookEndpoint

client.webhook_endpoints.rotate_secret() · await async_client.webhook_endpoints.rotate_secret() · POST /webhook_endpoints/{id}/rotate_secret · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).
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.

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.
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)

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.

client.webhook_endpoints
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.WebhookEndpointTest

client.webhook_endpoints.test() · await async_client.webhook_endpoints.test() · POST /webhook_endpoints/{id}/test · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).
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).

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.
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 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).

client.webhook_endpoints
def update(self, id: str, body: _m.WebhookEndpointUpdateParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET) -> _m.WebhookEndpoint

client.webhook_endpoints.update() · await async_client.webhook_endpoints.update() · PATCH /webhook_endpoints/{id} · API reference

Name Type Required Description
id str yes A webhook endpoint ID (we_…).
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.

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.
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)