Scopes and Permissions
Every API key carries a set of scopes that decide which actions it may perform. A key with no scopes set has full access; a scoped key is limited to the actions you grant it, so you can hand an agent or a deployed app a least-privilege credential instead of a full-access one.
Scopes are enforced on the redu.cloud API. A request that a key is not scoped for is rejected before it reaches your infrastructure.
Scope grammar
A scope is one of the following tokens. A key may combine several; access is granted if any of its scopes matches the requested action.
| Token | Grants |
|---|---|
* | Full access (every action). This is the default when no scopes are set. |
read | Every read (GET) action, on all resources. |
write | Every write (POST, PUT, PATCH) action, on all resources. |
delete | Every delete (DELETE) action, on all resources. |
<resource>:* | Every action on one resource, for example instance:*. |
<resource>:<action> | One specific action, for example backup:create. |
<resource>:<verb> | Shorthand for all same-verb actions on a resource, for example instance:read. |
Resource names are singular (instance, volume, managed_postgres).
Discover the full catalog
The complete, always-current list of resources and actions is served at:
curl https://api.redu.cloud/v1/capabilitiesThe response lists every resource with its actions, the scope grammar, and the scopes your current key holds:
{
"auth": {
"granted_scopes": ["backup:create", "backup:restore", "instance:read"],
"scope_model": {
"grammar": "\"*\" | \"read\" | \"write\" | \"delete\" | \"<resource>:*\" | \"<resource>:<action>\"",
"method_verbs": { "GET": "read", "POST": "write", "PUT": "write", "PATCH": "write", "DELETE": "delete" }
}
},
"resources": [
{ "type": "backup", "actions": ["create", "delete", "list", "restore"] },
{ "type": "instance", "actions": ["create", "delete", "list", "action", "console-log"] }
]
}Because both the enforcement and this catalog are generated from the same source, what /v1/capabilities lists is exactly what is enforced.
Common resources
A representative subset. Use /v1/capabilities for the authoritative list.
| Resource | Example actions |
|---|---|
instance | list, create, action, delete, console-log |
volume | list, create, get, attach, detach, delete |
snapshot | list, create, delete |
backup | list, create, restore, delete |
security_group | list, create, update, add-rule, remove-rule, delete |
private_network | list, create, delete |
dns | list, create, update, delete |
deployment | list, create, create-compose, get, delete |
managed_postgres | list, create, get, delete |
managed_redis | list, create, get, delete |
api_key | list, create, delete |
Least-privilege examples
A backup automation key. Read instances, and create or restore backups, nothing else:
{
"name": "nightly-backups",
"scopes": ["instance:read", "backup:read", "backup:create", "backup:restore"]
}A read-only monitoring key. See everything, change nothing:
{
"name": "monitoring",
"scopes": ["read"]
}A deploy key for one app. Manage deployments and their managed database:
{
"name": "ci-deploy",
"scopes": ["deployment:*", "managed_postgres:*"]
}Omit scopes entirely to create a full-access key (["*"]).
Creating API keys is itself a scope
Minting a new API key requires the api_key:create scope (or a full-access key). A scoped automation key that lacks it cannot create more keys, and a key can never grant scopes broader than its own creator’s. This keeps a leaked automation key from escalating itself to full access.
Create keys from a Console session, or from a key you have deliberately granted api_key:create.
Denied requests
When a key lacks the scope for an action, the API returns 403 with a stable insufficient_scope code:
{
"error": {
"code": "insufficient_scope",
"message": "This API key lacks the 'instance:delete' scope required for this request.",
"required_scope": "instance:delete",
"granted_scopes": ["backup:create", "backup:restore", "instance:read"]
}
}This is distinct from 401, which means the key is missing, malformed, expired, or invalid. See Authentication for the 401 cases.
Existing keys keep working
Keys created before scopes existed, and keys created with the coarse read / write / delete presets, behave exactly as before. Granular resource:action scopes are opt-in, chosen when you create a key.