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 the Idempotency-Key header. 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.