Skip to main content

Fasthook is a webhook framework for FastAPI Applications

Project description

🪝 Fastapihooks

Fastapihooks is a high-performance, and pluggable webhook management system for FastAPI. It allows you to "webhook-enable" any router with a single decorator, offloading the heavy lifting to a scalable sidecar worker while keeping your API response times near zero.

📚 Documentation

✨ Key Features

  • ⚡ Zero-Impact Emission: Uses FastAPI BackgroundTasks to ensure webhook processing never slows down your API flow.

  • 🔌 Backend by Design, Extensions by You: Fastapihooks ships with BackgroundTaskBackend only. Build Redis/Kafka/SQS backends by implementing BaseBackend.

  • 🛠️ Sidecar Worker: A dedicated async engine designed for high-concurrency delivery with built-in retries and HMAC signing.

  • 🛡️ Secure by Default: Optional HMAC-SHA256 signing — when a signing_secret is provided, every delivery includes a verifiable X-Fastapihooks-Signature header.

  • 📊 Observable: Telemetry support (Logfire, OpenTelemetry, Prometheus) planned for a future release.

  • 📝 Type-Safe: Powered by Pydantic for flexible payload transformations.

Quick Start

  1. Install
    pip install fastapihooks
    
  2. Configure
    from contextlib import asynccontextmanager
    from fastapi import FastAPI, BackgroundTasks, Request
    from fastapihooks import Fastapihooks
    from fastapihooks.backends import BackgroundTaskBackend
    
    hooks = Fastapihooks(backend=BackgroundTaskBackend(signing_secret="your-secret"))
    
    @asynccontextmanager
    async def lifespan(app: FastAPI):
        async with hooks:   # closes HTTP connections on shutdown
            yield
    
    app = FastAPI(lifespan=lifespan)
    
    @app.post("/orders")
    @hooks.hook("order.created")
    async def create_order(request: Request, background_tasks: BackgroundTasks):
        # Your business logic here
        return {"id": "ord_123", "status": "confirmed"}
    
  3. Run the Worker (The Sidecar)
    # Not required for BackgroundTaskBackend; dispatch runs in FastAPI BackgroundTasks.
    # Use the sidecar only when you implement a queue backend with consume()/ack().
    fastapihooks start --backend-module myapp.backends:custom_backend --store-module myapp.stores:store --signing-secret "your-secret"
    

Advanced Capabilities

Flexible Transformations

Don't just dump your API response. Use the FastapihooksContext to shape exactly what your subscribers see.

def my_transformer(ctx: FastapihooksContext):
    return {
        "event": ctx.event_name,
        "order_id": ctx.response_payload["id"],
        "user_agent": ctx.headers.get("user-agent")
    }

@app.post("/orders")
@hooks.hook("order.created", transform=my_transformer, include_headers=True)
async def create_order(...):
    ...

include_request=True caveat — When FastAPI parses a Pydantic model parameter (e.g. body: OrderIn), it consumes the request body before your handler runs. After that, await request.body() returns empty bytes and ctx.request_payload will be b"". Use include_request=True only when you inject the raw Request and read the body yourself. If you only need request headers, prefer include_headers=True — that is always safe.

Pluggable Architecture

Component Responsibility Available Drivers
Backend Transport Layer BackgroundTaskBackend (Built-in), custom via BaseBackend
Store Subscription Data SQLStore (PostgreSQL, MySQL, SQLite via SQLAlchemy), MemoryStore (dev/testing), custom via BaseStore
Telemetry Observability Planned — Logfire, OpenTelemetry, Prometheus

Custom Store Contract

Use BaseStore to bring your own subscription storage — MongoDB, DynamoDB, Redis, or anything else.

from collections.abc import Iterable
from typing import Any, Literal

from fastapihooks.stores import BaseStore, StoredWebhookSubscription


class MyMongoStore(BaseStore):
    async def add_subscription(self, event_name, target_url, auth_type="none", auth_value=None, metadata=None) -> str:
        ...  # insert and return generated ID

    async def remove_subscription(self, subscription_id: str) -> bool:
        ...  # delete by ID, return True if found

    async def get_subscriptions(self, event_name: str) -> Iterable[StoredWebhookSubscription]:
        ...  # query by event_name

    async def update_subscription(self, subscription_id, target_url=None, auth_type=None, auth_value=None, metadata=None) -> bool:
        ...  # partial update, return True if found

Custom Backend Contract

Use BaseBackend to add your own transport backend while keeping the main library lightweight.

from typing import Any

from fastapihooks.backends import BaseBackend
from fastapihooks.stores.base_store import WebhookSubscription


class MyQueueBackend(BaseBackend):
    async def publish(
        self,
        event_name: str,
        payload: Any,
        owner_id: str | None,
        subscribers: list[WebhookSubscription] | None = None,
    ):
        # enqueue event to your transport
        ...

    async def consume(self):
        # yield queued events for worker mode
        ...

    async def ack(self, event_id: str):
        # ack successful processing
        ...

Scalability Design

Fastapihooks is designed for horizontal scale. By using an asynchronous backend (eg: Redis Stream Backend), you can run multiple sidecar workers in a Consumer Group. This allows you to process millions of webhooks across a cluster of workers without duplicate deliveries.

Security: HMAC Verification

Fastapihooks signs every payload. Your users can verify the authenticity of a webhook using the X-Fastapihooks-Signature header.

The header value is formatted as sha256=<hex-digest>, matching the convention used by GitHub, Stripe, and most webhook providers.

import hashlib
import hmac

def verify_signature(payload: bytes, secret: str, header: str) -> bool:
    algorithm, _, received = header.partition("=")
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapihooks-0.1.0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapihooks-0.1.0-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file fastapihooks-0.1.0.tar.gz.

File metadata

  • Download URL: fastapihooks-0.1.0.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastapihooks-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c3e7f61a77ccfe416e419a5c024c8b76e68378318e344301e9219387b5cc6d1d
MD5 57f16828cce2a8f8f7eea2db5c15c46c
BLAKE2b-256 32ae1f5c1da6059027cdb3983003488f984e3a3f09646338849de2acdeeb2fe4

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapihooks-0.1.0.tar.gz:

Publisher: publish.yml on iudeen/fastapihooks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastapihooks-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fastapihooks-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastapihooks-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3eb62b37ed0e5fbe883a5b3ba770eab92eb7118b2dfcf1bae7adcc751b911c4b
MD5 a263d4db2549c31ec7b002c2a2bf38cb
BLAKE2b-256 2822fe43ea3b82b6ad620880292f6242759e11a564d0d5c5c6f33967f911ba0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapihooks-0.1.0-py3-none-any.whl:

Publisher: publish.yml on iudeen/fastapihooks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page