Errors
Every API error response carries a code, message, optional hint, and a docs_url that points to a section on this page. Look up the code here for what it means and how to fix it.
{
"error": {
"code": "insufficient_credits",
"message": "The credit balance is too low for this request.",
"hint": "Prompt the user to purchase more credits or top up.",
"docs_url": "https://usequota.ai/docs/errors#insufficient_credits"
}
}Authentication
invalid_api_key 401#
The bearer token in Authorization is missing, malformed, revoked, or for a different environment (e.g. a dev key sent to prod). Also fires when the token is fine but doesn't map to a known principal.
Fix: verify your sk-quota-… / quota_token_… / sess_… token is correct and active. Manage API keys at /dashboard.
invalid_token 401#
OAuth-specific: the access or refresh token failed validation. Common causes: expired token, single-use authorization code already consumed, or token issued by a different client.
Fix: if it's an access token, refresh it (see Connect Wallet → token refresh). If it's a code at /oauth/token, the code expired or was reused — re-run consent.
insufficient_scope 403#
The OAuth access token doesn't carry a scope this endpoint requires. /v1/balance needs credits.read; /v1/chat/completions needs credits.spend.
Fix: add the missing scope to your /oauth/authorize request and re-run the consent flow. See Scopes.
Billing
insufficient_credits 402#
The wallet that would be charged doesn't have enough credits to cover the request. Fires on chat completions, audio, and on POST /v1/funding/credit when the developer wallet can't cover a transfer.
Fix: top up the affected wallet — the developer wallet (Stripe checkout at /dashboard) or the end-user's wallet (render <QuotaBuyCredits /> from the Next.js SDK).
rate_limit 429#
Emitted by billing and provider paths when an upstream rate limit translates back into a Quota error response. Distinct from rate_limit_exceeded (Quota's own per-key throttle) and rate_limited (identity-flow throttle) — see below.
Fix: implement exponential backoff. The response includes Retry-After when the limit is fixed; otherwise back off and retry.
rate_limit_exceeded 429#
Quota's own per-API-key throttle, fired by the global rate-limit hook. Default is 100 req/min per key (configurable via RATE_LIMIT_PER_MINUTE). Keyed by API-key hash for authenticated requests, by IP otherwise.
Fix: implement exponential backoff. For sustained high throughput, ask for a per-key override. Health checks (/health) and Stripe webhooks are allow-listed and never produce this code.
rate_limited 429#
Identity-flow throttle on auth endpoints. Emitted by POST /auth/send-verification (3 issuances/hour per user) and POST /auth/change-password (5 attempts/15 min per user). These limits are DB-backed so they survive restarts and load-balanced replicas, separate from the global per-key throttle.
Fix: wait the window out. For password change, the count survives a wrong current_password — that is deliberate (the attacker model is brute-forcing a stolen session). For email verification, calling the endpoint after the user is already verified does not consume a slot.
Request validation
bad_request 400#
The request body or headers didn't validate — missing required field, wrong type, or a header the endpoint expected but didn't receive (e.g. Idempotency-Key on funding).
Fix: read the message — it names the exact field. Most schemas reject before the handler runs; if you're seeing FST_ERR_VALIDATION / invalid_request, that's also a schema reject.
invalid_request 400#
A more specific request shape problem, typically on the OAuth endpoints: missing response_type, missing code_challenge (PKCE is required), malformed redirect_uri, or unsupported grant type.
Fix: the message names the parameter. For OAuth, see PKCE for the required flow shape.
not_found 404#
A referenced resource doesn't exist — the most common cause is calling an endpoint with an ID that was never created (e.g. an OAuth app, webhook, or API key that doesn't belong to the authenticated developer).
Fix: verify the ID and that the authenticated developer owns the resource.
user_not_found 404#
Internal billing path — the principal the bearer token resolves to doesn't map to a user row. Generally surfaces when a token outlived an account deletion.
Fix: re-authenticate. If you're seeing this for an OAuth user, the linked Quota account was likely deleted; ask the user to sign in again.
model_not_found 404#
The model in your request isn't a model Quota supports. Common causes: typo, dropped provider prefix (anthropic/, google/, elevenlabs/), or a model that's been retired.
Fix: call GET /v1/models for the live list, or see Models reference.
OAuth client errors
invalid_client 401#
On POST /oauth/token: client_id /client_secret don't match a registered OAuth client, or the client has been revoked.
Fix: re-fetch credentials from your developer dashboard. If you rotated the secret recently, deploy the new one. See OAuth secret rotation.
invalid_grant 400#
On POST /oauth/token: the supplied code, refresh_token, or code_verifier didn't verify. Codes are single-use and expire fast; refresh tokens are revocable.
Fix: for authorization codes, re-run the consent flow. For refresh tokens, treat as "user must re-authenticate" and bounce them back through /oauth/authorize.
invalid_scope 400#
The scope at /oauth/authorize contains a value not in the OAuth client's allowed_scopes (or not a valid Quota scope at all).
Fix: add the scope to your app's allowed list (\`PATCH /developers/apps/:id\`) or remove it from the request. See Scopes for the closed vocabulary.
unauthorized_client 400#
The OAuth client is registered but isn't permitted to use the grant type or response type you requested. Most common: public clients trying to use confidential-only flows.
Fix: check the client's registered configuration, or use a flow the client is authorized for (typically authorization code with PKCE).
Upstream provider errors
provider_misconfigured 503#
The upstream provider (OpenAI / Anthropic / Google / ElevenLabs) rejected the request because the configured key is invalid, the provider account needs billing enabled, the plan tier doesn't permit the requested resource, or no key is configured at all. End-users see a generic "unavailable" message — we deliberately do not leak which provider is misconfigured.
Fix: open the developer dashboard and check the provider keys for the requested model family. Common causes:
- Free-tier provider account being asked to use a paid feature (e.g. ElevenLabs library voices).
- Key rotated upstream but not updated in Quota.
- Provider billing card declined or trial expired.
OPENAI_API_KEY/ANTHROPIC_API_KEY/GEMINI_API_KEY/ELEVENLABS_API_KEYsimply not set on this Quota deployment.
provider_unavailable 503#
The provider responded with a 5xx, connection-reset, or otherwise indicated transient unavailability. Distinct from provider_misconfigured: nothing is wrong with your configuration — the upstream is just having a bad minute.
Fix: retry with exponential backoff. If persistent, check the provider's status page. We never retry automatically on Quota's side — your client gets full control over the retry policy.
provider_timeout 504#
Quota gave up waiting on the upstream provider. Tends to fire on very long completions, large prompts on slower models, or when a provider region is degraded.
Fix: retry. Consider switching to a smaller model or using streaming if you're hitting timeouts on large completions.
provider_rate_limited 429#
The upstream provider rate-limited Quota's call. Distinct from Quota's own per-key rate_limit: provider_rate_limited means we hit the provider's TPM / RPM ceiling.
Fix: retry with backoff. For sustained high throughput, consider distributing load across multiple keys or providers.
content_filtered 400#
Provider content-safety system rejected the prompt or completion. Each provider has its own filter; the response message hints which filter tripped.
Fix: rephrase the prompt, or try a different model with different safety settings.
upstream_error 502#
The provider returned an error that didn't map cleanly to one of the more specific codes above. The original error is logged server-side; the message includes whatever the provider sent that's safe to surface.
Fix: retry. If persistent and the message isn't self-explanatory, contact support with the response time + correlation ID (in headers).
pricing_error 500#
Quota couldn't price the request — model has no pricing entry, or the calculation overflowed. Rare; indicates a configuration gap on our side.
Fix: file an issue with the model ID and request shape. Workaround: switch to a different model.