What is a webhook?
A webhook is a message that one system sends to another the moment something happens. You give the provider a URL. When an event occurs, such as an SMS being delivered or a payment completing, the provider sends an HTTPS request with the details to that URL. Your application learns about it immediately, without having to ask.
That one idea explains most of modern integration. It is why a payment page can update the instant the bank confirms, and why a delivery receipt reaches your system seconds after a text lands on a phone. This guide covers how webhooks work, how they differ from polling an API, how to secure them and how to handle the awkward cases: retries, duplicates and events that arrive out of order. The general concept is also described as an HTTP callback.
How a webhook works
- You register a URL. You tell the provider which events you want and where to send them.
- An event happens. For example, a message changes status from sent to delivered.
- The provider sends a POST. It includes a JSON body and usually a signature header so you can check who sent it.
- Your endpoint answers. A fast 200 response means "received". Anything else, or a timeout, means "try again".
- The provider retries if needed. It waits and tries again, with growing intervals, until it succeeds or gives up.
Webhook vs polling vs API
| Webhook | Polling | Normal API call | |
|---|---|---|---|
| Who starts it | The provider | You, on a timer | You, when you need something |
| Speed of updates | Immediate | As slow as your interval | On demand |
| Wasted requests | None | Many empty checks | None |
| Complexity | Needs a public endpoint | Very simple | Simple |
| Best for | Events and status changes | Systems that cannot expose a URL | Actions and lookups |
Webhooks and APIs usually work as a pair. With an SMS API you send the message, and a webhook tells you what happened to it. Our webhook reference lists the events and fields.
What a webhook request looks like
POST /hooks/telnxo HTTP/1.1
Content-Type: application/json
X-Telnxo-Signature: t=1767000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{
"id": "evt_91c2",
"type": "message.delivered",
"created": 1767000000,
"data": { "message_id": "msg_8f3a2c", "to": "+919812345678", "status": "delivered" }
}The header name and format above are illustrative; the exact scheme is in the documentation. The shape is common: an event id, a type, a timestamp and a data object.
How to verify a webhook
Anyone who discovers your URL can post to it, so never trust a webhook just because it arrived. The usual defence is a signature: the provider computes a hash of the body with a secret that only you and they know, and sends it in a header. You compute the same hash and compare.
import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str, tolerance=300):
parts = dict(p.split("=", 1) for p in header.split(","))
ts, sig = parts["t"], parts["v1"]
if abs(time.time() - int(ts)) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)- Compute the signature from the raw body, not from parsed and re-encoded JSON.
- Compare with a constant-time function to avoid timing leaks.
- Reject old timestamps so a captured request cannot be replayed later.
- Keep the signing secret in a secret manager, and rotate it if it leaks.
Our guide to webhooks, delivery receipts and signatures shows this in more languages. The OWASP API Security project is a good general reference.
Handling retries, duplicates and ordering
Assume every event can arrive twice, late or out of order. Build the handler so that none of those cases causes harm.
| Problem | Cause | Design answer |
|---|---|---|
| Duplicate events | Retry after a slow or lost response | Store event ids and skip ones you have seen |
| Out-of-order events | Retries and parallel delivery | Compare status rank or timestamps before updating |
| Timeouts | Slow handler | Store the event, return 200, process in a background job |
| Missed events | Endpoint down longer than the retry window | Reconcile by listing recent events through the API |
| Spike of events | A large campaign finishing | Queue incoming events and scale workers |
A dependable pattern is: verify, store, acknowledge, then process. Writing the raw event to a database or queue first means you never lose it even if processing fails, and you can replay it after fixing a bug.
Webhooks for messaging: the events you will see
In a messaging platform the most useful events are status changes and inbound messages. Status events tell you a message was accepted, sent, delivered or failed, and they carry an error code when something goes wrong. Inbound events arrive when a customer replies, which is how two-way SMS and WhatsApp conversations reach your application. See the guides to the WhatsApp Business API and why an SMS is not delivered for how these events are used.
Common webhook use cases
- Delivery tracking. Update an order or a notification log when an SMS or WhatsApp message is delivered or fails. See transactional messaging.
- Two-way conversations. Receive customer replies and route them to a bot or an agent, as in customer support workflows.
- Fraud and verification. React when a code is verified or a number is found to be inactive, as in OTP flows.
- Call events. Learn when a call starts, rings, is answered or ends through the voice API.
- Billing and alerts. Warn finance when a balance is low or an invoice is ready; see balance and invoices.
Common webhook mistakes
The same handful of errors cause most webhook incidents. The first is doing too much work inside the request: calling other services, sending emails and updating several tables before answering. If any of that is slow, the provider times out and retries, and you end up doing the work twice. The second is trusting the payload without checking the signature, which lets anyone forge an event such as a fake payment or a fake delivery. The third is parsing the body and then computing the signature from the re-serialised JSON, which almost never matches because spacing and key order change.
Other frequent problems are returning an error status for events you simply do not care about, which triggers needless retries, and forgetting to monitor the endpoint until a customer complains. A simple dashboard of response codes and processing lag catches most of these early. Finally, plan for change: providers add new event types and new fields over time, so ignore fields you do not recognise instead of rejecting the whole request.
Testing and monitoring webhooks
- Expose a local server on a temporary HTTPS address and register it for a test account.
- Send sample events and inspect the headers and body.
- Post a request with a bad signature and confirm you reject it.
- Delay your response beyond the timeout and watch the retry arrive.
- Deliver the same event twice and check that nothing is done twice.
- In production, alert on error rate, response time and the age of the oldest unprocessed event.
The status page and the analytics dashboard show delivery health from the provider's side, and support can help when events stop arriving.
A webhook is a promise to listen. Keep it simple, keep it fast and assume everything will happen more than once.
See webhooks in action. Send a test message and watch the delivery events arrive.
Frequently asked questions
What is a webhook?
A webhook is an HTTP request that one system sends to a URL you provide when an event happens, such as a message being delivered. It lets your application react immediately instead of repeatedly asking for updates.
What is the difference between a webhook and an API?
With an API you make a request and get a response when you ask. With a webhook the provider makes the request to you when something happens. Many services use both: an API to send and a webhook to report results.
How do I secure a webhook?
Use HTTPS, verify a signature on every request, check a timestamp to prevent replays, keep the secret out of code repositories, and restrict what the endpoint can do.
What happens if my webhook endpoint is down?
Good providers retry with increasing delays for a period of hours or days. After that the event may be lost unless it can be fetched later, so you should also be able to list recent events through the API.
Why am I receiving the same webhook twice?
Retries and network problems can cause duplicate delivery. Your handler should be idempotent: use the event id to detect and ignore repeats.
Do webhooks arrive in order?
Not always. Events can arrive out of order, especially after retries. Use timestamps or status ranking so an older event never overwrites a newer state.
How can I test a webhook locally?
Use a tunnelling tool to expose your local server on a public HTTPS address, register that URL for a test account and send sample events. Always remove the temporary URL afterwards.