Skip to content

Permissions

The File Service decides, for every call made with a user token, whether that user may do that thing with that item. This page explains the model: one set of actions, granted at three levels, combined by union. It is for backend developers deciding how much to let the service enforce, for administrators, and for evaluators. Machine clients are not limited by it: see the last section.

system level the Identity Server: files.* keys mapped onto roles, per application "this role may view everything"
│ union
folder level access entries on a folder, inherited by everything inside it "this team may edit this folder"
│ union
document level access entries on one file, and the owner's rights "this user may download this file"

A right granted at any level holds. There are no deny entries: you restrict by not granting, and by breaking inheritance on a folder so that it sees only its own entries. One thing sits above the actions: inside an application-managed folder people can view, download and copy out what their actions allow, but change nothing (folder_managed).

Action On a file On a folder
view See it in listings and search, read its metadata, open previews (renditions, inline images, video, audio, PDF, text) See the folder and list its children (each child still needs view)
download Mint download URLs of the original, download through a share link Nothing by itself; inherited by the children
edit Upload a new version, rename, move, change metadata and tags, change the status (except approval decisions), restore a version, regenerate renditions Create folders and files in it, rename and move it
share Create share links; grant entries to others, limited to the actions the granter holds; set the visibility The same on the folder
delete Move to the trash and restore; purge with files.manage, or as the owner when the application allows it The same, for the whole subtree
approve Set approved or rejected, reopen an approved file. A file in review is read-only for edit holders without approve Inherited by the children

view is implied by every other action: whoever may download a file may see it. Nothing else implies anything.

The system level is a set of permission keys that the tenant owner maps onto roles for each application, on the console’s Permissions page. They are stored at the Identity Server with your roles.

Key Grants Group
files.view view on everything in the application content
files.download download on everything content
files.edit edit on everything content
files.share share on everything content
files.delete delete on everything content
files.approve approve on everything content
files.manage All six actions on everything, plus: edit any access entry, break and restore inheritance anywhere, purge, reassign owners. Full content access in one key content
files.configure Both administration keys below, in one key administration
files.settings.manage Read and change the application’s settings: quota, types, sizes, retention, visibility, owner rights, taxonomies administration
files.audit.read Read the audit log and the usage of the application administration
files.permissions.manage See and change what every role may do in this application (every key but this one). Granted and withdrawn by the tenant owner only delegation

The tenant owner holds every key in every application, always. A social app might map files.view and files.download onto member and nothing else, keeping every write in its backend; a document library might map files.manage onto librarian. Either is one row in the matrix.

GET P/me/capabilities answers the caller’s keys, expanded: files.manage shows as the six action keys and files.manage, files.configure as the two administration keys.

Folder and document levels are access entries on an item:

{ "principal": { "type": "role", "role_id": "editor-role-id" }, "actions": ["view", "download", "edit"], "expires_at": "2026-12-31T00:00:00.000Z" }
Principal Matches
{ "type": "user", "user_id": "…" } That user
{ "type": "role", "role_id": "…" } Everyone with that tenant role, or that role of this application. Not tenant_owner
{ "type": "application" } Everyone who has access to the application

An item carries up to 200 entries of its own (too_many_entries). An entry may expire; an expired entry no longer counts. GET P/principals/roles lists the roles that may appear in an entry, GET P/principals/users searches the tenant’s members.

Route Does
GET P/files/:file_id/permissions, GET P/folders/:folder_id/permissions The item’s own and inherited entries (inherited_from names the folder) and the effective list. Everything with share, otherwise the caller’s own entries only
POST P/files/:file_id/permissions/entries, POST P/folders/:folder_id/permissions/entries Add one entry
DELETE P/files/:file_id/permissions/entries/:entry_id, DELETE P/folders/:folder_id/permissions/entries/:entry_id Remove one of the item’s own entries
PUT P/files/:file_id/permissions, PUT P/folders/:folder_id/permissions Replace the item’s entries and set inherit
GET P/files/:file_id/me/permissions What the caller may do with a file, with via

Granting. Whoever holds share on an item may add entries whose actions they hold on it themselves; anything more answers cannot_grant_more_than_held. files.manage may grant anything. Entry changes are rate limited to 30 per minute per user.

Every item has an owner_id: the uploader, or the user your backend named. The owner holds the application’s owner_actions on their own items whatever the entries say: by default view, download, edit, share and delete, never approve unless the application adds it. A tenant whose backend should be the only writer sets owner_actions to view, download.

An item with inherit: true (the default) has its own entries plus its parent’s effective entries, up to the root. A folder with inherit: false starts a new scope: it and everything inside it see only the entries from that folder down. The owner and the holders of system-level keys still see it.

  • Breaking inheritance: replace the folder’s permissions with { inherit: false, copy_inherited: true }. The entries it inherited are copied into its own list, so nothing changes for anyone until you remove one. With copy_inherited: false it starts empty.
  • Restoring inheritance: { inherit: true } clears the folder’s own list, unless keep_own: true.
  • An entry on a folder costs nothing per descendant: adding one to a folder of a million files is one write.

How a user’s right to do action a on item i comes about:

Source Holds when
System level A role of the user carries files.<a> (or files.manage) in this application, or the user is the tenant owner
Owner i.owner_id is the user and a is in the application’s owner_actions
Visibility i is application or public and a is view or download
Entries An entry on i, or on a folder i inherits from, matches the user and names a
Implied view a is view and any of the above gives the user another action on i

Listings and search apply the same rule inside the query, so paging and counts are exact: a user without files.view sees in a folder the children they may view, and searches only the folders they may view (up to 5,000 folder scopes; beyond that search answers too_many_scopes and asks for a folder filter).

Answer Means
403 missing_action The caller may view the item but lacks the action
404 file_not_found, folder_not_found The caller may not view it (or it does not exist: the service never says which)
403 missing_capability A system-level key is needed: settings, audit, the role matrix
403 partial_permission A subtree operation is blocked by some descendants; blocked lists them
403 folder_managed The item is in an application-managed folder: people cannot change it, whatever their actions; managed_folder_id names the folder

A backend client with files:manage holds every action on every item of its context, and the entries never limit it; files:read holds view and download. Your backend is trusted to apply its own rules before it calls. When it acts for a user and wants the service’s answer for that user, it asks: GET P/files/:file_id/effective-permissions?user_id= answers { actions, via }, with via such as system:files.view, owner, visibility:application or role:editor@folder:01J9…. See Permissions from code.