OAuth scopes

Permission scopes for Hypery OAuth apps and API access

Scopes constrain delegated OAuth tokens. First-party session cookies and personal API keys (ak_…) are not scope-gated — they act as the user.

An OAuth app may only mint scopes that appear in both:

  1. The global allowlist below
  2. The scopes registered on that app

Asking for scopes your app isn't registered for

Following RFC 6749 §3.3, Hypery grants the registered subset of what you ask for instead of failing the sign-in. If your app is registered for read ai:chat and requests read ai:chat ai:audio, the user is asked to approve read ai:chat, and the token carries just those.

The scopes actually granted are always in the token response's scope field (for the authorization_code, refresh_token and token-exchange grants), and the consent page lists only those. Read scope rather than assuming you got what you asked for:

const tokens = await res.json();
const granted = new Set(tokens.scope.split(' '));
if (!granted.has('ai:audio')) hideVoiceFeatures();

So you can ship a client that asks for a new scope before the registration catches up, with no feature flag; it starts receiving the scope once the app is registered for it (and the user re-consents).

The request is still refused with invalid_scope when:

  • none of the requested scopes is registered for the app, or
  • any scope name is malformed or unknown (not in the allowlist below), even beside valid ones.

AI scopes

ScopeGrants
ai:chatChat completions (/chat/completions, /v1/ai/language-model)
ai:completionsAlias for chat completions
ai:modelsList / inspect models
ai:imagesImage generation, predictions, /v1/ai/image-model
ai:embeddingsPOST /api/v1/embeddings and /v1/ai/embedding-model
ai:audioTTS, transcriptions, realtime session mint

Embeddings and audio do not inherit from ai:chat.

Account & billing

ScopeGrants
readRead-oriented management APIs
writeMutating management APIs (where declared)
billing:readWallet / usage reads
billing:chargePOST /api/v1/usage/charge (Browserbase, Deepgram, …; 1× the reported amount)

billing:charge is required for usage charges — ai:chat / write alone are rejected.

App configuration

ScopeGrants
config:storeStore & sync app-specific config blobs — GET/PUT/DELETE /api/config/{key}

config:store is namespaced per app: a token can only read/write blobs stored under its own app id. Values are capped (256 KB/key, 100 keys). Reserve it for apps that sync user settings across devices (e.g. a desktop editor).

Least privilege

Example for a chat + voice + RAG + browser app:

read write ai:chat ai:embeddings ai:audio ai:images ai:models billing:read billing:charge