> 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/firewall-and-ip-allowlisting-for-webhooks.md).

# Firewall & IP allowlisting for webhooks

## Firewall & IP allowlisting for webhooks

If your organization enforces a firewall, WAF, or IP allowlist in front of your webhook receiver, requests from Bead may be blocked before they reach your application. This page covers how to identify that failure mode and what to allowlist.

This is a narrower case of the general webhook troubleshooting flow — start with [Why am I not receiving webhook events?](/faqs-and-troubleshooting/webhooks-and-error-codes/why-am-i-not-receiving-webhook-events.md) first. Come here specifically when you've confirmed your endpoint is reachable and correctly configured, but requests are still being rejected at the network or WAF layer.

**1 — How to recognize a firewall/WAF block**

A WAF or IP-based block usually looks different from an application-level failure:

| Symptom                                                                                                                                                                       | Likely cause                                                                                                                                    |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Consistent `403 Forbidden` on every request, regardless of method or payload, often with a generic body (e.g. `Server: awselb/2.0` or a bare `403 Forbidden` HTML page)       | Load balancer or WAF rejecting the request before it reaches your application                                                                   |
| `200 OK` status, but the response body is a generic web server error page (e.g. Apache "internal error or misconfiguration") rather than your application's expected response | Request is reaching your web server but failing before your application code executes — check server/WAF config, not your webhook handler logic |
| Identical error response regardless of whether the request body is empty, a dummy payload, or a real Bead-shaped payload                                                      | Confirms the block is happening before payload inspection — rule out payload validation issues and look at network/WAF layer instead            |
| Endpoint works when tested from a browser or one network, but not from Bead's servers                                                                                         | Source-IP-based restriction; Bead's outbound IP(s) are not allowlisted                                                                          |
| Consistent block on every request specifically citing a missing or absent `User-Agent` header (e.g. a WAF rule like "no user agent")                                          | Your WAF rejects requests without a `User-Agent` header — see Section 3a below                                                                  |

If you're unsure which case you're in, capture the full raw response (status code, headers, and body) for a failing request and compare against the table above.

**2 — Bead's outbound webhook IPs**

Bead's webhook dispatch egresses from a small, fixed set of addresses per environment. Allowlist **all** addresses listed for your environment — traffic may originate from any of them.

**Sandbox**

| Value          |
| -------------- |
| `35.155.201.4` |
| `52.10.29.164` |

**Production**

| Value            |
| ---------------- |
| `35.95.167.220`  |
| `54.148.110.160` |

**3 — Recommended: verify by signature, not by IP**

IP allowlisting is fragile — egress ranges can expand, rotate, or change without notice as infrastructure changes, and a rule scoped to a single captured IP will silently start failing the next time that happens.

Bead signs every webhook payload with an HMAC signature in the `x-webhook-signature` (payment/terminal) or `X-Bead-Signature` (onboarding/settlement) header. Verifying that signature confirms a request genuinely came from Bead, independent of source IP. Where your security posture allows it, prefer signature verification over IP allowlisting — see [How do I verify that a webhook really came from Bead?](/faqs-and-troubleshooting/webhooks-and-error-codes/how-do-i-verify-that-a-webhook-really-came-from-bead.md) for the full implementation guide.

If your organization requires network-layer allowlisting for compliance reasons in addition to signature verification, allowlist every address listed in Section 2 for your environment — not just one — and revisit them periodically as part of your own change-management process.

**3a — If your WAF requires a User-Agent header**

Some WAFs block any request that lacks a `User-Agent` header outright, independent of IP allowlisting or signature verification — this is a common default WAF rule, not something specific to your configuration. If your logs show a block for a missing/absent `User-Agent`, note that every outbound webhook request from Bead (payment/terminal, onboarding, and settlement alike) now sends:

```
User-Agent: Bead-PaymentService/1.0
```

You can allowlist on this value in addition to, or instead of, IP-based rules. As of this writing, this header is confirmed present in the Bead Sandbox/test environment; if you're allowlisting for a production endpoint, confirm with your Bead contact that the same header is present in production before relying on it there.

This header does not replace signature verification (Section 3) as the strongest way to confirm a request came from Bead — it specifically addresses WAF rules that reject requests for missing a `User-Agent` regardless of any other check.

**4 — Common WAF false-positive triggers**

Some WAF rulesets flag standard HTTP client behavior as suspicious, which can block legitimate Bead traffic without any IP restriction being involved. If your WAF logs show a request blocked for header content (e.g. a rule matching on user-agent strings, generic client signatures, or patterns resembling command injection), check the following before assuming it's a targeted attack:

* **Default HTTP client User-Agent strings.** Bead's webhook requests send a fixed `User-Agent: Bead-PaymentService/1.0` (Section 3a). Confirm your WAF rule isn't matching broadly on client-identifying strings rather than actual malicious content.
* **Standard headers vs. custom rule patterns.** Compare the exact header content your WAF flagged against the rule's pattern — overly broad patterns can produce false positives on ordinary requests.
* **Retry behavior.** Bead retries failed webhook deliveries with backoff (see [Why am I not receiving webhook events?](/faqs-and-troubleshooting/webhooks-and-error-codes/why-am-i-not-receiving-webhook-events.md)). A WAF or rate-limiting rule tuned for a single request may flag retries as abuse.

If you see a block you believe is a false positive, capture the exact WAF log entry (rule ID, matched pattern, timestamp) — this is the fastest way for both teams to confirm what triggered it.

**5 — Still blocked after allowlisting?**

1. Confirm the allowlist change has actually deployed/propagated on your side — WAF and firewall rule changes are not always instant.
2. Re-test using a direct request (e.g. `curl`) against your endpoint from a known Bead environment, and capture the full verbose output (status, headers, body).
3. Check whether the block is happening at a load balancer/WAF layer (Section 1) versus your application layer — they require different fixes.
4. Email Bead with: your terminal ID, webhook URL, the exact error/response you're seeing, and a timestamp of a failed attempt so we can correlate it against our dispatch logs.

**Related pages**

* [Why am I not receiving webhook events?](/faqs-and-troubleshooting/webhooks-and-error-codes/why-am-i-not-receiving-webhook-events.md)
* [How do I verify that a webhook really came from Bead?](/faqs-and-troubleshooting/webhooks-and-error-codes/how-do-i-verify-that-a-webhook-really-came-from-bead.md)
* [Payment Webhooks](/payments/payment-webhooks.md)


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.bead.xyz/faqs-and-troubleshooting/webhooks-and-error-codes/firewall-and-ip-allowlisting-for-webhooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
