← All notes

Anyone on the internet can knock on your webhook

14 min read

Somewhere in your business there is a web address you have never seen.

It was created when somebody connected two of your systems together. Your online shop calls it when an order comes in, or your payment provider calls it when money arrives, and something happens at the other end: an invoice is raised, a job is scheduled, a customer gets an email. The address does its work quietly and has never once been mentioned in a meeting.

That address is on the public internet. It has to be, because a system somewhere else needs to reach it. And on a good many of the tools small businesses use to build these connections, the only thing standing between that address and the rest of the world is that it is hard to guess.

This is not a secret. The vendors say so on their own websites. They just say it somewhere nobody is looking at the time.

The vendor says the address is the password

The clearest statement of the problem in this whole article comes from Zapier, about Zapier, in Zapier's own help centre.

The URL is secured by obscurity. It is almost impossible to guess the combination of the number and code in the URL. But if you make the URL public (e.g. in front-end JavaScript) anyone who finds it will be able to spam it and trigger your Zap. Treat it as a password or any other secret!

Everything a business owner needs to know is in those four sentences. The address is not guarded; it is merely obscure. Obscure is a real defence against a random passer-by and no defence at all against anybody who has seen the address once. And the address is handled like a configuration value, not like a password: pasted into another tool, emailed to a contractor, dropped into a shared document so a colleague can finish the setup.

Now consider where that paragraph sits. It is in the introduction to a general "how to get started" page, immediately after the passage that hands the reader their URL - which is exactly the right place for it, and worth saying plainly. That page is the one you read once, before you build anything.

The page a person actually follows while wiring a connection up is a different one: a step-by-step task page. I read that one in full. Its sections cover what to do before you begin, adding the trigger, setting it up, adding the URL to your app, sending data, response behaviour, ownership, sending more than one event, triggering multiple workflows, limitations, and next steps. There is no security section on it, and nothing about who is allowed to call the address. The only thing it says about who the URL belongs to is that it changes if the automation is transferred to somebody else, because the URL contains the owner's account identifier.

So the warning exists, it is honest, and it is on the page you skim. It is not on the page you follow.

What the sending side does, and where it stops

The platforms doing the calling have thought about this carefully. Their documentation says so, and the language is worth reading because it is stronger than most people expect.

Stripe states the exposure and the consequence in one sentence: "Without verification, an attacker could send fake webhook events to your endpoint to trigger actions like fulfilling orders, granting account access, or modifying records." That is the vendor, not me, listing three things a business owner recognises immediately as their own business. The instruction on the same page is unqualified: "Always verify that webhook events originate from Stripe before acting on them."

Shopify's framing is the same shape. Its documentation tells developers to always confirm a delivery is genuine before trusting what is in it, and to skip that step only on a test setup with mock tools.

Both platforms sign what they send, so that the receiving end can tell a real message from an invented one. That is the important structural fact, and it is worth stating precisely: the sender's job is to make itself provable; proving it is the receiver's job. The signature travels with the message and then sits there, waiting for somebody at your end to look at it.

Whether anybody looks is not the platform's decision. It is not your decision either, in practice. It was made by whoever built the connection, on an afternoon you were not present for, and it has never been reviewed since.

On the tools small businesses use, nobody is checking

Here is where the gap opens, and it is a gap between two industries rather than a flaw in any one product.

Every sending platform quoted in this article signs what it sends. The tools that most small businesses actually use to receive those calls do not check incoming ones.

Make publishes an address restriction control for its apps, and the description of what an empty field means is the whole story. The field takes an "allowed list of ip addresses delimited by comma only webhook requests that come from the specified ips will be processed... leave empty if you want to allow requests from all ips". The page says what happens if the field is empty. It does not say whether the field ships empty, and the word "default" appears nowhere on it. I also read Make's main webhooks help page from top to bottom. It covers creating hooks, scheduling, processing order, queues, expiry, logs and error handling. It contains no section on authentication or on verifying who sent the request.

n8n is the most forthcoming of the three. Its webhook documentation lists the authentication choices available for an incoming call: three ways of requiring the caller to identify itself, and a fourth option named None. On the address allowlist, the same page says "If left blank, all IP addresses can invoke the webhook trigger URL."

I want to be precise about one thing, because it would be easy to overstate. The n8n page does not say which of those options is selected when you create a new webhook, and I am not going to guess. What it says is that None is on the menu, and that an empty address list admits everybody. That is enough.

Across all three tools the pattern is identical. Verification of the caller is something the user builds, not something the tool performs. Nobody is doing anything wrong; these are open, general-purpose tools and a general-purpose tool cannot know what your rule should be. But the effect on a small business is that a signature is being generated at one end of the connection and there is nowhere at the other end for it to be checked, unless a person deliberately built a place.

If you would rather have somebody map the connections your business depends on and work out what can be automated, in what order, and what each piece is worth, that is the process audit. $299, three business days, and a written map you keep whether or not you hire us.

The question keeps being asked, and the answer keeps being "build it yourself"

The reason to look at community threads as well as documentation is that documentation describes what is possible and threads describe what happens. n8n's community has a thread titled "Webhook Authentication" that opened in March 2021 with a question about the proper way to secure a webhook and was still collecting replies in November 2025. The question does not go away, which is the most useful signal in this entire section, and the shape of the answers has not changed either: a check the user builds by hand and inserts downstream of the hook. Read what that means commercially: the automation still runs, still consumes a paid operation, and the check happens because somebody remembered to add a step.

The other recurring version is not a security question but a line item. An open address is something people ask about in terms of avoiding a flood of calls and saving credits, and the mitigation usually suggested is a firewall and rate limiting placed in front of the tool, which is to say: something bought separately, outside the automation platform entirely.

The vendors do not agree on how firmly to tell you

