Tenants API documentation
This document describes all Tenant-related API endpoints of the Patrowl Dashboard. It covers tenant information, resource capacity (EASM credits, pentest slots, greybox credits, retest credits), managing the organizations under a tenant, allocating resources to those organizations, and managing the users linked to a tenant.
Base URL:
Authentication: All requests require an API token in the authorization header:
Authorization: Token <your-API-token>
What is a Tenant?
A Tenant represents your MSSP or customer account. It holds a pool of resource capacity — EASM credits, pentest slots, greybox credits, and retest credits — that you distribute across one or more Organizations it manages (for example, one organization per customer or business unit).
A tenant can manage multiple organizations.
Each resource type has three figures at any level: capacity (the total available), allocated (the portion assigned to organizations), and used (what has actually been consumed).
Permissions
Every endpoint in this document requires Tenant Administrator access:
You must be registered as an administrator of the specific tenant you are calling.
Requesting a tenant you do not administer returns 404 Not Found.
Being an administrator of your own organization does not by itself grant tenant administrator access — it must be explicitly granted (see §5.2).
The tenant list endpoint (GET /api/auth/tenants/) only returns tenants you administer.
1. Tenant
1.1 List tenants
Returns a paginated list of the tenants you administer.
Item | Value |
Method | GET |
URL | /api/auth/tenants/ |
Permission | Tenant Administrator |
Example request
GET /api/auth/tenants/
Authorization: Token <your-API-token>
Accept: application/json
Example response 200 OK
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "Acme MSSP",
"brand_image": "iVBORw0KGgoAAAANSUhEUgAA...",
"updated_at": "2025-02-20T10:00:00Z",
"resources": {
"easm_credits": { "capacity": 500, "allocated": 350, "used": 5 },
"pentest_slots": { "capacity": 10, "allocated": 3, "used": 1 },
"greybox_credits": { "capacity": 20, "allocated": 5, "used": 0 },
"retest_credits": { "capacity": 20, "allocated": 5, "used": 0 }
}
}
]
}
brand_image is your tenant logo, encoded as a base64 string (or null if none is set).
Possible status codes
Code | Description |
200 | Success. Empty results if you administer no tenant. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for any tenant. |
1.2 Retrieve a tenant
Item | Value |
Method | GET |
URL | /api/auth/tenants/{id}/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Example request
GET /api/auth/tenants/1/
Authorization: Token <your-API-token>
Accept: application/json
Example response 200 OK
Same shape as a single item of §1.1's results.
Possible status codes
Code | Description |
200 | Success. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
2. Tenant memberships
Add or remove users from organizations in bulk, within a tenant.
2.1 Bulk assign memberships
Adds every user in user_ids to every organization in organization_ids.
Users already members of an organization are left unchanged.
Item | Value |
Method | POST |
URL | /api/auth/tenants/{id}/memberships/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
user_ids | array of integers | Yes | User IDs to add. At least one. |
organization_ids | array of integers | Yes | Organization IDs to add the users to. At least one. Every organization must belong to this tenant. |
Example request
POST /api/auth/tenants/1/memberships/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"user_ids": [10, 11],
"organization_ids": [5, 6]
}
Example response 200 OK
{
"status": "created"
}
Possible status codes
Code | Description |
200 | Success. |
400 | Invalid payload, or one or more organizations/users are outside the tenant. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
2.2 Bulk remove memberships
Removes every user in user_ids from every organization in organization_ids. Removing a user from an organization also clears anything they own or are assigned to within that organization (assets, asset groups, vulnerabilities, remediations, team memberships, and pending notifications).
Item | Value |
Method | DELETE |
URL | /api/auth/tenants/{id}/memberships/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
user_ids | array of integers | Yes | User IDs to remove. At least one. |
organization_ids | array of integers | Yes | Organization IDs to remove the users from. At least one. Every organization must belong to this tenant. |
Example request
DELETE /api/auth/tenants/1/memberships/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"user_ids": [10, 11],
"organization_ids": [5, 6]
}
Example response 200 OK
{
"status": "success"
}
Possible status codes
Code | Description |
200 | Success. |
400 | Invalid payload, or one or more organizations/users are outside the tenant. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
3. Tenant organizations
Manage the organizations your tenant provisions and owns.
3.1 List organizations for a tenant
Item | Value |
Method | GET |
URL | /api/auth/tenants/{id}/organizations/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Query parameters
Parameter | Type | Required | Description |
search | string | No | Case-insensitive search on organization name. |
Example request
GET /api/auth/tenants/1/organizations/?search=acme
Authorization: Token <your-API-token>
Accept: application/json
Example response 200 OK
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 5,
"name": "Acme UK",
"member_total": 3,
"member_preview": [
{ "id": 10, "email": "[email protected]" },
{ "id": 11, "email": "[email protected]" }
],
"created_by": "[email protected]",
"created_at": "2025-01-10T09:00:00Z",
"updated_at": "2025-02-20T10:00:00Z"
}
]
}member_preview lists up to 5 members of the organization. created_by may be
null if unknown.
Possible status codes
Code | Description |
200 | Success. Empty page if search matches nothing. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
3.2 Create an organization under a tenant
Creates a new organization managed by the tenant, with an optional logo and initial resource allocations (each defaults to 0).
Item | Value |
Method | POST |
URL | /api/auth/tenants/{id}/organizations/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
name | string | Yes | Organization name, max 200 characters. Must be unique within the tenant. |
brand_image | string | No | Logo, encoded as a base64 string. |
easm_credits | integer | No | Initial allocation. Min 0 . Default 0 . |
pentest_slots | integer | No | Initial allocation. Min 0 . Default 0 . |
greybox_credits | integer | No | Initial allocation. Min 0 . Default 0 . |
retest_credits | integer | No | Initial allocation. Min 0 . Default 0 . |
Requested allocations cannot exceed the tenant's remaining (unallocated) capacity for each resource.
Example request
POST /api/auth/tenants/1/organizations/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"name": "Acme UK",
"easm_credits": 50,
"pentest_slots": 2,
"greybox_credits": 5,
"retest_credits": 5
}
Example response 201 Created
{
"id": 5,
"name": "Acme UK",
"resources": {
"easm_credits": { "capacity": 500, "allocated": 50, "used": 0 },
"pentest_slots": { "capacity": 10, "allocated": 2, "used": 0 },
"greybox_credits": { "capacity": 20, "allocated": 5, "used": 0 },
"retest_credits": { "capacity": 20, "allocated": 5, "used": 0 }
},
"created_by": "[email protected]",
"created_at": "2025-02-20T10:00:00Z",
"updated_at": "2025-02-20T10:00:00Z"
}
Possible status codes
Code | Description |
201 | Organization created. |
400 | Invalid payload; the name is already used within the tenant; or a requested allocation exceeds the tenant's remaining capacity. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
502 | The organization could not be provisioned. Please try again later; contact support if the problem persists. |
3.3 Update an organization (rename / change logo)
Item | Value |
Method | PATCH |
URL | /api/auth/tenants/{id}/organizations/{org_id}/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
org_id | integer | Organization ID. Must belong to the tenant. |
Request body (JSON)
Field | Type | Required | Description |
name | string | No | New name, max 200 characters. At least one of name / brand_image required. |
brand_image | string | No | New logo, encoded as a base64 string. |
Example request
PATCH /api/auth/tenants/1/organizations/5/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"name": "Acme UK Ltd"
}
Example response 200 OK
{
"id": 5,
"name": "Acme UK Ltd",
"updated_at": "2025-02-21T08:00:00Z"
}
Possible status codes
Code | Description |
200 | Success. |
400 | Neither name nor brand_image provided; or the name is already used within the tenant. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant or organization not found (or organization not in this tenant). |
502 | The update could not be applied. Please try again later; contact support if the problem persists. |
3.4 Bulk delete organizations
Deletes one or more organizations of a tenant. Their resource allocations are released back to the tenant's available capacity.
Item | Value |
Method | DELETE |
URL | /api/auth/tenants/{id}/organizations/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
ids | array of integers | Yes | Organization IDs to delete. Every id must belong to the tenant. |
Example request
DELETE /api/auth/tenants/1/organizations/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"ids": [5, 6]
}
Example response 200 OK
{
"deleted_ids": [5, 6]
}
Example error response
{
"invalid_ids": [99]
}Possible status codes
Code | Description |
200 | Success; deleted_ids echoes the requested ids . |
400 | Invalid/empty ids , or one or more ids do not belong to the tenant ( invalid_ids ). |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
4. Tenant organization resources
View and adjust how much of the tenant's resource capacity is allocated to each organization.
4.1 List organization resources for a tenant
Item | Value |
Method | GET |
URL | /api/auth/tenants/{id}/organizations/resources/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Query parameters
Parameter | Type | Required | Description |
search | string | No | Case-insensitive search on organization name. |
Example request
GET /api/auth/tenants/1/organizations/resources/?search=acme
Authorization: Token <your-API-token>
Accept: application/json
Example response 200 OK
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 5,
"name": "Acme UK",
"asset_count": 42,
"resources": {
"easm_credits": { "capacity": 500, "allocated": 50, "used": 42 },
"pentest_slots": { "capacity": 10, "allocated": 2, "used": 1 },
"greybox_credits": { "capacity": 20, "allocated": 5, "used": 0 },
"retest_credits": { "capacity": 20, "allocated": 5, "used": 0 }
},
"created_at": "2025-01-10T09:00:00Z",
"updated_at": "2025-02-20T10:00:00Z"
}
]
}
asset_count is the number of active assets monitored for that organization.
Possible status codes
Code | Description |
200 | Success. Empty page if search matches nothing. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
4.2 Update an organization's resource allocations
Updates one or more of the organization's allocations (EASM credits, pentest slots, greybox credits, retest credits). At least one field is required.
Item | Value |
Method | PATCH |
URL | /api/auth/tenants/{id}/organizations/{org_id}/resources/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
org_id | integer | Organization ID. Must belong to the tenant. |
Request body (JSON)
Field | Type | Required | Description |
easm_credits | integer | No | New allocation. Min 0 . |
pentest_slots | integer | No | New allocation. Min 0 . |
greybox_credits | integer | No | New allocation. Min 0 . |
retest_credits | integer | No | New allocation. Min 0 . |
A new value cannot be set below what the organization is already using, and cannot exceed the tenant's remaining available capacity.
Example request
PATCH /api/auth/tenants/1/organizations/5/resources/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"easm_credits": 100
}
Example response 200 OK
{
"resources": {
"easm_credits": { "capacity": 500, "allocated": 100, "used": 42 },
"pentest_slots": { "capacity": 10, "allocated": 2, "used": 1 },
"greybox_credits": { "capacity": 20, "allocated": 5, "used": 0 },
"retest_credits": { "capacity": 20, "allocated": 5, "used": 0 }
}
}
Example error response 400 Bad Request
{
"easm_credits": "Cannot set easm_credits to 10: 42 are currently in use for this organization."
}
or, when exceeding the tenant's remaining capacity:
{
"easm_credits": "Cannot set easm_credits to 600: tenant capacity allows 450 at most (500 total, 50 allocated to other organizations)."
}
Possible status codes
Code | Description |
200 | Success. |
400 | No resource field provided, allocation below current usage, or allocation exceeds remaining tenant capacity. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant or organization not found (or organization not in this tenant). |
5. Tenant users
Directory of the users linked to a tenant, plus tenant-administrator management and CSV export.
5.1 List users for a tenant
Returns users linked to the tenant directly, or through membership in one of its organizations.
Item | Value |
Method | GET |
URL | /api/auth/tenants/{id}/users/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Query parameters
Parameter | Type | Required | Description |
search | string | No | Free-text search (name/email). |
is_active | boolean | No | Filter by active status. |
role | string | No | Filter by user role. |
first_name | string | No | Filter by first name. |
last_name | string | No | Filter by last name. |
string | No | Filter by email. | |
org_id | integer | No | Filter by organization membership. |
org_not | integer | No | Exclude an organization's members. |
is_asset_owner | boolean | No | Filter users who own at least one asset. |
is_asset_group_owner | boolean | No | Filter users who own at least one asset group. |
is_vuln_owner | boolean | No | Filter users who own at least one vulnerability. |
is_vuln_solution_owner | boolean | No | Filter users who own at least one vulnerability solution. |
limit | integer | No | Page size (pagination), capped at 200. |
page | integer | No | Page number. |
Example request
GET /api/auth/tenants/1/users/?search=org_member@customer
Authorization: Token <your-API-token>
Accept: application/json
Example response 200 OK
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 11,
"email": "[email protected]",
"first_name": "Org",
"last_name": "Member",
"is_active": true,
"is_tenant_admin": false,
"last_login": "2025-02-19T07:30:00Z",
"organizations": [{ "id": 5, "name": "Acme UK", "slug": "acme-uk" }]
}
]
}
organizations only lists organizations belonging to this tenant.
Possible status codes
Code | Description |
200 | Success. Empty page if filters match nothing. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
5.2 Assign tenant administrator
Grants tenant-administrator access to an existing user.
Item | Value |
Method | POST |
URL | /api/auth/tenants/{id}/users/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
user_id | integer | Yes | ID of an existing user to promote. |
Example request
POST /api/auth/tenants/1/users/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"user_id": 12
}
Example response 201 Created
{
"user_id": 12,
"tenant_id": 1
}
Possible status codes
Code | Description |
201 | User assigned as tenant administrator. |
400 | Invalid payload (missing/invalid user_id ). |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found (or user_id does not reference an existing user). |
409 | The user is already a tenant administrator. |
5.3 Revoke tenant administrator
Demotes a tenant administrator back to a standard tenant member. At least one administrator must always remain.
Item | Value |
Method | DELETE |
URL | /api/auth/tenants/{id}/users/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
Request body (JSON)
Field | Type | Required | Description |
user_id | integer | Yes | ID of the tenant administrator to demote. |
Example request
DELETE /api/auth/tenants/1/users/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: application/json
{
"user_id": 12
}
Example response 200 OK
{
"user_id": 12
}
Possible status codes
Code | Description |
200 | User demoted to standard tenant member. |
400 | Invalid payload, or this is the last remaining tenant administrator. |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant, or you are not permitted to revoke this particular administrator. |
404 | Tenant not found, or the user is not a tenant administrator. |
5.4 Export tenant users (CSV)
Exports users linked to the tenant as a CSV file. GET exports according to the same filters as §5.1; POST exports only the given user ids.
Item | Value |
Method | GET or POST |
URL | /api/auth/tenants/{id}/users/export/ |
Permission | Tenant Administrator (of this tenant) |
URL parameters
Parameter | Type | Description |
id | integer | Tenant ID. |
GET Applies the same query parameters as §5.1. No body.
POST
Request body (JSON)
Field | Type | Required | Description |
users_id | array of integers | Yes | User IDs to export. At least one. |
Example request (GET)
GET /api/auth/tenants/1/users/export/?is_active=true
Authorization: Token <your-API-token>
Accept: text/csv
Example request (POST)
POST /api/auth/tenants/1/users/export/
Authorization: Token <your-API-token>
Content-Type: application/json
Accept: text/csv
{
"users_id": [10, 11]
}
Response 200 OK
Content-Type: text/csv
Content-Disposition: attachment; filename="users_YYYY-MM-DD_HH-MM-SS.csv".
CSV columns (in order): Email, Firstname, Lastname, Enabled, Role, Last login, Organizations (comma-separated list of the tenant’s organizations the user belongs to).
A JSON response can be requested instead of CSV by sending Accept:application/json.
.
Possible status codes
Code | Description |
200 | CSV (or JSON) returned. |
400 | POST with invalid/empty users_id . |
401 | Unauthorized. |
403 | You are not a Tenant Administrator for this tenant. |
404 | Tenant not found. |
6. Common error response format
Errors are generally returned as a JSON body describing what went wrong, either as a general message:
{
"detail": "Human-readable description of the error."
}
or as a field-specific message:
{
"<field_name>": "Human-readable description of the error."
}
HTTP status codes used across this document:
Code | Usage |
200 | Success (including bulk operations and CSV/JSON export). |
201 | Resource created (organization, tenant-admin assignment). |
400 | Bad request (invalid/missing parameters or body; a business rule was violated, such as a resource limit or a duplicate name). |
401 | Unauthorized (missing/invalid token). |
403 | Forbidden (you are not a Tenant Administrator for this tenant, or an administrative rule prevents the action). |
404 | Not found (tenant, organization, or user not found, or outside your scope). |
409 | Conflict (the user is already a tenant administrator). |
502 | The request could not be completed due to a downstream error. Please try again later. |
7. Summary table
Action | Method | URL | Permission |
List tenants | GET | /api/auth/tenants/ | Tenant Administrator |
Retrieve tenant | GET | /api/auth/tenants/{id}/ | Tenant Administrator |
Bulk assign memberships | POST | /api/auth/tenants/{id}/memberships/ | Tenant Administrator |
Bulk remove memberships | DELETE | /api/auth/tenants/{id}/memberships/ | Tenant Administrator |
List organizations of a tenant (filter: search ) | GET | /api/auth/tenants/{id}/organizations/ | Tenant Administrator |
Create organization under a tenant | POST | /api/auth/tenants/{id}/organizations/ | Tenant Administrator |
Update organization (name/logo) | PATCH | /api/auth/tenants/{id}/organizations/{org_id}/ | Tenant Administrator |
Bulk delete organizations | DELETE | /api/auth/tenants/{id}/organizations/ | Tenant Administrator |
List organization resources (filter: search ) | GET | /api/auth/tenants/{id}/organizations/resources/ | Tenant Administrator |
Update organization resource allocations | PATCH | /api/auth/tenants/{id}/organizations/{org_id}/resources/ | Tenant Administrator |
List users linked to a tenant (filters: see §5.1) | GET | /api/auth/tenants/{id}/users/ | Tenant Administrator |
Assign tenant administrator | POST | /api/auth/tenants/{id}/users/ | Tenant Administrator |
Revoke tenant administrator | DELETE | /api/auth/tenants/{id}/users/ | Tenant Administrator |
Export tenant users (CSV/JSON) | GET / POST | /api/auth/tenants/{id}/users/export/ | Tenant Administrator |
