Skip to content

Scopes ​

Every capability an app can use is gated by a scope. An app declares the scopes it needs in its block.manifest.json; a moderator reviews them; and at runtime the host mints a short-lived block token carrying only the approved-and-granted subset. The block never holds a long-lived credential.

The table below is generated from the civitai scope constants — the same source the manifest validator and the token minter read.

ScopeWhat it authorizesOAuth bitBinding
models:read:selfRead the model on the page where the block is mountedModelsReadBound to the model on the page where the block is mounted (a model-slot install supplies the modelId context).
user:read:selfRead the viewer's username and account statusUserReadSelf-bound to the token subject; rejected for an anonymous subject.
ai:write:budgetedRun AI work that spends the viewer's Buzz, with a per-call capAIServicesWriteHost-enforced per-call Buzz cap; the token carries a buzzBudget claim the host clamps against.
buzz:read:selfRead the viewer's Buzz balanceBuzzReadSelf-bound to the token subject (the signed-in viewer).
social:tip:selfPost tips on behalf of the viewerSocialTipSelf-bound: tips are posted as the token subject.
apps:storage:readRead this app's private per-install data store—Scoped to this app's private per-install store; asserted per read op.
apps:storage:writeWrite to this app's private per-install data store—Scoped to this app's private per-install store; asserted per write op.
apps:storage:shared:readRead this app's shared, community-wide data (e.g. everyone's posts + vote counts)—Scoped to this app's shared (cross-user) store; min-trust gate + fail-closed flag. Never minted for dev-tunnel / dev-token sessions.
apps:storage:shared:writePost + vote in this app's shared, community-wide data — visible to all users of the app—Scoped to this app's shared (cross-user) store; min-trust gate + fail-closed flag. Never minted for dev-tunnel / dev-token sessions.
collections:read:selfBrowse and read public Civitai collections, and your own public collections—Self-bound; public collections + the viewer's own public collections. Consent-exempt (server visibility/ownership is the gate).
collections:write:selfBookmark (follow) collections on your behalf—Self-bound: follow/bookmark on the viewer’s own behalf. Consent-exempt.
collections:read:privateRead your private collections—Self-bound; CONSENT-GATED — the viewer must grant it via the host consent gate before a token carries it.
posts:write:selfPublish posts to your profile from this app's own results — you approve each oneMediaWriteSelf-bound to the token subject; an anonymous subject is rejected — there is no anonymous profile to post to. CONSENT-GATED and SENSITIVE: a manifest declaring it must carry a scopeJustifications entry or submit is rejected. The grant alone is not the whole consent story — the host also opens a per-post confirm rendering the resolved title, tags and images, because the content differs every time and a blanket grant cannot inform.
goods:read:selfSee which of this app's items you already own—Self-bound, and app-bound: the reply is scoped server-side to the calling app's own blockId, so an app only ever sees the entitlements IT sold to this viewer — never their purchases in any other app. Consent-exempt for that reason (the server-side app scoping is the gate, as with the collections read scopes); a non-anonymous subject is still required. No OAuth bit — an app good is a platform-mediated entitlement that touches none of the viewer's Civitai resources through the OAuth surface.
goods:purchase:selfBuy this app's items with your Buzz—Self-bound: the purchase is billed to the token subject, and an anonymous subject is rejected — there is nobody to bill. CONSENT-GATED and SENSITIVE: money leaves the viewer's balance, so it needs an explicit grant AND a scopeJustifications entry or submit is rejected. Bounded rather than prohibited on page apps: the price is review-gated and hard-capped per purchase, with a per-user daily ceiling across every app. It does NOT consult the per-app daily Buzz budget that governs ai:write:budgeted — that is a separate rail. No OAuth bit, deliberately: reusing social:tip:self's SocialTip bit would let every app already approved to tip start selling goods.

How to read this table ​

  • Scope — the exact string you put in manifest.scopes.
  • What it authorizes — the capability it unlocks.
  • OAuth bit — the underlying OauthClient.allowedScopes bit this scope maps to. Your app's manifest scopes must be a strict subset of the OAuth client's allowed bits (a registration-time gate, re-checked at token issuance). A — means the scope has no OAuth bit and is gated by another mechanism (noted in Binding) rather than the bitmask.
  • Binding — how the scope is constrained at runtime. :self scopes are bound to the token subject (the signed-in viewer) and are rejected for an anonymous subject; model-slot scopes require the model context from the page the block is mounted on.

What this table can't show (the server enforces more) ​

  • Consent gating. Most self-reads are consent-exempt (server visibility is the gate), but some scopes — notably collections:read:private — are consent-gated: the viewer must grant them through the host consent gate before a token will carry them.
  • Dev-token / dev-tunnel restrictions. The shared-storage scopes (apps:storage:shared:*) are deliberately never minted for pre-approval dev sessions; only an approved, mod-reviewed app that declares them gets them.
  • Per-op assertions. Storage scopes are asserted per operation (a read scope can't perform a write) on the server side, independent of what the token carries.

If a scope you declare isn't approved, granted, or in-context, the corresponding host call fails closed — design your app to degrade gracefully.

The refusal carries a machine-readable code that distinguishes these cases from each other — "you never had this scope", "the viewer withdrew it", "the request doesn't match what the token was bound to" and "permission state is temporarily unreadable" all call for different behaviour, and only one of them is retryable. The full list, with statuses and remedies, is in How an app earns.

Civitai Developer Documentation