Skip to main content

FastAPI

Install

pip install fact0-sdk fastapi

Async client with lifespan

from contextlib import asynccontextmanager
from fastapi import FastAPI
import fact0

audit: fact0.AsyncClient | None = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global audit
    audit = fact0.AsyncClient(api_key="f0_live_...")
    yield
    await audit.close()

app = FastAPI(lifespan=lifespan)

Request-level audit middleware

from fact0.integrations.fastapi import AuditMiddleware

app.add_middleware(
    AuditMiddleware,
    client_factory=lambda: audit,
    action_prefix="api",
)
The middleware logs api.request on each request with method, path, status, and duration in metadata.

Manual instrumentation

@app.post("/approve/{invoice_id}")
async def approve(invoice_id: str, user: User = Depends(get_user)):
    await audit.audit.log(
        actor={"id": user.id, "type": "human"},
        action="invoice.approve",
        resource={"id": invoice_id, "type": "invoice"},
        outcome="success",
    )
    ...
Use the same resource.id (often an execution ID) across all steps of one agent run for correlated filtering.