Authentication

Quota supports API keys for server-to-server access and OAuth for user billing. Use API keys for developer billing or OAuth tokens when end users should pay for their own usage.

Developer Account

Create a developer account to get started. All session-authenticated endpoints use the sess_... token returned at login.

Register

POST /auth/register

curl -X POST https://api.usequota.ai/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com",
    "password": "securepassword"
  }'

Email must contain @. Password must be at least 8 characters.

Response (201):

{
  "user": { "id": "uuid", "email": "dev@example.com", "balance": 100 },
  "session_token": "sess_abc123...",
  "expires_at": "2026-02-10T00:00:00.000Z"
}

New accounts receive 100 welcome credits.

Registration Errors

StatusCodeDescription
400invalid_emailEmail format is invalid
400weak_passwordPassword is shorter than 8 characters
409email_existsAn account with this email already exists

Rate limit: 3 requests/minute.

Login

POST /auth/login

curl -X POST https://api.usequota.ai/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com",
    "password": "securepassword"
  }'

Response (200):

{
  "user": { "id": "uuid", "email": "dev@example.com", "balance": 9500 },
  "session_token": "sess_xyz789...",
  "expires_at": "2026-02-10T00:00:00.000Z"
}

Login Errors

StatusCodeDescription
401invalid_credentialsEmail or password is incorrect

Rate limit: 5 requests/minute.

Get Current User

GET /auth/me

Returns the authenticated user. Requires Authorization: Bearer sess_....

{
  "id": "uuid",
  "email": "dev@example.com",
  "balance": 9500
}

Logout

POST /auth/logout

Invalidates the current session token. Requires Authorization: Bearer sess_....

{ "success": true }

API Keys

Create API keys via POST /developers/keys (requires a session token). Keys use this format:

sk-quota-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The sk-quota- prefix prevents mixups with other providers.

Managing API Keys

EndpointMethodDescription
/developers/keysPOSTCreate a new API key (returned only once)
/developers/keysGETList your API keys (no secrets exposed)
/developers/keys/:idDELETERevoke an API key

All key management endpoints require session authentication (Authorization: Bearer sess_...).

Using an API Key

Send your key as Authorization or X-API-Key:

Authorization: Bearer sk-quota-your-api-key
X-API-Key: sk-quota-your-api-key

Example with cURL

curl https://api.usequota.ai/v1/balance \
  -H "Authorization: Bearer sk-quota-your-api-key"

Example with JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.usequota.ai/v1",
  apiKey: "sk-quota-your-api-key",
});

Environment Variables

We recommend storing your API key in an environment variable:

# .env
QUOTA_API_KEY=sk-quota-your-api-key

Then use it in your code:

const client = new OpenAI({
  baseURL: "https://api.usequota.ai/v1",
  apiKey: process.env.QUOTA_API_KEY,
});

Security Best Practices

  • Never commit API keys to version control
  • Use environment variables in production
  • Rotate keys periodically
  • Use separate keys for development and production

OAuth (User Billing)

Use OAuth when end users should be billed from their own balance.

1. Register an OAuth Client

Create an OAuth client via POST /developers/apps (requires session auth):

curl -X POST https://api.usequota.ai/developers/apps \
  -H "Authorization: Bearer sess_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My App",
    "redirect_uris": ["https://myapp.com/callback"]
  }'

Response:

{
  "id": "...",
  "name": "My App",
  "client_id": "quota_client_...",
  "client_secret": "quota_secret_...",
  "redirect_uris": ["https://myapp.com/callback"],
  "created_at": "..."
}

The client_secret is only returned once. Store it securely.

Redirect URI Requirements

  • Development: http://localhost:* and http://127.0.0.1:* are allowed (any port)
  • Production: Must use HTTPS (https://yourapp.com/callback)
  • No wildcards: Each URI must be an exact match — wildcard patterns like https://*.example.com are not supported
  • Multiple URIs: Register separate URIs for dev, staging, and production environments

Managing OAuth Clients

EndpointMethodDescription
/developers/appsPOSTRegister a new OAuth client
/developers/appsGETList your OAuth clients
/developers/apps/:idDELETEDelete an OAuth client

2. Authorization Flow

  1. Redirect users to /oauth/authorize with client_id, redirect_uri, response_type=code, state, and optional scope.
  2. Unauthenticated users see a hosted login/register page (/oauth/login, /oauth/register).
  3. Exchange the returned code at /oauth/token (form-encoded) with grant_type=authorization_code, then store access_token and refresh_token.
  4. Refresh with grant_type=refresh_token when tokens expire.
  5. Fetch user info from /oauth/userinfo; revoke with /oauth/revoke.

Access and refresh tokens are opaque strings prefixed with quota_token_ and quota_refresh_.

Hosted Token Storage (X-Quota-User)

Use hosted token storage when you want Quota to manage OAuth tokens server-side. Instead of storing tokens yourself, send the user's external ID via the X-Quota-User header alongside your API key.

Quick Setup

  1. Create an OAuth app: POST /developers/apps with your redirect URIs
  2. Redirect users to authorize: /oauth/authorize?client_id=...&redirect_uri=...&response_type=code&state=...&storage_mode=hosted&external_user_id=your_user_123
  3. Exchange the code: POST /oauth/token with grant_type=authorization_code — Quota stores the token server-side
  4. Make requests with X-Quota-User: Include X-Quota-User: your_user_123 header with your API key
  5. Quota handles billing: Requests are automatically billed to the linked user's balance

How it works

  1. User connects via OAuth (same flow as above).
  2. Quota stores the token link server-side, keyed by an external user ID.
  3. Your app sends X-Quota-User: external_id with your API key on every request.
  4. Quota resolves the linked user and bills their balance.

Example with cURL

curl https://api.usequota.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-quota-your-api-key" \
  -H "X-Quota-User: user_123" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Hello!"}]}'

Example with OpenAI SDK

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.QUOTA_API_KEY,
  baseURL: "https://api.usequota.ai/v1",  // Include /v1
  defaultHeaders: { "X-Quota-User": userId },
});

Example with Anthropic SDK

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.QUOTA_API_KEY,
  baseURL: "https://api.usequota.ai",  // No /v1 suffix!
  defaultHeaders: { "X-Quota-User": userId },
});

Note: The Anthropic SDK adds its own /v1 prefix, so omit it from the baseURL to avoid /v1/v1/messages.

See Hosted Users API for endpoint details, Core SDK for a framework-agnostic client, or Next.js SDK for a turnkey Next.js integration.

When to Use Which

MethodWho PaysUse Case
API KeyDeveloperInternal tools, backends, prototypes
OAuth TokenEnd userUser-facing apps where users pay for AI usage
API Key + X-Quota-UserEnd userServer-side apps billing users without client-side OAuth

Rate Limits

Default: 100 requests/minute per API key. Funding and auth endpoints use stricter limits. Rate limit headers are included in every response:

HeaderDescription
X-RateLimit-LimitMaximum requests per minute
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the limit resets