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

# Java SDK webhooks

> Verify Telnyx ED25519 webhook signatures and parse typed webhook events with the Java 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 service verifies the signature against your account's public key and
parses the payload into a typed event.

Copy your public key from the Mission Control Portal and expose it as
`TELNYX_PUBLIC_KEY` (or the `telnyx.publicKey` system property) —
`TelnyxOkHttpClient.fromEnv()` 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 from your HTTP framework to
`client.webhooks().unwrap()`:

```java theme={null}
import java.util.List;
import java.util.Map;

import com.telnyx.sdk.client.TelnyxClient;
import com.telnyx.sdk.client.okhttp.TelnyxOkHttpClient;
import com.telnyx.sdk.core.UnwrapWebhookParams;
import com.telnyx.sdk.core.http.Headers;
import com.telnyx.sdk.errors.TelnyxWebhookException;
import com.telnyx.sdk.models.webhooks.UnwrapWebhookEvent;

public class TelnyxWebhookHandler {

    private final TelnyxClient client = TelnyxOkHttpClient.fromEnv();

    // Call with the raw request body and headers from your HTTP framework.
    public void handle(String body, Map<String, List<String>> requestHeaders) {
        Headers headers = Headers.builder().putAll(requestHeaders).build();

        try {
            UnwrapWebhookEvent event = client.webhooks().unwrap(
                UnwrapWebhookParams.builder()
                    .body(body)
                    .headers(headers)
                    .build());
            // Handle the typed event.
        } catch (TelnyxWebhookException e) {
            // Signature invalid — respond with HTTP 400.
        }
    }
}
```

`unwrap(UnwrapWebhookParams)` throws `TelnyxWebhookException` when the
signature does not match and `TelnyxInvalidDataException` when the payload
cannot be parsed.

## Skipping verification

`client.webhooks().unsafeUnwrap(body)` — and the single-argument
`unwrap(String body)` overload — parse a payload without checking the
signature. Only use them 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/java/errors-and-retries)
  covers the SDK's exception hierarchy.