Five platforms, one identical exposure, five different strengths of instruction.

Stripe: "Always verify that webhook events originate from Stripe before acting on them."

Shopify: always confirm the delivery before trusting its contents.

Meta, in its developer documentation for the Graph API webhooks that sit behind WhatsApp and Facebook messaging: "You don't have to validate the payload, but you should."

Twilio: "If your application exposes sensitive data or modifies your data, you may want to verify that HTTP requests to your web application come from Twilio."

GitHub takes a different route again and makes the signing itself optional: it sends no signature unless the person setting up the connection provides a secret first, while still advising that deliveries be validated.

Every one of those positions is defensible on its own page. The trouble is that no small business reads four sets of documentation and reconciles them. It reads whichever one its contractor happened to read, and inherits that document's confidence level as its own policy. A business connected to five services may well have five different standards in force, none of them chosen.

The same event can arrive twice, and out of order

There is a second thing about that address which surprises people, and it has nothing to do with anyone acting in bad faith. The platform calling you does not promise to call once, or in sequence.

Stripe says both things plainly: "Webhook endpoints might occasionally receive the same event more than once", and "Stripe doesn't guarantee the delivery of events in the order that they're generated." It goes further and closes off the obvious workaround, warning against using an event's creation timestamp "to determine event order or whether you've already processed an event."

Shopify publishes the same warnings in its own words: duplicates are minimised but possible, for example after a network timeout or a retry, and ordering is not guaranteed within a topic or across topics for the same resource.

In business terms, this is not an abstraction. It is the customer who receives two invoices for one order, or the refund that is processed before the system has registered the sale it belongs to. The version small businesses hit most often is an automation running twice for one event because the sending app fired more than once, and a home-made fix - checking a spreadsheet for a marker - failing because both runs happened before either had written its marker. That is the same shape as what happens when an automation runs the same job twice, arriving from outside instead of from a retry.

The most expensive failure here is silence

Of everything in this article, the most costly thing that can happen to a small business is not that a stranger calls the address. It is that the platform stops calling and nobody notices.

Shopify documents the sequence exactly. An app has five seconds to respond to a delivery; if it does not, the delivery fails. Failures are retried up to eight times over four hours. And then: "After multiple failures in a 24-hour period, the webhook subscription is removed."

Removed. The orders keep arriving in the shop, the customers keep paying, and the connection that was telling your other systems about them has been switched off because it was slow on a bad afternoon.

A warning does go out, and it is worth reading who receives it. The delivery documentation says warning emails are sent to the app's emergency developer address - to whoever built the connection, that is, rather than to the person whose orders have stopped moving. The two Shopify pages also differ in how firmly they put the removal: the troubleshooting page states it flatly, while the delivery page attaches a condition about how the subscription was created. Either way the ending is the same one.

Stripe handles the same situation in the opposite direction, and creates a different problem. Undelivered events are resent "for up to three days", which is generous — and then, in the awkward case where a business has spent that outage reconciling by hand: "Stripe still considers your manually processed events as undelivered and continues to automatically retry them." The backlog you already worked through arrives anyway.

Two platforms, one outage, opposite aftermaths. One goes quiet permanently, one replays everything. Where a warning is sent at all it reaches whoever built the connection, which in a small business is frequently somebody who finished the engagement a year ago. This is the same silence described in why automations fail silently, and the mirror image of orders that stopped arriving because the other end stopped calling — there, the calls simply stopped; here, they may still be arriving, from somebody you have not identified.

An open door costs money even when nothing bad happens

Worth separating out, because it changes who at a business should care.

Most automation tools charge by the operation, task or execution. An address that anybody can call is an address anybody can call repeatedly. Nothing has to be stolen and no data has to leak for that to appear on an invoice; the automation does exactly what it was built to do, at a volume nobody planned.

This is why the question comes up as saving credits at least as often as it comes up as security. For a business on a metered plan, an unguarded address is a spending risk before it is anything else, and it is the kind of spending risk that shows up a month later on a bill nobody can explain. It is worth reading alongside what happens to your automations when the plan runs out, because that is where an unexplained volume spike eventually lands.

What to ask the person who built it

This is not a job you should do yourself, and this article deliberately does not explain how it is done. It is a conversation to have with whoever built your connections, and these are the questions worth asking.

Which of our systems are called from outside, and what does each one do when called? Start with an inventory. Most owners are surprised by the length of the list, and by discovering that one of the addresses triggers something involving money.

Does anything check who is calling, on each of those? Not "is it secure" — that invites a reassuring answer. Ask it per connection, and expect a different answer for the ones built on a payment platform than for the ones built in an automation tool.

Where else does that address exist? In a document, in an email, in the source of a public page, in a contractor's notes, in a tool you have stopped using. Every copy is a copy of a password.

What happens if the same message arrives twice? The vendors say it will. Somebody should be able to tell you what your side does about it.

How would we find out if the platform stopped calling? If the answer involves somebody noticing that orders look thin, that is the answer, and it is worth knowing before the quiet week rather than after it.

Who has this on their list now? Not who built it. Who is responsible for it this quarter. This is the same question as in whose accounts does your automation actually run on, and it tends to have the same uncomfortable answer.

When this stops being a settings question

For a business with one or two connections built on a payment platform that signs its calls, the questions above are the whole job. Ask them, write down the answers, and revisit when something new gets connected.

It stops being that when the connections multiply and stop resembling each other. Five systems calling in, built at different times by different people on different tools, each with its own answer to who is trusted, what happens on a repeat, and what happens on an outage. At that point the exposure is not any single address. It is that no one document says what all of them do, and the answer changes every time somebody adds a sixth.

Working out whether you need a conversation or a rebuild is what the process audit settles: what can be automated, in what order, and what each piece is worth, in writing, in three business days.