Getting started

Authentication & keys

Store, validate, rotate, and revoke CLSSAI API keys safely.

On this page

This page is for developers and operators who decide where API keys live and how a team rotates them.

Use the standard server-side header for OpenAI-compatible calls:

Plain textPlain rendering
Authorization: Bearer $CLSSAI_API_KEY

Create and manage keys at Workspace keys (sign-in required). Never put a key in frontend source or application logs. Store it in a server-side secret manager or environment variable. Prefer authentication headers. Every route also accepts a ?key= query parameter, and it takes precedence over headers; if a client requires it, keep the URL server-side and sanitize it from logs.

Native clients may use their standard authentication form: x-api-key for Anthropic and x-goog-api-key for Gemini. Anthropic Messages also accepts Authorization: Bearer. Gemini does not: send the key as x-goog-api-key or as a ?key= query parameter. A Bearer token on a Gemini route is passed upstream and rejected with 401. A ?key= query parameter is accepted on every route, not only Gemini's; use it only when a client leaves you no header option.

Validate a key#

The public model list does not require a key, so it confirms connectivity rather than key validity.

BashSyntax highlighted
curl https://api.clssai.com/v1/models \
  -H "Content-Type: application/json"

Validate the key with a minimal inference call:

BashSyntax highlighted
curl https://api.clssai.com/v1/chat/completions \
  -H "Authorization: Bearer $CLSSAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-5.4-nano","messages":[{"role":"user","content":"Reply with OK."}],"max_tokens":8}'

Inspect balance and key state#

GET /v1/balance validates the presented key and returns its current balance projection and state. Expired or disabled keys still return HTTP 200 from this endpoint; check both booleans before allowing work.

BashSyntax highlighted
curl https://api.clssai.com/v1/balance \
  -H "Authorization: Bearer $CLSSAI_API_KEY"
JSONSyntax highlighted
{
  "object": "balance",
  "key": "sk-...abc123",
  "identity": "account",
  "remaining_usd": 2.25,
  "limit_usd": 2.5,
  "recharge_usd": 2,
  "credit_usd": 1,
  "allocated_usd": 0.5,
  "consumption_usd": 0.25,
  "grace_usd": 0.1,
  "expires_at": null,
  "expired": false,
  "disabled": false,
  "settlement": "asynchronous",
  "note": "consumption_usd settles asynchronously and can lag recent requests by minutes; shared child Keys report the parent balance."
}

identity is account, allocated_child, or shared_child. A shared child reports its parent's balance without exposing the parent key. consumption_usd can lag by several minutes because settlement is asynchronous. The projection is remaining_usd = max(limit_usd - consumption_usd, 0). expires_at is null for a key with no expiry, otherwise a Unix timestamp in seconds. grace_usd is a small request-admission allowance, not spendable balance; do not include it in remaining_usd.

Rotate or revoke#

Create the replacement key, update server secrets, verify one request, and then revoke or unbind the old key in Workspace keys. Keys can be account keys, independently funded child keys, or shared child keys whose usage is charged to a parent. An expired or disabled child can fail independently; an allocated child also stops when its parent is disabled or expired.

Authentication failures#

A missing or unknown key returns 401. Expired, disabled, parent-disabled, or depleted keys return 402. Other upstream authorization decisions can be returned as 403.

JSONSyntax highlighted
{"error":"Unauthorized: Missing API key"}

For 401, confirm that the environment variable is present, begins with sk-, and is sent in the header. For 402, inspect the key state and balance rather than retrying unchanged.

Common mistakes#

  • Include /v1 in the OpenAI SDK base URL.
  • Do not send secrets from browser JavaScript. A browser call may succeed; the key is still exposed to every visitor.
  • Do not paste a complete key into logs or support messages.
  • Check expired and disabled in a 200 balance response, and do not treat grace_usd as balance.
  • Use the Anthropic SDK base URL without /v1.
  • For Gemini, use x-goog-api-key or ?key= instead of Bearer authentication.
  • Spell :free and :batch model variants as complete author/model:variant IDs.
  • Use cf-ray, not a made-up application header, as the inference trace identifier.
Need a hand?

Find answers to common questions or diagnose a failed request.

Frequently asked questions →Troubleshoot errors →