API key scopes
An API key can exist in two ways: as a global key owned by the tenant, or as a user-bound key owned by a specific person. The difference decides what happens when that person leaves the company.
#The difference in one paragraph
A global key carries exactly the scopes selected when it was created — permanently. A user-bound key carries the intersection of its scopes and its owner's current permissions, re-evaluated on every request. It can therefore never grant more than the person is allowed right now.
#Why there are two kinds
Originally every key was tenant-wide. That fits monitoring agents and CI jobs. For keys representing a person's automation it creates two well-known problems:
- Ghost permissions — someone leaves the company, the account is deactivated. The personal API key keeps working until someone revokes it by hand. That revocation is exactly what gets missed during offboarding
- Stale snapshots — a key was created with write access. Months later the person was moved back to read-only — the key still writes
User-bound keys solve both, because they evaluate permissions live rather than freezing them.
#How the intersection is formed
On every request Uslimato checks, in this order:
- Is the owner's account active? If not, the request ends here
- Which permissions does that person currently hold?
- Those permissions are mapped to API scopes
- The effective scope is the intersection of the key's scopes and the person's resolved scopes
If the required scope is missing from the intersection, the API answers 403 INSUFFICIENT_SCOPE.
#Mapping permissions to scopes
| Permission | Yields the API scopes |
|---|---|
admin | All scopes |
assets:write | assets:read, assets:write |
assets:use | assets:read |
users:manage | users:read, users:write |
processes:manage | processes:read, processes:write |
processes:use | processes:read |
tickets:manage, tickets:admin | tickets:read, tickets:write |
tickets:create, tickets:close | tickets:read |
#How quickly changes take effect
Permissions are cached for up to 60 seconds. When a group membership or a group permission changes, the cache is refreshed immediately — the withdrawal then applies on the next request.
#Who may create which key
The scope type has no default — it always has to be chosen explicitly on creation.
| Who creates it | Type | For whom | Result |
|---|---|---|---|
| Anyone | *not specified* | — | 400 SCOPE_REQUIRED |
| Administration | global | — | Created |
| Administration | global | a person | 400 VALIDATION_ERROR |
| Without admin rights | global | — | 403 GLOBAL_KEY_ADMIN_ONLY |
| Administration | user-bound | member of the tenant | Created |
| Administration | user-bound | person in another tenant | 400 INVALID_USER |
| Without admin rights | user-bound | themselves | Created |
| Without admin rights | user-bound | someone else | 403 FORBIDDEN |
Whether people without admin rights may create their own keys at all is controlled by a per-tenant setting — see Admin mode.
#What happens to a key
| Event | Effect on a user-bound key |
|---|---|
| Person removed from a group | Effective scope shrinks within 60 seconds |
| Account deactivated | The next request is refused |
| Account deleted | The key is removed automatically |
| Key explicitly revoked | The key is deactivated immediately |
#Which type when
Global, when the key represents a service rather than a person — CI, backups, monitoring — when it should keep running even after someone leaves, or when the integration deliberately needs broad, role-independent access.
User-bound, when the key is a person's automation, when it should follow their role changes automatically, or when offboarding should take care of the key without an extra step.