Scopes
18 permissions, resource-dot-action. Coarse on purpose: you should be able to pick the right ones without reading a manual.
A credential carries a set of scopes chosen when it is minted. An endpoint that needs a scope the credential lacks returns 403 insufficient_scope and names the missing scope, so you never have to guess which one you forgot. Each endpoint's reference page shows the scope it needs.
Every scope#
| Scope | What it lets the holder do | Notes |
|---|---|---|
account.read | See your plan and remaining credits | Read-only preset |
projects.read | Read your projects and their edit documents | Read-only preset |
projects.write | Create, edit and delete projects | |
media.read | List the media you have uploaded | Read-only preset |
media.write | Upload media and import it from a URL | |
render.read | Check render progress and fetch preview frames | Read-only preset |
render.write | Start renders, using your monthly export allowance | Can spend |
ai.transcribe | Transcribe audio, spending your credits | Can spend |
ai.speech | Generate speech, spending your credits | Can spend |
ai.image | Generate images and stickers, spending your credits | Can spend |
ai.video | Generate video, spending your credits | Can spend |
ai.agent | Run the AI editing agent, spending your credits | Can spend |
ai.analyze | Analyse footage for scenes, faces and speech | Can spend |
stock.read | Search the stock media library | Read-only preset |
webhooks.manage | Manage webhook endpoints for this app | Never inherited |
plugins.invoke | Call third-party plugins you have installed, sending them the arguments of each call | Never inherited |
telegram.users.read | See the people using your Telegram bot and what they spent | Never inherited |
telegram.users.write | Allow, block and set daily limits for the people using your Telegram bot | Never inherited |
Can spend means the scope can cost the owner real money (credits or export allowance). Read-only preset is the default offered when you mint a key. Never inherited means keys minted before the scope existed do not carry it.
Presets#
The console offers named bundles instead of 18 checkboxes, least privileged first:
- Read only: Look at projects, media and render status. Cannot change or spend anything. (
account.read,projects.read,media.read,render.read,stock.read) - Build & render: Everything above, plus creating and editing projects, uploading media and starting renders. (
account.read,projects.read,media.read,render.read,stock.read,projects.write,media.write,render.write) - Build & render + AI: Everything above, plus transcription, generation and the editing agent. Spends credits. (
account.read,projects.read,media.read,render.read,stock.read,projects.write,media.write,render.write,ai.transcribe,ai.speech,ai.image,ai.video,ai.agent,ai.analyze)
Older keys#
A key minted before scopes existed stores no scope list, and that means the legacy full grant: it behaves exactly as it always did. That grant never includes the scopes that did not exist then and that send data somewhere or reach real people: webhooks.manage, plugins.invoke, telegram.users.read, telegram.users.write. To use those, mint a new key.
Choosing them#
Mint time is the one moment least privilege is cheap. Afterwards it means rotating a credential that is already in production, which is why the picker is the first thing on the key form.
A useful set for a render pipeline (read projects, write them, render, poll):
Note what is absent: no media.write (this pipeline points clips at URLs it already has) and no ai.* at all. If that key leaks, the worst case is somebody using your export allowance, not your credits.
The app ceiling#
Each app carries a ceiling: the most any of its keys or OAuth tokens may ever hold. New apps get the full vocabulary, so the ceiling is invisible until it is lowered, which happens for apps not verified for the expensive generation scopes. A key requesting more than its app's ceiling gets the intersection, and the ceiling is applied again on every request. Check what a credential actually ended up with:
Scopes that will never exist#
Posting to Vidmoat Social: a public feed written to by third parties is a moderation liability. Anything admin. And key management: keys never mint keys, which is enforced at the route rather than by the absence of a scope, so it cannot be undone by adding one.
webhooks.manage is reserved for a future public webhook API. Today, webhook destinations are managed in the console; see webhooks.