Skip to main content

FastAPI AI Kit includes a complete usage-based billing layer: per-request token tracking, buffered metering reports to Stripe, webhook handling, and usage visibility endpoints.

Architecture

LLM call → token count → Redis buffer → (5 min flush) → Stripe metered billing
                ↓
           Postgres (internal analytics + per-key usage)

Configuration

# .env
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_METERED_PRICE_ID=price_...    # Your metered billing price
STRIPE_METERING_ENABLED=true

Disable metering in development with STRIPE_METERING_ENABLED=false.

How billing works

Every metered endpoint records token usage automatically:

# Metering happens inside the LLM abstraction layer
response = await llm.chat(messages=..., track_tokens=True)

# Behind the scenes:
# 1. LLM call completes with token counts
# 2. meter.record(api_key_id, tokens, customer_id) called
# 3. Redis counter incremented (non-blocking)
# 4. Celery beat task flushes to Stripe every 5 minutes

No changes to your endpoint code — add track_tokens=True and metering is automatic.

Stripe setup

  1. Create a product in Stripe Dashboard
  2. Add a metered price (recurring, per unit)
  3. Create a billing meter with event_name: "api_tokens"
  4. Copy the price ID to STRIPE_METERED_PRICE_ID

When a user subscribes, store their stripe_customer_id on the User model. The kit's auth system links this to their API keys automatically.

Webhook handling

The kit handles subscription lifecycle events:

# POST /v1/webhooks/stripe (registered via Stripe Dashboard)

# Events handled:
# customer.subscription.created → activate API key access
# customer.subscription.deleted → deactivate or downgrade
# invoice.payment_failed → send warning email
# invoice.paid → reset monthly limits

Register https://your-api.com/v1/webhooks/stripe in the Stripe Dashboard. Add your endpoint's webhook secret to STRIPE_WEBHOOK_SECRET.

Usage endpoints

Per-key usage

GET /v1/usage?period=current_month

{
    "tokens_used": 84200,
    "requests": 1430,
    "period_start": "2024-11-01T00:00:00Z",
    "period_end": "2024-11-30T23:59:59Z",
    "rate_limit_remaining": {
        "per_minute": 42,
        "per_day": 3570
    }
}

Historical usage

GET /v1/usage?period=last_30_days
GET /v1/usage?start=2024-10-01&end=2024-10-31

Internal analytics

All usage is also written to Postgres for your own analytics:

-- Usage by API key over time
SELECT 
    date,
    SUM(tokens) as total_tokens,
    COUNT(*) as requests
FROM api_key_usage
WHERE api_key_id = '...'
GROUP BY date
ORDER BY date DESC;

Testing billing

Use Stripe's test mode:

STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

Use the Stripe CLI to forward webhooks locally:

stripe listen --forward-to localhost:8000/v1/webhooks/stripe

Disabling billing

If you don't need Stripe:

STRIPE_METERING_ENABLED=false

Token usage still records internally — only Stripe reporting is skipped.