OAuth scopes
Nine scopes, closed vocabulary. Each token carries a subset; each protected endpoint requires one. Granular scopes let read-only integrations live without spend permission, and let dashboards show a precise consent prompt instead of an all-or-nothing one.
01 The vocabulary
Every scope Quota knows about. New scopes go through code review and a migration — the discovery document's scopes_supported reads from this same source of truth.
| openid | Sign the user in. Triggers an id_token in the token response. Required for any OIDC flow. |
| profile | See the user's display name and avatar. Adds name and picture claims to the id_token (when present in the database). |
See the user's email address. Adds email and email_verified claims to the id_token. | |
| credits.read | See credit balance and usage history. Required by GET /v1/balance, GET /v1/me, and GET /v1/models. |
| credits.spend | Spend credits on the user's behalf. Required by every billing-touching endpoint — POST /v1/chat/completions, POST /v1/messages (Anthropic), POST /v1beta/models/* (Google), and POST /v1/audio/speech. |
| account.read | See account profile and billing settings. Required by the /v1/me account-management surface. |
| account.write | Update account profile and billing settings. Required by payment-method and auto-topoff endpoints under /v1/payments/*. |
| apps.read | See developer apps and API keys. Almost no third-party app should ask for this — it's for first-party tooling. |
| apps.write | Create, update, and delete developer apps. Same first-party-only caveat as apps.read. |
02 Endpoints by scope
Quick lookup — find the scope you need to mint a token for a given call. Every endpoint here is enforced via requireScopeForAuth.
credits.spend
POST /v1/chat/completionsPOST /v1/messages(Anthropic)POST /v1beta/models/*(Google generateContent / stream)POST /v1/audio/speech
credits.read
GET /v1/balanceGET /v1/models
account.read
GET /v1/me
account.write
POST /v1/payments/*(payment methods, auto-topoff)
apps.read / apps.write
Reserved for first-party tooling that manages developer apps and API keys on behalf of a user. No public API endpoint currently requires these scopes — the developer-dashboard surface (/developers/apps/*) is session-authenticated, not OAuth.
03 Requesting scopes
Pass a space-delimited list (URL-encoded as +) on /oauth/authorize. The user sees a consent screen with the human-readable description of each scope.
https://api.usequota.ai/oauth/authorize
?response_type=code
&client_id=quota_client_my_app
&redirect_uri=https://myapp.com/callback
&state=xyz
&scope=openid+profile+email+credits.read+credits.spendGranted scopes are echoed on the token response, and on every introspection of the resulting access token:
{
"access_token": "quota_token_...",
"token_type": "Bearer",
"expires_in": 604800,
"refresh_token": "quota_refresh_...",
"scope": "openid profile email credits.read credits.spend",
"id_token": "eyJ..."
}04 Validation
A requested scope must clear two gates: it must be in the closed vocabulary above, AND it must be on the authorizing client's allowed_scopes list. Either failure produces a clean OAuth error.
| invalid_scope (unknown) | The string isn't in the vocabulary. Typical cause: typo (credits_read instead of credits.read) or referring to a scope from another provider. |
| invalid_scope (not_allowed) | The scope is valid but the client's allowed_scopes list does not include it. Edit the app at POST /developers/apps/:id to widen the allowlist. |
05 Insufficient scope at the API
If a token is missing a required scope, the protected endpoint returns:
{
"error": {
"code": "insufficient_scope",
"message": "Token is missing required scope 'credits.spend'. Granted scopes: [openid, credits.read]. Re-authorize with scope=credits.spend included."
}
}Status 403. The fix is always to re-authorize with the missing scope added — refresh tokens cannot widen scope.
06 Recommended scope sets
| Sign-in only | openid profile email — gets you a verified user identity with name and avatar. No API access. |
| Read-only dashboard | openid email credits.read — show balance and usage; can't spend. |
| User-pays AI app | openid profile email credits.read credits.spend — the canonical set for an end-user-facing chat or completions app billed against the user's balance. |
| Account self-service | openid email account.read account.write — let users edit their own profile, payment method, and auto-topoff from inside your app. |