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
- Create a product in Stripe Dashboard
- Add a metered price (recurring, per unit)
- Create a billing meter with
event_name: "api_tokens" - 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.
