Skip to content

OAuth Scopes

Civitai OAuth scopes are bitwise flags. To request multiple scopes, OR them together and pass the decimal integer as the scope parameter on the /authorize URL.

text
scope = UserRead | AIServicesRead | AIServicesWrite | BuzzRead
      = 1 | 16384 | 32768 | 65536
      = 114689

Scope reference

BitValueScopeWhat it grants
01UserReadRead profile, settings & email (always granted)
12UserWriteUpdate profile & settings
24ModelsReadBrowse & download models
38ModelsWriteUpload & edit models
416ModelsDeleteDelete models
532MediaReadView images, videos & posts
664MediaWriteUpload media & create posts
7128MediaDeleteDelete media & posts
8256ArticlesReadRead articles
9512ArticlesWriteCreate & edit articles
101 024ArticlesDeleteDelete articles
112 048BountiesReadView bounties
124 096BountiesWriteCreate & manage bounties (buzz spend)
138 192BountiesDeleteDelete bounties
1416 384AIServicesReadView generation & training history
1532 768AIServicesWriteGenerate, train & scan (buzz spend)
1665 536BuzzReadView buzz balance & history
17131 072CollectionsReadView collections
18262 144CollectionsWriteManage collections
19524 288SocialWriteFollow, react, comment & review
201 048 576SocialTipReserved — see below
212 097 152NotificationsReadRead notifications
224 194 304NotificationsWriteManage notification preferences
238 388 608VaultReadView vault
2416 777 216VaultWriteManage vault
33 554 431FullAll scopes

UserRead is always granted

UserRead is a mandatory baseline: every token Civitai issues includes it, no matter what you request on /authorize. An app acting on a user's behalf always needs to know whose account it's on, so the bit can't be dropped. This is why the /userinfo endpoint (including the user's email) always works.

You don't need to add UserRead to your scope parameter explicitly — but including it does no harm, and the consent screen always shows it.

Buzz-spend scopes

Two scopes carry an implicit buzz-spend authorization — granting them lets your app draw from the user's buzz balance:

  • AIServicesWrite — every generation/training/scan request the app makes is billed to the consenting user. This is the only scope subject to the per-app buzz limit cap users can set at consent.
  • BountiesWrite — bounty creation costs buzz at post time. Spend is gated by the user's overall balance only; per-app caps don't apply.

(SocialTip would be a third — see the reserved note below.)

Pair either with BuzzRead if you want to surface the user's remaining balance in your UI before a spend.

SocialTip is currently reserved

The SocialTip bit is defined in the scope enum but every server endpoint that requires it (tipping, donation goals, event tipping) is gated by blockApiKeys: true, which denies all API-key and OAuth callers regardless of scope. Granting SocialTip today is a no-op. The bit stays reserved (and locked at 1<<20) so we don't reshuffle the bitmask when tipping is unblocked for OAuth in the future.

Presets

The app-registration UI exposes four convenience presets. You can also target them from the scope URL parameter directly:

PresetDecimalScopes
Read Only10 701 093All *Read scopes
Creator11 492 205Read Only + Models / Media / Articles / Bounties / Collections Write + SocialWrite
AI Services114 689UserRead | AIServicesRead | AIServicesWrite | BuzzRead
Full Access33 554 431Every defined scope

Use a preset's number on /authorize and the consent screen will still show the user every flag underneath — there's no shortcut around per-scope consent.

Asking for less than you registered

The allowedScopes you set during registration is a ceiling, not a floor. You can ask for any subset of those bits on any individual /authorize call — useful when one user only needs read access but another wants to spend buzz, and you want a single registered app for both.

If you request a scope bit your app isn't registered for, the user is shown the consent screen anyway but Civitai will trim the token to your allowed scopes when it issues it. Read the scope value back from the token-endpoint response — it's authoritative.

Checking scopes at the API boundary

Pass the access token as Authorization: Bearer <token> on any Civitai endpoint. The endpoint returns 403 insufficient_scope if the token's scope is missing the bit it requires:

json
{
  "error": "insufficient_scope",
  "error_description": "Token does not have ModelsWrite scope"
}

That's the signal to re-run the flow with a wider scope (or, more often, to display "this action needs additional permissions" in your UI).

Civitai Developer Documentation