> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK webhooks

> Verify Telnyx ED25519 webhook signatures and parse typed webhook events with the Python SDK.

Telnyx signs every webhook delivery with an ED25519 signature carried in the
`telnyx-signature-ed25519` and `telnyx-timestamp` request headers. The SDK's
webhook helper verifies the signature against your account's public key and
parses the payload into a typed event.

Webhook verification needs the optional `webhooks` extra:

```bash theme={null}
pip install "telnyx[webhooks]"
```

Copy your public key from the Mission Control Portal and expose it as
`TELNYX_PUBLIC_KEY` — the client reads it automatically, the same way it reads
`TELNYX_API_KEY`:

```bash theme={null}
export TELNYX_PUBLIC_KEY="..."
```

## Verify and parse an event

Pass the raw request body and the request headers to `client.webhooks.unwrap()`.
Verification needs the exact bytes Telnyx sent, so read the body directly rather
than re-serializing parsed JSON:

```python theme={null}
from fastapi import FastAPI, Request, Response
from telnyx import Telnyx

client = Telnyx()  # reads TELNYX_API_KEY and TELNYX_PUBLIC_KEY

app = FastAPI()


@app.post("/webhooks/telnyx")
async def telnyx_webhook(request: Request) -> Response:
    payload = (await request.body()).decode("utf-8")
    try:
        event = client.webhooks.unwrap(payload, headers=request.headers)
    except Exception:
        return Response(status_code=400)  # signature invalid or payload malformed
    print(event.data.event_type)
    return Response(status_code=200)
```

`unwrap()` raises when the signature does not match, and returns the parsed
event as a typed union of every webhook event the API sends — check
`event.data.event_type` to handle specific events.

## Skipping verification

`client.webhooks.unsafe_unwrap(payload)` parses a payload without checking the
signature. Only use it for payloads you have already verified by other means,
or in tests.

## Related

* [Receiving webhooks](/docs/development/api-fundamentals/webhooks/receiving-webhooks)
  covers delivery, retries, and failover URLs.
* [Errors, retries, and timeouts](/docs/development/sdk/python/errors-and-retries)
  covers the SDK's exception hierarchy.
