> For the complete documentation index, see [llms.txt](https://developers.bead.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.bead.xyz/faqs-and-troubleshooting/webhooks-and-error-codes/can-i-send-webhook-events-to-multiple-urls.md).

# Can I send webhook events to multiple URLs?

**Yes.** Bead supports two layers of webhook delivery, and you can combine them to fan-out each event to several destinations:

| Layer                     | How to set it                           | Scope                                | Typical use-cases                                      |
| ------------------------- | --------------------------------------- | ------------------------------------ | ------------------------------------------------------ |
| **Terminal webhook**      | `PUT /Terminals/{terminalId}/webhook`   | All payments created by the terminal | Core order-management system, accounting queue         |
| **Per-payment overrides** | `webhookUrls` array in `POST /Payments` | Only the payment being created       | A/B testing, partner-specific listener, analytics hook |

`webhookUrls` is also accepted on the deprecated `POST /Payments/crypto`, which takes the same request body.

When you include a `webhookUrls` array, **Bead POSTs the same JSON payload to&#x20;*****all*****&#x20;of these endpoints**:

1. The terminal's default webhook URL
2. Every URL listed in `webhookUrls`

No extra configuration is needed. Just add the array to your create-payment request:

```json
{
    "...": "...other fields...",
    "webhookUrls": [
        "https://orders.example.com/bead/events",
        "https://analytics.example.com/hooks/bead"
    ]
}
```

**Delivery behavior**

* **Fan-out**: events are sent to every destination in parallel.
* **Success criteria**: each URL must return **HTTP 2xx**; any non-2xx triggers retries for that endpoint only (exponential back-off, 24 h window).
* **Same body, different signature per delivery**: the JSON body is identical for every recipient, so your parsing logic doesn't need to branch by destination. The `x-webhook-signature` header, however, is generated fresh for each individual delivery (a new timestamp each time), so the signature *value* differs across recipients even though the body and the underlying secret are the same. Your verification code should recompute the signature per delivery rather than comparing signature values against each other.

**Tips & best practices**

* **Idempotency**: process webhooks idempotently (for example by `paymentId` + `statusCode` + `refundLifecycleStatus`) in case one URL retries while another succeeds. Reclaim progress events repeat the same `statusCode`, so include `refundLifecycleStatus` in the key. `trackingId` is a legacy identifier and should not be used as the key.
* **Environment isolation**: point sandbox terminals to test URLs, then add production URLs in `webhookUrls` only when you go live.
* **Signing secrets**: the HMAC uses the **terminal's `signingSecret`**, for both the terminal's own webhook and every URL in `webhookUrls`. Share that secret securely with every service that needs to verify events.
* **Set a terminal webhook first, even if `webhookUrls` is your primary path**: a terminal only has a `signingSecret` once you've called `PUT /Terminals/{terminalId}/webhook` on it at least once. If you only ever use `webhookUrls` and never set a terminal-level default, that terminal has no signing secret, and its `webhookUrls` deliveries are sent **without** an `x-webhook-signature` header, silently, with no error or warning. Set the terminal-level webhook first to establish the secret, then rely on `webhookUrls` for additional routing.
* **Performance**: acknowledge quickly (under 1 s) and offload heavy work to background jobs.

**Testing multiple endpoints**

1. **Sandbox first**: set a sandbox webhook URL on the terminal (this also establishes the `signingSecret`).
2. Include a second test URL in `webhookUrls`.
3. Create a payment in sandbox and complete it with a test wallet.
4. Confirm both endpoints receive the same event body, each with a valid (but distinct) `x-webhook-signature`, and that retries stop after 2xx.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers.bead.xyz/faqs-and-troubleshooting/webhooks-and-error-codes/can-i-send-webhook-events-to-multiple-urls.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
