Perform Bulk Operations
Use the Permit API bulk endpoints to sync many users, tenants, resource instances, role assignments, relationship tuples, or roles in one request. This reference is for developers who sync application data into Permit, for example during an initial user import or a policy graph update. It lists each bulk endpoint, its item limit, and a sample request.
The samples on this page are plain HTTP requests. The Permit SDKs wrap many of the bulk endpoints. See SDK feature parity for the operations each SDK supports. To request a missing SDK operation, ask in the Permit Slack community.
Before you call a bulk endpoint
Every sample on this page uses these placeholders. Replace them before you run a request:
| Placeholder | Replace with |
|---|---|
{proj_id} | Your project ID or key. See Get the project ID and environment ID. |
{env_id} | Your environment ID or key. |
{your_permit_token} | A Permit API key with access to the environment. See Get your API key. |
... | More items of the same shape. Remove ... from the JSON body before you send the request. |
Bulk limits
Each bulk call accepts a limited number of items. The following limits apply per call:
| Bulk call | Maximum items per call |
|---|---|
| Users | 3,000 |
| Tenants | 2,000 |
| Resource instances | 3,000 |
| Role assignments | 2,000 |
| Roles | 2,000 |
| Relationship tuples | 1,000 |
If a request contains more items than the limit, the Permit API rejects the whole request with HTTP 403 and the message Number of requested operations (<count>) exceeds maximum allowed (<limit>). A request with no items returns HTTP 400. Split large data sets into several requests.
Bulk calls also count toward the Permit API rate limits. Bulk endpoints are not designed for full or large-volume data migrations. Before a large-scale migration, contact Permit support at support@permit.io.
Bulk operations glossary
Each bulk endpoint replaces many calls to a single-item endpoint:
| Single-item operation | Bulk operation | Bulk endpoint |
|---|---|---|
| Create User | Bulk Create Users | POST /v2/facts/{proj_id}/{env_id}/bulk/users |
| Replace User | Bulk Replace Users | PUT /v2/facts/{proj_id}/{env_id}/bulk/users |
| Delete User | Bulk Delete Users | DELETE /v2/facts/{proj_id}/{env_id}/bulk/users |
| Create Tenant | Bulk Create Tenants | POST /v2/facts/{proj_id}/{env_id}/bulk/tenants |
| Delete Tenant | Bulk Delete Tenants | DELETE /v2/facts/{proj_id}/{env_id}/bulk/tenants |
| Create Resource Instance | Bulk Replace Resource Instances | PUT /v2/facts/{proj_id}/{env_id}/bulk/resource_instances |
| Delete Resource Instance | Bulk Delete Resource Instances | DELETE /v2/facts/{proj_id}/{env_id}/bulk/resource_instances |
| Assign Role | Bulk Assign Roles | POST /v2/facts/{proj_id}/{env_id}/role_assignments/bulk |
| Unassign Role | Bulk Unassign Roles | DELETE /v2/facts/{proj_id}/{env_id}/role_assignments/bulk |
| Create Relationship Tuple | Bulk Create Relationship Tuples | POST /v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk |
| Delete Relationship Tuple | Bulk Delete Relationship Tuples | DELETE /v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk |
| Create Role | Bulk Create or Replace Roles | PUT /v2/schema/{proj_id}/{env_id}/bulk/roles |
Bulk user operations
Permit handles authorization, not identity management, so your user data usually lives in an identity provider or your application database and is synced into Permit. Use the bulk user endpoints for the initial user sync or to update many users at once. For a walkthrough of syncing one user, see Sync your first user.
| Operation | Method and path | Body |
|---|---|---|
| Create users | POST /v2/facts/{proj_id}/{env_id}/bulk/users | operations: a list of users. Each user requires key, and accepts email, first_name, last_name, attributes, and role_assignments. |
| Replace users | PUT /v2/facts/{proj_id}/{env_id}/bulk/users | operations: a list of users with the same fields as create. |
| Delete users | DELETE /v2/facts/{proj_id}/{env_id}/bulk/users | idents: a list of user keys. |
The following sample creates, replaces, and deletes users:
# Create new users
curl -X POST https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/users \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [{
"key": "jane_doe",
"email": "jane@coolcompany.com",
"first_name": "Jane",
"last_name": "Doe",
"attributes": {}
}, ...]
}'
# Update existing users
curl -X PUT https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/users \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [{
"key": "jane_doe",
"email": "test@permit.io",
"first_name": "Jane",
"last_name": "Doe",
"attributes": {}
}, ...]
}'
# Delete existing users
curl -X DELETE https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/users \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"idents": ["jane_doe", ...]
}'
A successful request returns HTTP 200. To confirm the result, open the Directory screen in the Permit dashboard and check that the users appear, or list users with the List Users API.
Bulk tenant operations
Tenants group users in the same way your application groups users under customer accounts (account -> user). When you sync users in bulk, you usually sync their tenants in bulk too.
| Operation | Method and path | Body |
|---|---|---|
| Create tenants | POST /v2/facts/{proj_id}/{env_id}/bulk/tenants | operations: a list of tenants. Each tenant requires key and name, and accepts description and attributes. |
| Delete tenants | DELETE /v2/facts/{proj_id}/{env_id}/bulk/tenants | idents: a list of tenant keys. |
The following sample creates and deletes tenants:
# Create new tenants
curl -X POST https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/tenants \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [{
"key": "cool_company",
"name": "Cool Company",
"attributes": {}
}, ...]
}'
# Delete existing tenants
curl -X DELETE https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/tenants \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"idents": ["stripeince", ...]
}'
Bulk role assignment
After you sync users, you assign them roles. Bulk role assignment also fits two other cases:
- You add a role to your policy and assign the role to many existing users.
- You update the resource roles of many users to keep relationship-based access control (ReBAC) relationships in sync.
| Operation | Method and path | Body |
|---|---|---|
| Assign roles | POST /v2/facts/{proj_id}/{env_id}/role_assignments/bulk | A JSON list of role assignments. Each assignment requires user and role, and accepts tenant and resource_instance. |
| Unassign roles | DELETE /v2/facts/{proj_id}/{env_id}/role_assignments/bulk | A JSON list of role assignments to remove. Each assignment requires user, role, and tenant, and accepts resource_instance. |
The response to a bulk assign request contains assignments_created, the number of role assignments created. The response to a bulk unassign request contains assignments_removed.
The following sample assigns and unassigns roles:
curl -X POST https://api.permit.io/v2/facts/{proj_id}/{env_id}/role_assignments/bulk \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '[{
"user": "892179821739812389327",
"role": "admin",
"tenant": "default"
}, ...]'
curl -X DELETE https://api.permit.io/v2/facts/{proj_id}/{env_id}/role_assignments/bulk \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '[{
"user": "892179821739812389327",
"role": "owner:892179821739812389327",
"tenant": "stripeince"
}, ...]'
Bulk resource operations
A ReBAC policy evaluates resource instances, so the resource instances in Permit must match the resources in your application. Use the single-item resource instance endpoints for event-driven updates. Use the bulk resource instance endpoints when you sync many resource instances at once.
| Operation | Method and path | Body |
|---|---|---|
| Create or replace resource instances | PUT /v2/facts/{proj_id}/{env_id}/bulk/resource_instances | operations: a list of resource instances. Each instance requires key, resource, and tenant, and accepts attributes. An instance with the same key and resource as an existing instance replaces the existing instance. |
| Delete resource instances | DELETE /v2/facts/{proj_id}/{env_id}/bulk/resource_instances | idents: a list of resource instance identifiers in resource:key format, for example repository:react. |
The following sample replaces and deletes resource instances:
# Update existing resource instances
curl -X PUT https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/resource_instances \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [{
"key": "react",
"resource": "repository",
"tenant": "default",
"attributes": {}
}, ...]
}'
# Delete existing resource instances
curl -X DELETE https://api.permit.io/v2/facts/{proj_id}/{env_id}/bulk/resource_instances \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"idents": ["repository:react", ...]
}'
Bulk relationship operations
Relationship tuples connect resource instances in a ReBAC policy graph, for example organization:permitio is the owner of repo:opal. Create or delete one relationship tuple at a time for event-driven updates. Use the bulk relationship tuple endpoints when you change many relationships at once.
| Operation | Method and path | Body |
|---|---|---|
| Create relationship tuples | POST /v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk | operations: a list of tuples. Each tuple requires subject, relation, and object, and accepts tenant. |
| Delete relationship tuples | DELETE /v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk | idents: a list of tuples, each with subject, relation, and object. |
The following sample creates and deletes relationship tuples:
# Create new relationships
curl -X POST https://api.permit.io/v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [{
"subject": "organization:permitio",
"relation": "owner",
"object": "repo:opal",
"tenant": "public"
}, ...]
}'
# Delete an existing relationships
curl -X DELETE https://api.permit.io/v2/facts/{proj_id}/{env_id}/relationship_tuples/bulk \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"idents": [{
"subject": "organization:permitio",
"relation": "owner",
"object": "repo:removed_repo"
}, ...]
}'
Bulk role operations
Create or replace roles in bulk
PUT /v2/schema/{proj_id}/{env_id}/bulk/roles creates or replaces many roles in one request. One request can contain both top-level role-based access control (RBAC) roles and ReBAC resource roles for several resources:
- Each role requires
keyandname, and acceptspermissions,attributes, andextends. - Add the optional
resourcefield to create a resource role for that resource. A role withoutresourceis a top-level RBAC role. - If a role with the same key exists, the request replaces the existing role.
The response lists the roles the request created in created and the roles it replaced in updated.
curl -X PUT https://api.permit.io/v2/schema/{proj_id}/{env_id}/bulk/roles \
-H "Authorization: Bearer {your_permit_token}" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{
"key": "admin",
"name": "Administrator",
"permissions": ["document:create", "document:delete"]
},
{
"key": "editor",
"name": "Editor",
"resource": "document",
"permissions": ["read", "write"]
}]
}'