Team and Security
Roles and permissions
Every action needs a permission key. Roles are lists of keys; the five presets, what each one can do, and how roles apply on every surface.
A role decides what a member can do in your account. Behind every button, API route, MCP tool, CLI command and AI agent tool there is one permission key, written module.action (for example documents.void). A role is simply a named list of those keys. Each account starts with five roles: Owner, Admin, Editor, Viewer and Accountant.
How permissions work
- No action without a key. Every capability declares the key it needs. There are 48 keys across every module, from
businesses.viewtoaccount.delete. The full catalogue is on Permission keys. - Checked everywhere, the same way. The check runs in the API, so the web app, REST API, MCP server, CLI, store connectors and the AI agent all refuse the same things. The web app also hides what your role cannot do.
- Read on every request. Permissions are loaded per request, not stored in your session. When a role changes, the next request already uses the new keys.
- Business scope on top. Each member also has a business scope (all businesses, or a list). The role says what they can do; the scope says where. The Owner always reaches every business.
- Keys and tokens follow their creator. An API key or MCP token carries scopes from the same list, but at call time it can only do what both its scopes and its creator's current permissions allow. If the creator loses a key, or leaves the account, their API keys and MCP tokens lose it on the next request.
The five presets
| Role | Meant for | In short |
|---|---|---|
| Owner | The person who owns the account | Every permission. Fixed: cannot be edited or deleted. The only role that can delete the account, export everything, manage billing by default, or transfer ownership. |
| Admin | A partner or office manager | Everything except billing, account export and account deletion. Can manage the team and roles. |
| Editor | Someone who does the day-to-day invoicing | Creates, edits and sends documents, records payments, manages saved items, templates and reminders. Cannot void, credit, refund or change settings. |
| Viewer | Someone who only needs to look | Read-only across documents, clients, payments, contracts, time, expenses and reports. |
| Accountant | Your bookkeeper or accountant | Read-only finance access plus report exports and the ledger view. This is the one extra seat on the Free plan. |
Default permission matrix
This table is the default set of keys each preset gets when your account is created, and what Reset to default restores. On Team, every role except Owner can be edited, so the roles in your account may differ from this table. The roles in Settings > Team > Roles are always the source of truth.
| Key | Owner | Admin | Editor | Viewer | Accountant |
|---|---|---|---|---|---|
businesses.view | Y | Y | Y | Y | Y |
businesses.manage | Y | Y | - | - | - |
documents.view | Y | Y | Y | Y | Y |
documents.create | Y | Y | Y | - | - |
documents.edit | Y | Y | Y | - | - |
documents.send | Y | Y | Y | - | - |
documents.void | Y | Y | - | - | - |
documents.credit | Y | Y | - | - | - |
clients.view | Y | Y | Y | Y | Y |
clients.create / clients.edit | Y | Y | Y | - | - |
clients.delete | Y | Y | - | - | - |
items.view | Y | Y | Y | Y | Y |
items.manage | Y | Y | Y | - | - |
payments.view | Y | Y | Y | Y | Y |
payments.record | Y | Y | Y | - | - |
payments.refund | Y | Y | - | - | - |
payments.auto_charge | Y | Y | - | - | - |
rails.manage | Y | Y | - | - | - |
senders.manage | Y | Y | - | - | - |
templates.manage | Y | Y | Y | - | - |
reminders.manage | Y | Y | Y | - | - |
late_fees.manage | Y | Y | - | - | - |
late_fees.waive | Y | Y | Y | - | - |
contracts.view | Y | Y | Y | Y | Y |
contracts.manage | Y | Y | Y | - | - |
contracts.sign | Y | Y | - | - | - |
time.view | Y | Y | Y | Y | Y |
time.log | Y | Y | Y | - | - |
time.manage | Y | Y | - | - | - |
expenses.view | Y | Y | Y | Y | Y |
expenses.manage | Y | Y | Y | - | - |
reports.view | Y | Y | Y | Y | Y |
reports.export | Y | Y | Y | - | Y |
accounting.manage | Y | Y | - | - | - |
ledger.view | Y | Y | - | - | Y |
ledger.journal | Y | Y | - | - | - |
ledger.manage | Y | Y | - | - | - |
ai.use | Y | Y | Y | - | - |
ai.manage | Y | Y | - | - | - |
settings.view | Y | Y | Y | Y | Y |
settings.manage | Y | Y | - | - | - |
team.manage | Y | Y | - | - | - |
integrations.manage | Y | Y | - | - | - |
audit.view | Y | Y | - | - | - |
billing.manage | Y | - | - | - | - |
account.export | Y | - | - | - | - |
account.delete | Y | - | - | - | - |
Business scope (all businesses or a list) applies on top of the role for every role except Owner.
Transferring ownership is not a key in this table. It is checked against the Owner role itself, so it can never be ticked on another role. See Transfer ownership.
The Owner role is fixed
- The Owner holds every permission key.
- The Owner role cannot be edited, reset or deleted (
role_locked). - An account always has at least one Owner (
last_owner). account.deleteand ownership transfer are Owner-only. They cannot be ticked on any other role (permission_not_grantable).account.exportis also Owner-only by default.- The Owner can never be deactivated or removed.
Nobody can grant what they do not have
Only a member whose role holds team.manage can create, edit, delete or reset roles, and even then they cannot tick a key they do not hold themselves. An Admin, for example, does not hold billing.manage by default, so an Admin cannot give billing.manage to any role, including their own. The same check stops a member from changing the role they are on in a way that adds keys. Refused changes return permission_not_grantable and nothing is saved.
Plan differences
| Free | Team | |
|---|---|---|
| Roles in the account | Owner and one view-only Accountant, both fixed | Owner (fixed) plus Admin, Editor, Viewer, Accountant and any custom roles |
| Edit a preset (tick or untick keys) | - | Yes, every role except Owner |
| Reset a preset to default | - | Yes |
| Create custom roles | - | Yes, from scratch or by duplicating a role. See Custom roles. |
| Delete a role | - | Yes, except Owner, once no members are on it |
On Free, Settings > Team > Roles shows the Owner and the Accountant as fixed, and role editing as a locked Team feature. Calls to the role capabilities return feature_locked.
If a Team account goes back to Free (for example after a failed renewal), custom and edited roles are kept but inactive, and every member except the Owner is deactivated. On re-upgrade, the roles come back as they were.
Edit a preset role
Open Settings > Team > Roles
You need team.manage and a Team plan.
Choose a role
Admin, Editor, Viewer, Accountant or a custom role. The Owner role is shown but cannot be opened for editing.
Tick or untick permission keys
Keys you do not hold yourself cannot be ticked.
Save
The change applies to every member on that role from their next request, and an audit entry records the old and new key lists.
To undo your edits on a preset, choose Reset to default. Its keys go back to the defaults in the matrix above, and the reset is audited.
Through the API
curl "https://api.freeinvoiceautomation.com/v1/roles" \
-H "Authorization: Bearer $FIA_API_KEY"{
"data": {
"id": "0193f2a1-4d2e-7a10-8b3c-5e6f7a8b9c02",
"name": "Editor",
"preset_key": "editor",
"is_owner": false,
"is_active": true,
"permissions": ["businesses.view", "documents.view", "documents.create", "..."]
}
}preset_key is owner, admin, editor, viewer or accountant for presets, and null for custom roles.
| Capability | Route | Permission |
|---|---|---|
| List roles | GET /v1/roles | team.manage |
| Create a role | POST /v1/roles | team.manage (Team) |
| Update a role | PATCH /v1/roles/{id} | team.manage (Team) |
| Delete a role | DELETE /v1/roles/{id} | team.manage (Team) |
| Reset a role | POST /v1/roles/{id}/reset | team.manage (Team, presets only) |
Errors
| Code | HTTP | When |
|---|---|---|
permission_denied | 403 | Your role lacks the key the action needs, for example team.manage. |
scope_missing | 403 | The API key or MCP token lacks the scope. |
feature_locked | 403 | Role editing or custom roles on the Free plan. |
permission_not_grantable | 403 | The change would grant a key you do not hold, or an Owner-only key to another role. |
role_locked | 409 | Someone tried to edit, reset or delete the Owner role. |
role_in_use | 409 | The role still has members. Move them first. |
last_owner | 409 | The change would leave the account without an Owner. |