How to Create a Webhook with FastAPI: A Practical Guide
Webhooks allow external services to push real-time data to your application. With FastAPI, building a webhook receiver is simple, async-friendly, and production-ready. This tutorial covers the essential steps: creating the endpoint, validating payloads, securing requests, and responding quickly.
You’ll need FastAPI and an ASGI server like Uvicorn installed. The core idea is to expose a POST route that accepts JSON data from the webhook sender.

1. Create the Webhook Endpoint
In FastAPI, a webhook is just a POST endpoint. Define a Pydantic model to structure the expected payload:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class WebhookPayload(BaseModel):
event: str
data: dict
@app.post("/webhook")
async def handle_webhook(payload: WebhookPayload):
# Process the event here
return {"status": "received"}
2. Validate the Payload
Pydantic automatically validates incoming JSON. If required fields are missing or types don’t match, FastAPI returns a clear 422 error. For flexibility, you can accept a raw dict, but a structured model is safer and self-documenting.
3. Secure the Webhook
Never trust an unauthenticated request. Most providers sign the payload with a secret key. Verify the signature header (like X-Signature) using HMAC:
import hmac, hashlib
def verify_signature(payload_bytes, signature):
expected = hmac.new(SECRET, payload_bytes, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
Use await request.body() to get the raw bytes, then compare the computed signature against the header.
4. Respond Immediately
Webhook senders often retry on timeouts. Always return a 200 status quickly, then process the event in the background using BackgroundTasks or a queue like Celery. This prevents duplicate deliveries and keeps your webhook fast.
With these four steps—basic endpoint, payload validation, signature verification, and background processing—you have a robust webhook receiver ready for production.