Skip to content
camada
Menu

Quickstart

FastAPI quickstart

Package camada, on PyPI.

1. Install

pip install camada

2. Environment

The key is printed once when you create a project in the app. Set these as environment variables: export them in the shell that starts your app, or add them in your host's settings. Python reads no .env file on its own.

shell
export CAMADA_KEY=<ingest_token>.<snap_token>
export CAMADA_INGEST_URL=http://localhost:8787   # dev only; defaults to production ingest

3. Wire it in

from camada.fastapi import CamadaMiddleware
app.add_middleware(CamadaMiddleware)   # any Starlette app too
  • A pure ASGI middleware: streaming responses and lifespan are untouched.
  • Add it last, so it runs outermost and answers before anything else.

4. Add the beacon to HTML pages

Optional but recommended. The beacon cuts false positives by showing which sessions are real browsers. Use the helper.

from camada.fastapi import script_tag
return f"<head>{script_tag(request)}</head>…"

5. Send app outcomes

Login failures, signups and checkout declines are the signals no edge position sees. The identifier is HMAC-hashed in your process. How they catch credential stuffing.

from camada.fastapi import track
track(request, "login_failed", user=email)

Runtime

What it does per request

  1. Refreshes the snapshot off-path on a daemon thread (30 s poll with ETag, gzip on the wire). A cold start fails open.
  2. Resolves the client IP per your trusted-proxy setting. Raw X-Forwarded-For is never trusted without it.
  3. Your ordered custom rules first, then allow, block, challenge. A block gets a 403 with x-block-reason before your app runs; a challenge serves the proof-of-work page on a page load, and an API call reaches your app with an x-camada-challenge: 1 response header. The event still ships.
  4. Serves /_cam/b.js (the beacon, first-party) and relays /_cam/fp posts onto the event batch with the resolved client IP.
  5. Sets x-rid and the _sfp session cookie, and when the response is done ships one batched, redacted event.

Limits

Caveats at this position

  • Enforcement at this position covers IP, path, user-agent and request-header conditions. ASN, country and TLS-fingerprint entries fail open in-app.
  • ASGI keeps the wire's header order, so the event carries it.
  • Every worker process polls its own snapshot (about 5 MB each) — the server's poll_seconds keeps the cadence honest. Under gunicorn --preload the threads restart after the fork.
  • CAMADA_SERVERLESS=1 switches to lazy refresh with no poll thread.

Kill switch: CAMADA_DISABLED=1, checked per request. All other variables are listed in the docs index; the package's options and deployment notes are on the Python page.