Usage
Docs / Control plane
GET

/v1/usage

Current period counts against the plan's caps so you can alert on headroom before we refuse you. Unlimited caps are null with a limit_note, never a magic zero. Redis down is 503 dependency_unavailable — we never invent a count.

Authentication

Authorization: Bearer spw_…

Requires usage:read.

Keys rule — prefix, shown once, abilities never widen, and no key carries both messages:send and messages:read-content.

Worked example

curl https://spoolway.com/api/v1/usage \
  -H "Authorization: Bearer spw_…"
200 — Free planaccount counters
{
  "data": {
    "period": {
      "timezone": "UTC",
      "day": "2026-08-06",
      "month": "2026-08"
    },
    "plan": "Free",
    "daily": {
      "used": 7,
      "limit": 1000,
      "remaining": 993,
      "limit_note": null
    },
    "monthly": {
      "used": 42,
      "limit": 10000,
      "remaining": 9958,
      "limit_note": "signal only — exceeding the monthly figure does not reject sends"
    }
  }
}
200 — unlimited planTeam · limits null with notes
{
  "data": {
    "period": {
      "timezone": "UTC",
      "day": "2026-08-06",
      "month": "2026-08"
    },
    "plan": "Team",
    "daily": {
      "used": 3,
      "limit": null,
      "remaining": null,
      "limit_note": "unlimited — plan has no daily send cap"
    },
    "monthly": {
      "used": 11,
      "limit": null,
      "remaining": null,
      "limit_note": "unlimited — plan has no monthly volume cap"
    }
  }
}

Null, not zero

HONESTY NOTE — NEVER INVENT A COUNTUnlimited caps return limit: null, remaining: null, and a limit_note that says why — never 0 as a stand-in. On Free/Pro the monthly figure is a signal only (see limit_note); daily reject when exceeded. If Redis cannot answer, the endpoint is 503 with type: dependency_unavailable and Retry-After: 30 — not a zero that would look like headroom.

daily is the account-wide counter only. limit and remaining are the plan and account ceiling, with no application and no member folded in. A send can still answer 429 with dimension application_daily_send, or daily_send with binding application or member, while daily.remaining on this response still shows headroom. The day runs in the account's timezone, the zone period.timezone names. An account with no timezone set uses UTC.

Responses & failures

403 without usage:read. 503 when the counter dependency is down — honour Retry-After; do not treat absence of a body as unlimited headroom.