Docs
Usage API
Authenticate with a bearer API key from the dashboard. Events persist to Postgres. A daily cron rolls the previous UTC day when CRON_SECRET is set.
POST /api/v1/usage
curl -X POST "$APP_URL/api/v1/usage" \
-H "Authorization: Bearer um_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: evt_123" \
-d '{
"meter": "api_calls",
"quantity": 12,
"timestamp": "2026-09-05T13:00:00Z"
}'Body
meter— slug of a meter you created (default:api_calls,seats).quantity— positive number.timestamp— optional ISO-8601. Defaults to now.idempotency_key— advanced, optional. Same as theIdempotency-Keyheader. Same tenant + key returns the original event. We do not double-count.
Advanced: Idempotency-Key
Send Idempotency-Key or idempotency_key. Same tenant + key returns the original event. We do not double-count.
Advanced: hard caps
Hit the monthly ceiling and the API says so — a 4xx (429) with an error body. We do not silently drop the event. Meter count is capped the same way when you try to add another meter. Published caps: Starter 10,000 / 2 · Pro 500,000 / 20 · Scale 5,000,000 / 100.
GET /api/stripe/webhook
Returns { ok, path, configured }. configured is true when STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET are set. POST without stripe-signature is 400. Verified events update plan from STRIPE_PRICE_PRO / STRIPE_PRICE_SCALE for checkout, subscription, and invoice paid/failed.
GET /api/health
Returns process health, whether DATABASE_URL pings, and whether Stripe keys are present. No secrets.
GET /api/cron/aggregate
Authorize with Authorization: Bearer $CRON_SECRET. Sums yesterday (UTC). When Stripe is configured, tries invoice items or usage records. Without Stripe keys this is a ledger write only.