Webhooks, and why receiving one is the easy half

The hard part of webhooks is not receiving them but handling duplicates and losses, because senders retry on any doubt and will deliver the same event more than once, while an event you failed to process is gone unless you stored it.

A webhook is someone else calling you when something happens, instead of you asking repeatedly whether it has. Accepting one is a few lines. Trusting the resulting state is the work.

You will get the same event twice

Senders retry when they do not get a clean acknowledgement, including when your handler succeeded but the response was slow or lost. So the same event arrives again, and any handler that simply does the work will do it twice. This is not an edge case, it is the designed behaviour of every sender worth using.

Store first, act second

Write the raw event with its identifier, acknowledge immediately, and process afterwards. That order gives you two things a direct handler cannot have: duplicates are visible because you already hold the identifier, and a failure during processing is recoverable because the event is still on disk. A handler that acts before storing has neither.

The failure you will not notice

Your endpoint returns an error, the sender retries a few times, gives up, and stops. Nothing on your side records that anything was missed. Weeks later a total is wrong and there is no trail, because the only evidence was a request you rejected. This is why the store step is not an optimisation.

Verify that it came from who it claims

A webhook endpoint is a public URL that changes your data. Most senders sign the payload; check the signature before you trust the contents, and reject rather than process on failure. This is ordinary to do and easy to leave until later, and later is after someone has posted something to it.

The test that matters

Send the same event twice and confirm the outcome is identical to sending it once. Then make your handler fail and confirm you can replay the event afterwards. A webhook system that passes both is finished; one that passes neither will be wrong in a way nobody can reconstruct.

Live, right now, on this page

MarketPriceFunding24h volume
BTC$79,657.500.0006%$203,532,857
ETH$2,487.350.0013%$138,334,875
SOL$105.81-0.0012%$46,858,638
HYPE$87.600.0013%$11,072,399

Read from a live market as this page rendered, through a public endpoint that needs no key. Read at 2026-09-06 17:30 UTC; accurate as of that time and not afterwards.

Describe something and watch it get built.

Open the builder, or start from a working app and change it.

Related reading

All guides · Live market pages · Components