Scopes¶
The full scope catalog, semantics, namespace rules, and the lifecycle of scope changes.
Catalog¶
| Scope | Token type | Description | What it unlocks |
|---|---|---|---|
event.read |
installation | Read event metadata (title, dates, description, status) | GET /events/{id} |
participants.read |
installation | Read participants and their event-scoped profiles (including custom form responses, role, application status) | GET /events/{id}/participants |
program.read |
installation | Read event program (threads, activities, locations, registration waves) | GET /events/{id}/program, /activities, /threads, /locations, /registration-waves |
profile.read |
user | Read the signed-in user's profile (name, email) | GET /me/profile |
event.attendance |
user | Confirmation that you attend the event the token is bound to | GET /me/application |
Single namespace, two token types¶
Scopes share one namespace. The Token type column tells you which token type can request a given scope:
installationscopes → only available via the organizer-connect flow.userscopes → only available via Login with Revento.
Mixing — requesting participants.read (installation) on a Login-with-Revento authorization request — returns invalid_scope. Requesting profile.read (user) on an organizer-connect authorization request — same error.
There's no installation.event.read vs user.event.attendance namespace prefix. Scope names are global; the discriminator is implicit in the flow you use.
Declared vs requested vs granted¶
Three layers, each filtering the next:
flowchart LR
A[Manifest declares<br/>scopes you'll EVER request] --> B[Authorization request<br/>asks for SUBSET]
B --> C[Consent screen shows<br/>required + optional scopes]
C --> D[User grants SUBSET<br/>required ones all-or-nothing]
D --> E[Token carries<br/>granted scopes]
E --> F[API enforces<br/>per-endpoint scope]
Manifest¶
When you register your integration, you declare every scope you'll ever request, ever. This is your manifest. Adding a scope later requires re-consent from every existing connection (see below).
Authorization request¶
On each /oauth/authorize request you list the scopes you're requesting for this connection. This must be a subset of your manifest. Requesting a scope you didn't declare returns invalid_scope: scope not declared in integration manifest.
You can request fewer scopes than your manifest if you want to be conservative — e.g. your manifest has program.read but a particular connection doesn't need it.
Consent screen¶
The consent screen shows two groups:
- Required scopes — your integration declared these as required. The organizer can either grant all of them or cancel.
- Optional scopes — your integration declared these as optional. Each has a checkbox, default-checked.
In your manifest you declare which scopes are required and which are optional, per scope. The same scope name can be required by one integration and optional by another.
Granted¶
The token's scope claim reflects what the user actually granted, which may be fewer than what you requested if optional scopes were declined.
{
"access_token": "rev_install_...",
"scope": "event.read participants.read", // program.read was optional and was declined
...
}
Always check the granted scopes before assuming you can call an endpoint. Don't hard-code "we have program.read" — read the response and adapt.
Scope minimization¶
Two reasons to request fewer scopes:
- Easier consent. Organizers more readily grant 2 scopes than 5. Sharper consent screens convert better.
- Smaller blast radius. A leaked token with fewer scopes leaks less data.
Practical guidance:
- Don't request
participants.readif you only need event metadata. Useevent.readalone. - Mark scopes as optional whenever your integration can degrade gracefully without them. E.g.
program.readoptional with a fallback "program sync disabled — grant program.read to enable."
Re-consent on new scopes¶
If you ship a new version of your integration that declares a scope an existing connection doesn't have:
- The connection enters "re-consent required" state.
- Existing tokens continue working with the previous scope set.
- The new scope is unavailable until the organizer re-consents.
- The organizer sees a banner in their integrations panel asking them to grant the new permissions.
- Tapping "Accept new permissions" runs them through the OAuth flow again with the updated scope set.
New scopes always require explicit re-consent.
For renaming or splitting existing scopes: treated identically to net-new scopes. Re-consent required.
What does NOT require re-consent:
- Adding new endpoints that use existing already-granted scopes.
- Changing your integration's branding, name, or description.
- Bumping minor versions where the manifest is unchanged.
What about removing scopes?¶
Removing a scope from your manifest is fine — existing tokens keep their old scopes (we don't take scopes away from existing connections), but new authorizations don't request the removed scope. After all old tokens age out (1 year max), the scope is fully gone.
To actively revoke a scope from existing connections, call the OAuth revocation endpoint per token, then surface a "reconnect" CTA in your UI. Most integrations never need this.
On the consent screen, in the user's language¶
The consent screen renders in the organizer's (or participant's) preferred locale, currently pl or en. Revento maintains both translations for the canonical scope catalog — you don't need to translate anything.
Custom scopes are not supported. The catalog is fixed.