platform
Authentication
CatState users authenticate with a single API key — an org key or a delegated sub-key. QPU access is BYOA-only: provider credentials live in the vault, never in your code.
API keys
Two token formats exist. Org keys start with cs_live_, sub-keys with cs_sub_. Both are 32 random alphanumeric characters (~190 bits of entropy). Plaintext is never stored — only a SHA-256 hash — so copy the token when it's minted; it cannot be retrieved again.
{"Authorization": "Bearer cs_sub_9fa8b7c6d5e4...","Idempotency-Key": "7b9a2c1f-4e5a-4b6c-8d7e-1f2a3b4c5d6e"}
The SDK
The SDK reads CATSTATE_API_KEY from the environment. A sub-key works anywhere an org key does — scope is enforced server-side:
import catstatecs = catstate.connect() # org key OR sub-keycs.devices() # devices visible to this key's allowlistcs("ionq:aria") # allowed if ionq:aria is in scope
Human auth (dashboard)
The dashboard doesn't use API keys. Login screens call the dedicated auth service, which sets short-lived JWT access tokens and refresh tokens in httpOnly cookies. The core API validates JWTs statelessly — no database round-trip. Machine-to-machine traffic (SDKs, CI) always uses Bearer API keys.
Rate limits
Job submission is limited to 300 requests/minute per key; reads to 600/minute. Exceeding a limit returns 429 with a Retry-After header. The unauthenticated simulator playground is capped at 10 requests/minute per IP.