integrations
FastAPI
A complete Python receiver using FastAPI. Handles signature verification, filters by job type, logs each posting, and returns a fast 200.
Dependencies
pip install fastapi uvicorn
main.py
# main.py
import hmac
import hashlib
import json
import logging
from fastapi import FastAPI, Header, HTTPException, Request
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
WEBHOOK_SECRET = "replace-with-your-sign-key"
def verify_signature(jobs: list[dict], secret: str, received: str) -> bool:
canonical = json.dumps(
sorted(jobs, key=lambda j: j["url"]),
sort_keys=True,
separators=(",", ":"),
)
expected = hmac.new(
secret.encode("utf-8"),
canonical.encode("utf-8"),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, received)
@app.post("/webhook")
async def receive_webhook(
request: Request,
webhook_signature: str = Header(..., alias="webhook-signature"),
):
body = await request.json()
jobs: list[dict] = body.get("data", [])
if not verify_signature(jobs, WEBHOOK_SECRET, webhook_signature):
raise HTTPException(status_code=401, detail="Invalid signature")
for job in jobs:
# Skip test events in production
if job.get("is_test"):
logger.info("Skipping test event")
continue
# Filter by job type
if job.get("is_intern"):
logger.info("Internship: %s at %s", job.get("title"), job.get("company_name"))
elif job.get("is_fte"):
logger.info("FTE: %s at %s", job.get("title"), job.get("company_name"))
return {"ok": True, "received": len(jobs)}Run it
uvicorn main:app --reload --port 8000
Local testing with ngrok
Freshbatch needs a public URL to POST to. During local development, use ngrok to tunnel your local server:
# In a separate terminal ngrok http 8000 # Copy the https:// URL ngrok gives you, e.g.: # https://abc123.ngrok-free.app/webhook # Paste that into Dashboard Settings as your webhook URL
For signature verification details, see Signature Verification — Python