Webhooks and event-driven integrations
In short: A webhook is an HTTP POST that a system sends to your URL when an event happens, such as an alert or a configuration change. It is faster and lighter than polling. A safe receiver uses HTTPS, verifies an HMAC signature and timestamp, replies quickly and handles duplicate deliveries.
What a webhook is
With a normal API call, your script asks a question and waits for an answer. A webhook flips that around. You give a system a URL, and when something happens, such as an interface going down, a firewall policy being changed or a pull request being merged, the system sends an HTTP POST with details of the event to your URL. Webhooks are sometimes called reverse APIs or HTTP callbacks.
Where you will use them
| Source | Event | Typical action |
|---|---|---|
| Monitoring system | Device unreachable | Post to team chat, open ticket |
| Git platform | Change merged | Run a pipeline that tests and deploys config |
| Network controller | New device joined | Add it to inventory and backup jobs |
| Cloud security tool | High-severity finding | Notify SOC (Security Operations Centre) |
| Chat platform | Command typed by engineer | Run a network check and reply |
Webhooks are the glue of event-driven automation: one system raises an event, another reacts, with no person in the middle and no script polling every minute.
Building a receiver safely
Your webhook URL is reachable from the network, so anyone who finds it can send fake events. Most providers protect against this by signing each delivery with a shared secret using an HMAC (Hash-based Message Authentication Code), often HMAC-SHA256, and sending the signature in a header. Your receiver recomputes the HMAC over the raw body and compares.
import hashlib, hmac, os, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["WEBHOOK_SECRET"].encode()
seen_ids = set() # use a database or cache in production
@app.post("/hooks/monitoring")
def monitoring_hook():
body = request.get_data() # raw bytes
sent_sig = request.headers.get("X-Signature", "")
ts = request.headers.get("X-Timestamp", "0")
if abs(time.time() - int(ts)) > 300:
abort(400) # too old: possible replay
expected = hmac.new(SECRET, ts.encode() + b"." + body,
hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sent_sig):
abort(401)
event = request.get_json()
if event["id"] in seen_ids:
return "", 200 # duplicate delivery
seen_ids.add(event["id"])
queue_for_processing(event) # do slow work elsewhere
return "", 202
The exact header names and signing format differ between providers, so follow their documentation. The principles do not change:
- Use HTTPS with a valid certificate.
- Verify the signature over the raw body with a constant-time comparison (
hmac.compare_digest). - Check a timestamp to block replayed old messages.
- Reply fast (within a few seconds) and do heavy work in a background job, or the sender will time out and retry.
- Be idempotent: senders retry, so the same event may arrive twice. Store event IDs and skip repeats.
- Treat the payload as untrusted: validate fields and never pass them straight into shell commands.
Tip: to test a receiver, build it in a lab and send signed sample events with curl or a small Python script, rather than exposing your laptop to the internet.
Design choices and mistakes
If the receiver is down, events may be lost after the sender gives up retrying. For important flows, keep a scheduled reconciliation job that polls occasionally to catch anything missed. Exposing receivers directly to the internet widens your attack surface; place them behind a reverse proxy or API gateway with rate limiting, and allow only the provider’s published source addresses where possible. Rotate the shared secret like any other credential. In interviews, be ready to explain why webhooks need signature verification and idempotency, and when polling is still the simpler choice.
Practice
Why should a webhook receiver acknowledge quickly and process later?
What does verifying an HMAC signature prove?
How do you stop a duplicate delivery from opening two tickets?
Key takeaways
- Webhooks push events to your URL; polling repeatedly asks for changes.
- Verify an HMAC signature over the raw body and check a timestamp.
- Reply with 2xx quickly and process events in the background.
- Expect retries and duplicates; make handlers idempotent.
- Treat payloads as untrusted input and protect the endpoint like any API.
Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.