How to Batch Update Document Permissions
Background:
This article explains how to Batch Update the permissions of multiple documents at the same time.
Imagine a scenario where you need to update the permissions of a document, e.g. you want your “Tester” role to have “Read and Write” permission level instead of “Read” for your newly created dashboard.
The process is straightforward
Select the document → Open the Info panel → Permissions section → Assign the permission to the role.
Now imagine having to do this for thousands of documents across twenty organizations, each with a Tester role. It wouldn’t be feasible to perform this process one by one, as it would require an enormous amount of manual work and time. This is where batch permission updates become useful and can be performed through the GUI or the API.
Starting with the GUI:
You can navigate to the Admin Portal → Documents → Types or Categories → enable the checkbox → select the documents → Edit Document Permissions.

The same results can be achieved through the API by using the /api/v2/common/documents/permissions/batch-update endpoint.
Request Details:
| Property | Value |
|---|---|
| Route | {server}/api/v2/common/documents/permissions/batch-update |
| Method | POST |
Request Body:
| Property | Type | Description | Example |
|---|---|---|---|
| documentIds | array<string> | Document IDs whose permissions will be changed | [“1FB74CF4-FFB0-492F-A2D5-29AA761955CF”, “DD695D78-015D-43E2-9F3A-8919F4F534FE”] |
| operationType | string | Operation type: AddNew, RemoveExisting, RemoveExistingAndAddNew | AddNew |
| grantCollection | array<object> | Permissions to grant | see JSON below |
| grantCollection[].role | string | Role name | Tester |
| grantCollection[].ops | array<string> | Allowed operations: Execute: [Execute”] Read: [“Execute”, “Read”] Write: [“Execute”, “Read”, “Update”] | [“Execute”, “Read”] |
| revokeCollection | array<object> | Permissions to revoke (effective for remove operations) | see JSON below |
| revokeCollection[].role | string | Role name | Tester |
| revokeCollection[].ops | array<string> | Operations to revoke | [“Execute”] |
JSON Body Request Example:
{
"documentIds": [
"1FB74CF4-FFB0-492F-A2D5-29AA761955CF",
"DD695D78-015D-43E2-9F3A-8919F4F534FE"
],
"operationType": "AddNew",
"grantCollection": [
{
"role": "Tester",
"ops": ["Execute", "Read"]
}
],
"revokeCollection": [
{
"role": "Tester",
"ops": ["Execute"]
}
]
}
cURL Example:
curl --location 'http://localhost:51980/api/v2/common/documents/permissions/batch-update' \
--header 'Reference-Token: <YourTokenHere>' \
--header 'Content-Type: application/json' \
--data '{
"documentIds": [
"b0d8cf89-8384-41ef-b75a-75fa1cb63ee4",
"b44e0292-bcaa-423d-9aa4-74fa685283af"
],
"operationType": "AddNew",
"grantCollection": [
{
"role":"Tester",
"ops": [
"Execute",
"Read",
"Update"
]
},
{
"role":"497584cd-a74b-4144-a01e-9c3539ff5bdf$Tester",
"ops": [
"Execute",
"Read",
"Update"
]
}
]
}'
Here is the Response Body:
[
{
"documentId": "b0d8cf89-8384-41ef-b75a-75fa1cb63ee4",
"title": "device_nameOrigin",
"fileExt": ".rdlx",
"contentType": null,
"creatorName": "admin",
"modifierName": "admin",
"deleterName": null,
"description": null,
"isSystemReserved": null,
"isResource": false,
"hideOnMobile": null,
"meta": "{\"ReportType\":\"CPL\",\"Commands\":[\"$navigation\",\"$refresh\",\"$refreshcache\",\"$history\",\"$breadcrumbs\",\"$mousemode\",\"$zoom\",\"$fullscreen\",\"$print\",\"$email\",\"$singlepagemode\",\"$continuousmode\",\"$galleymode\",\"$variants\",\"$thumbnail\",\"$search\",\"$pdf\",\"$excel\",\"$exceldata\",\"$docx\",\"$image\",\"$html\",\"$csv\",\"$json\",\"$txt\",\"$xml\"],\"RenderModeUsed\":false,\"DisplayType\":\"Page\",\"RenderedReportValues\":[]}",
"hideInDocumentPortal": null,
"organizationId": "global",
"organizationIdPath": "",
"thumbnail": null,
"schemaVersion": null
},
{
"documentId": "b44e0292-bcaa-423d-9aa4-74fa685283af",
"title": "device_nameTarget",
"fileExt": ".rdlx",
"contentType": "application/xml",
"creatorName": "admin",
"modifierName": "admin",
"deleterName": null,
"description": null,
"isSystemReserved": null,
"isResource": false,
"hideOnMobile": null,
"meta": "{\"ReportType\":\"CPL\",\"Commands\":[\"$navigation\",\"$refresh\",\"$refreshcache\",\"$history\",\"$breadcrumbs\",\"$mousemode\",\"$zoom\",\"$fullscreen\",\"$print\",\"$email\",\"$singlepagemode\",\"$continuousmode\",\"$galleymode\",\"$variants\",\"$thumbnail\",\"$search\",\"$pdf\",\"$excel\",\"$exceldata\",\"$docx\",\"$image\",\"$html\",\"$csv\",\"$json\",\"$txt\",\"$xml\"],\"RenderModeUsed\":false,\"DisplayType\":\"Page\",\"RenderedReportValues\":[]}",
"hideInDocumentPortal": null,
"organizationId": "global",
"organizationIdPath": "",
"thumbnail": null,
"schemaVersion": null
}
]
In the example above, it can be observed that the role of the first element in the grant collection is simply "Tester", while the role of the second element is 497584cd-a74b-4144-a01e-9c3539ff5bdf$Tester.
If the organization is Global, the role naming convention is RoleName. If the organization is not Global, the convention is OrganizationId$RoleName.
As a result:
- The first role represents Global/Tester.The second role represents Global/AcmeOrg/Tester, where
497584cd-a74b-4144-a01e-9c3539ff5bdfidentifies the AcmeOrg organization.
The organization IDs can be obtained from the api/v2/identity/users/me/organizations endpoint.
cURL Example
curl --location --request POST 'http://localhost:51980/api/v2/identity/users/me/organizations' \
--header 'Reference-Token: <YourTokenHere>' \
--data ''