---
title: "Restrict a webhook to known IP addresses - Workflow Webhooks"
description: "Limit a Shopify Flow webhook to your sender's IP addresses or CIDR ranges, on top of its token or HMAC signature."
canonical: "https://docs.workflow-webhooks.app/ip-allowlist"
---

# IP allowlists

Authentication proves the *caller* knows your secret. An **IP allowlist** narrows *where* the call may come from, so a leaked token is not enough on its own. Set it per webhook, under **Advanced settings -> IP allowlist**.

It applies on top of whatever authentication the webhook uses, including **None**. A request from any other address is rejected with `403` and the reason `ip_not_allowed`, before the token or signature is even looked at.

## Filling in the list

One entry per line, up to 50:

- a single IPv4 or IPv6 address, such as `203.0.113.10` or `2001:db8::1`
- a CIDR range, such as `203.0.113.0/24` or `2001:db8::/32`

Most senders that are worth allowlisting publish their outbound ranges - Stripe, GitHub, Shopify and Square all do. Paste those ranges, and re-check them when the sender announces a change: an allowlist that is never updated eventually starts rejecting real traffic.

> [!WARNING]
> **Not every sender has fixed addresses**
> Tools that run on shared cloud infrastructure - most no-code platforms, and anything self-hosted behind a changing IP - either publish no ranges at all or publish ranges so wide that the allowlist stops being a control. For those, a strong token or an HMAC signature is the real protection. An allowlist you have to keep widening is worse than none, because it looks like a control and is not.

## Which requests it checks

| Request | Allowlist applies |
| --- | --- |
| A call to the webhook URL | **Yes** |
| A call to the app proxy URL | No - those reach us from Shopify's servers, not from your sender |
| A scheduled run | No - we make the request ourselves |
| The Flow action calling this webhook | No |
| **Send test** and replays from History | No |

That is why an allowlist is not a substitute for authentication: several legitimate paths into the webhook do not pass through it.

## The address we compare

We compare against the address the request actually arrives from. If anything sits between your sender and us - a corporate proxy, an API gateway, a tunnel, a CDN - that is the address you have to allowlist, not the origin server's.

The quickest way to find it: send one request with the allowlist empty, open the entry in [History and troubleshooting](https://docs.workflow-webhooks.app/history-and-troubleshooting.md), and read the address we recorded.

## When it goes wrong

A rejected request still appears in History with `403` and `ip_not_allowed`, so you can see the address that was refused and add it. Nothing is silently dropped.

## Related

- [Authentication](https://docs.workflow-webhooks.app/authentication.md) - tokens, Bearer, Basic and query parameters.
- [Verifying signed webhooks](https://docs.workflow-webhooks.app/signature-verification.md) - HMAC verification for senders that sign.
- [History and troubleshooting](https://docs.workflow-webhooks.app/history-and-troubleshooting.md) - every request, accepted or not.
