Permissions reference
Every action in Tether is protected by a permission key. Roles set default permissions. Per-user overrides let you grant or revoke individual permissions on top of the role.
How permissions work
The effective permission set for a user is calculated as follows:
- Start with all permissions granted by the user's role
- Apply any individual overrides — Grant adds a permission the role doesn't include; Revoke removes a permission the role would otherwise provide
- The resulting set is checked server-side on every API request
This means you can give a client_viewer the ability to check assets out by
granting assets.checkout, or prevent a client_admin from
deleting assets by revoking assets.delete — without creating any new roles.
The frontend uses permissions to show or hide UI elements, but every API endpoint independently validates the caller's permissions. It is not possible to bypass permissions by calling the API directly — the check happens in the backend regardless of how the request arrives.
All permission keys
| Permission key | What it controls | Affected endpoints |
|---|---|---|
assets.view | View the asset list and individual asset detail pages | GET /api/assets, GET /api/assets/{id} |
assets.create | Create new asset records | POST /api/assets |
assets.edit | Edit existing asset fields (name, serial, cost, etc.) | PUT /api/assets/{id} |
assets.delete | Delete asset records permanently | DELETE /api/assets/{id} |
assets.checkout | Check an asset out to a person | POST /api/assets/{id}/checkout |
assets.checkin | Check an asset back in | POST /api/assets/{id}/checkin |
assets.import | Import assets via CSV upload | POST /api/assets/import/csv |
assets.export | Export assets to a CSV file | GET /api/assets/export/csv |
categories.manage | Create, rename, and delete asset categories | /api/categories |
locations.manage | Create, rename, and delete locations | /api/locations |
employees.manage | Create, edit, and delete people (employees assets are assigned to) | /api/employees |
users.manage | Create, edit, deactivate, and delete user accounts within the tenant | /api/users |
reports.view | View reports and summary statistics | Dashboard stats endpoints |
settings.manage | Edit tenant settings: name, logo, currency, accent colour | PUT /api/settings |
tenants.manage | Create, edit, and delete client tenants — MSP only | /api/tenants |
msp.dashboard | Access the cross-client MSP dashboard and stats | GET /api/dashboard/msp |
msp.impersonate | Access any client tenant as MSP staff | Host-header-based tenant scoping |
Role default permissions
| Permission | msp_admin | msp_technician | client_admin | client_manager | client_viewer |
|---|---|---|---|---|---|
| assets.view | Yes | Yes | Yes | Yes | Yes |
| assets.create | Yes | Yes | Yes | Yes | No |
| assets.edit | Yes | Yes | Yes | Yes | No |
| assets.delete | Yes | Yes | Yes | No | No |
| assets.checkout | Yes | Yes | Yes | Yes | No |
| assets.checkin | Yes | Yes | Yes | Yes | No |
| assets.import | Yes | Yes | Yes | Yes | No |
| assets.export | Yes | Yes | Yes | Yes | Yes |
| categories.manage | Yes | Yes | Yes | Yes | No |
| locations.manage | Yes | Yes | Yes | Yes | No |
| employees.manage | Yes | Yes | Yes | Yes | No |
| users.manage | Yes | No | Yes | No | No |
| reports.view | Yes | Yes | Yes | Yes | Yes |
| settings.manage | Yes | No | Yes | No | No |
| tenants.manage | Yes | No | No | No | No |
| msp.dashboard | Yes | Yes | No | No | No |
| msp.impersonate | Yes | Yes | No | No | No |
Editing permission overrides
- Go to Users (MSP-level or client-level)
- Find the user and click the lock icon (Perms)
- The permission editor shows each permission key with three columns:
- Role default — whether the role includes this permission
- Override — three options: Grant (always on), Revoke (always off), Default (follow the role)
- Effective — the final result after applying the override
- Set overrides as needed and click Save Permissions
When you set an override, it changes only that one permission — all other permissions remain as the role specifies. You do not need to re-specify all permissions when adding an override.
Checking permissions via API
The /api/auth/me endpoint returns the currently authenticated user's complete permission list:
httpGET /api/auth/me Authorization: Bearer {token} # Response includes: {{ "permissions": ["assets.view", "assets.create", "assets.edit", ...] }}