> For the complete documentation index, see [llms.txt](https://developer.paddle.com/llms.txt).

# Handle webhook delivery

Receive notifications by making sure your webhook event server is configured correctly, and responding within five seconds.

---

Once you've created a notification destination, you should properly handle webhook delivery. This includes making sure your webhook server is configured correctly, responding to notifications promptly, and handling retries.

## Before you begin

[Create a notification destination](https://developer.paddle.com/webhooks/notification-destinations.md) where the type is `url` (webhook), if you haven't already.

## Use an AI agent

## Allow Paddle IP addresses

You should make sure that webhooks originate from a Paddle webhook IP address. We recommend adding Paddle webhook IP addresses to your allowlist, and rejecting webhooks that come from other sources.

Allow different IP addresses for `sandbox` and `live` accounts:

{% code-group %}

```text {% title="Sandbox" %}
34.194.127.46
54.234.237.108
3.208.120.145
44.226.236.210
44.241.183.62
100.20.172.113
```

```text {% title="Live" %}
34.232.58.13
34.195.105.136
34.237.3.244
35.155.119.135
52.11.166.252
34.212.5.7
```

{% /code-group %}

## Update firewall rules

If you're using a Web Application Firewall (WAF) to protect your web server from bot traffic, requests from Paddle may be blocked incorrectly.

We recommend configuring your firewall to bypass bot checks on webhook endpoint paths. Additionally, use Paddle IP addresses and match `Paddle` as the user agent string to further restrict your rule.

## Configure your webhook handler

To receive webhooks, make sure your webhook event server:

- Uses HTTPS
- Can accept `POST` requests with a JSON payload
- Returns `200` within **five seconds** of receiving a request

We recommend configuring your handler to process webhooks asynchronously by queueing received events and processing them in order. This helps prevent a large spike in webhooks from overwhelming your server.

## Respond to events

The server that you set to receive events from Paddle should respond with an HTTP `200` status code **within five seconds**. This lets Paddle know that you successfully received the message.

You should respond before doing any internal processing. For example, if you use a webhook to update a record in a third-party system, respond with a `200` before running any logic to communicate with the third-party solution.

If you're running your webhook handler on Vercel Serverless Functions, AWS Lambda, Google Cloud Functions, or similar serverless platforms, consider pre-warming your function to prevent cold starts that might cause intermittent timeouts.

We can't guarantee the order of delivery for webhooks. They may be delivered in a different order to the order they're generated. Store and check the `occurred_at` date against a webhook before making changes.

## Handle retries

If your server sends another kind of status code or doesn't respond within five seconds, Paddle automatically retries using an exponential backoff schedule:

- For sandbox accounts, we retry 3 times within 15 minutes.
- For live accounts, we retry 60 times within 3 days. The first 20 attempts happen in the first hour, with 47 in the first day and 60 in total.

Use [an exponential backoff calculator](https://exponentialbackoffcalculator.com/) to visualize retries from the date now. Use these values:

{% definition-list %}
{% definition term="Interval (secs)" %}
`60`
{% /definition %}
{% definition term="Max retries" %}
`60`
{% /definition %}
{% definition term="Exponential" %}
`1.1`
{% /definition %}
{% /definition-list %}

You can check the status of a webhook and see delivery attempts using the Paddle dashboard, or by using the [list logs for a notification operation](https://developer.paddle.com/api-reference/notification-logs/list-notification-logs.md) in the Paddle API.

When all attempts to deliver a webhook are exhausted, its status is set to `failed`. You can attempt to redeliver a notification using the [replay a notification operation](https://developer.paddle.com/api-reference/notifications/replay-notification.md) in the Paddle API.

## Verify webhook signatures

Use the `Paddle-Signature` header included with each webhook to [verify that received events](https://developer.paddle.com/webhooks/signature-verification.md) are genuinely sent by Paddle.

## Test your handler

### Send simulated webhooks to your handler

Test your webhook handler by sending simulated events to your endpoint using the [webhook simulator](https://developer.paddle.com/webhooks/test-webhooks.md). You can customize payloads, inspect event details, and replay simulations as part of your testing process.

### Forward events to a local endpoint

Notification destinations require public-facing URLs. If you're developing locally, you can expose your local development server to the internet using a service like [Hookdeck CLI](https://hookdeck.com/docs/cli):

1. Install [Hookdeck CLI](https://hookdeck.com/docs/cli#installation).

2. Run your local server. Note the port your local server is running on.

3. Run `hookdeck listen {PORT} paddle --path {WEBHOOK_ENDPOINT_PATH}`, where `{PORT}` is the port where your local server is running and `{WEBHOOK_ENDPOINT_PATH}` is the path to your webhook handler. For example:

   ```bash
   hookdeck listen 3000 paddle --path /api/webhook
   ```

4. Use the unique URL generated by Hookdeck CLI as your webhook endpoint URL when [creating or updating a notification destination](https://developer.paddle.com/webhooks/notification-destinations.md).

[Learn more about using the Hookdeck CLI to test and replay Paddle webhooks events on the Hookdeck docs.](https://hookdeck.com/webhooks/platforms/how-to-test-and-replay-paddle-webhooks-events-on-localhost-with-hookdeck)