Glossary

Webhook

A webhook is an HTTP request a service sends to a URL you control whenever something happens that you asked to hear about. Instead of your code repeatedly polling an API to ask "has anything changed yet?", the service pushes the event to you as soon as it occurs. The request body carries a description of what happened — an order was paid, a payout failed — and your endpoint reacts to it. Because anyone who learns the URL could post to it, a webhook worth trusting is signed, and the receiver verifies that signature before treating the message as real.

01

What a webhook is

A webhook reverses the usual direction of an API call. Normally your application is the client: it makes a request and the server responds. With a webhook, the server becomes the caller — it makes an HTTP request to an endpoint you registered, sending an event in the body, and your application responds. This is why webhooks are sometimes called reverse APIs or HTTP callbacks. They turn "check again later" into "you'll be told the moment it happens."

The alternative is polling: asking the API over and over whether a state has changed. Polling wastes requests when nothing has happened and still adds latency when something does, because you only find out on the next poll. A webhook removes both costs — the event arrives as soon as it is generated, and there is no idle traffic in between. The trade-off is that your endpoint has to be reachable, has to answer quickly, and has to be ready for the same event to arrive more than once, since most senders retry until they get a successful response.

Two properties make a webhook safe to build on. The first is authenticity: because the receiving URL is just an HTTP endpoint, anything on the internet could send it a forged payload, so the sender signs each request — commonly with an HMAC computed over the body using a shared secret — and the receiver recomputes that signature to confirm the message genuinely came from the sender and was not tampered with in transit. The second is idempotency: networks drop responses and senders retry, so the same event can be delivered twice, and a correct receiver processes each event once and ignores duplicates rather than acting on the same thing twice.

02

What it means in a crypto payment

Crypto payments are inherently asynchronous. A customer broadcasts a transaction, the network includes it in a block, and confirmations accumulate over time — none of which happens on a request-response timeline a checkout can wait on. Webhooks are how a payment processor closes that gap: rather than making a merchant poll for the state of every invoice, it pushes an event when the state changes, so the merchant's systems learn about a confirming deposit, a settled payment, or a failed payout the moment it is known.

The signing requirement matters more here than almost anywhere else, because the event is what releases value — fulfilling an order, crediting an account, marking a payout done. A forged "payment received" message that an endpoint trusted blindly would be a direct path to fraud. The rule is the same on every serious payment platform: verify the signature first, and only then act on the contents. An unsigned or wrongly-signed request is discarded, never processed.

03

Webhooks on halfin

halfin delivers events as HMAC-signed webhooks. Each delivery is a JSON envelope describing what happened, signed with a secret shared between halfin and the merchant. The contract is explicit: verify the signature before taking any business action. A request that does not verify is treated as untrusted and dropped — the signature is the line between an event you can act on and one you cannot.

The events follow the lifecycle of the underlying primitive. For invoices, halfin emits invoice.confirming when a deposit is detected and accumulating confirmations, then invoice.paid once the chain reaches the per-chain confirmation threshold, with invoice.overpaid and invoice.underpaid when the amount that confirmed does not match the invoice. Because crediting is reorg-aware, the lifecycle also covers the unhappy paths: invoice.expired, invoice.late_deposit for a payment that arrives after expiry, and invoice.deposit_reversed when a confirmed deposit is undone by a chain reorganization. Balance and payout activity surface as balance.credited, payout.completed, and payout.failed. An integration listens for the events it cares about, verifies each one, and reacts — fulfilling an order on invoice.paid, reconciling treasury on balance.credited, or retrying on payout.failed.

Because deliveries can be retried, an endpoint should handle the same event arriving more than once without double-acting. Treating each event as idempotent — keyed on the event it describes — keeps a retried webhook from fulfilling an order twice or crediting a balance twice. This pairs with the signature check to make webhook handling both safe and reliable.