Teams API
The Teams API allows administrators to create, list, update, and delete teams programmatically, and to read the change history of a team.
Tip
For complete API documentation, including request/response schemas, visit the API docs.
All endpoints are served from your Qualytics deployment (e.g., https://your-instance.qualytics.io). The paths below include the /api prefix.
Permissions
Reading teams requires the Manager or Admin role. Creating, updating, and deleting teams requires the Admin role. The non-paginated listing is open to every role. See How Teams Work for details.
The Team Object
Every endpoint that returns a team uses the same shape.
| Field | Type | Description |
|---|---|---|
id |
integer |
The team's identifier. The Public team always has the ID -1. |
name |
string |
The team's unique name. This is the value group sync matches against directory groups. |
display_name |
string or null |
The optional friendly label shown in place of the name. null when no label is set. |
display_label |
string |
What users see in the platform: display_name when set, otherwise name. Read this field when you need the label on screen, and name when you need the value group sync matches on. |
description |
string or null |
The team's description. |
permission |
string |
The team permission: Editor, Author, Drafter, Viewer, or Reporter. |
users |
array of object |
The members of the team. Each entry carries the user's id, user_id, user_name, email, name, picture, role, user_type (Human or Service), last_login, deleted_at, and created. |
datastores |
array of object |
The datastores the team covers, source and enrichment alike. Each entry carries the datastore's id, name, description, store_type, type, connected, enrichment_only, and its default settings. enrichment_only is true for enrichment datastores. |
created |
datetime |
When the team was created, in UTC. |
See Name and Display Name for how the three label fields relate.
List Teams
Retrieve a paginated list of teams with optional search and sorting.
Endpoint: GET /api/teams
Permission: Manager or Admin user role
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
name |
string |
Search teams whose display_label or name contains the value (partial match, case-insensitive). A team with a display name is found by either label. |
sort_name |
string |
Sort by display_label, which is the display name when set and the name otherwise (asc or desc). |
sort_created |
string |
Sort by creation date (asc or desc). |
page |
integer |
Page number, starting at 1. |
size |
integer |
Items per page. |
Example request and response
Request:
curl -X GET "https://your-instance.qualytics.io/api/teams?name=analysts&sort_name=asc" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (datastore entries trimmed for brevity):
{
"items": [
{
"id": 7,
"created": "2026-03-02T14:05:11Z",
"name": "WF-DQ-PROD-ANALYSTS-RW",
"display_name": "Production Analysts",
"display_label": "Production Analysts",
"description": "Analysts with write access to production quality checks",
"permission": "Author",
"users": [
{
"id": 42,
"created": "2026-01-15T10:30:00Z",
"user_id": "jane.doe@example.com",
"user_name": "jane.doe",
"email": "jane.doe@example.com",
"name": "Jane Doe",
"picture": null,
"role": "Member",
"user_type": "Human",
"last_login": "2026-09-15T08:12:40Z",
"deleted_at": null
}
],
"datastores": [
{
"id": 10,
"name": "Production Warehouse",
"description": null,
"store_type": "jdbc",
"type": "snowflake",
"connected": true,
"enrichment_only": false
},
{
"id": 20,
"name": "Enrichment Warehouse",
"description": null,
"store_type": "jdbc",
"type": "snowflake",
"connected": true,
"enrichment_only": true
}
]
}
],
"total": 1,
"page": 1,
"size": 50,
"pages": 1
}
For the UI equivalent, see The Teams List and Sort Teams.
List Teams (Non-Paginated)
Retrieve a flat list of teams, ordered by display_label. Useful for dropdowns and for finding the teams a user belongs to.
Endpoint: GET /api/teams/listing
Permission: Member or above
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
users |
array of integer |
Only teams that include at least one of these user IDs. Repeat the parameter for each ID (users=1&users=2). |
permission |
string |
Only teams with this team permission (Editor, Author, Drafter, Viewer, or Reporter). |
Example request
curl -X GET "https://your-instance.qualytics.io/api/teams/listing?users=42&permission=Author" \
-H "Authorization: Bearer YOUR_TOKEN"
The response is a JSON array of team objects, without the pagination wrapper.
Get Team
Retrieve a single team by ID.
Endpoint: GET /api/teams/{id}
Permission: Manager or Admin user role
Example request and response
Request:
curl -X GET "https://your-instance.qualytics.io/api/teams/7" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (datastore entries trimmed for brevity):
{
"id": 7,
"created": "2026-03-02T14:05:11Z",
"name": "WF-DQ-PROD-ANALYSTS-RW",
"display_name": "Production Analysts",
"display_label": "Production Analysts",
"description": "Analysts with write access to production quality checks",
"permission": "Author",
"users": [
{
"id": 42,
"created": "2026-01-15T10:30:00Z",
"user_id": "jane.doe@example.com",
"user_name": "jane.doe",
"email": "jane.doe@example.com",
"name": "Jane Doe",
"picture": null,
"role": "Member",
"user_type": "Human",
"last_login": "2026-09-15T08:12:40Z",
"deleted_at": null
}
],
"datastores": [
{
"id": 10,
"name": "Production Warehouse",
"description": null,
"store_type": "jdbc",
"type": "snowflake",
"connected": true,
"enrichment_only": false
}
]
}
Get Team History
Retrieve a paginated change log for the team, one entry per saved version, including who made each change.
Endpoint: GET /api/teams/{id}/history
Permission: Manager or Admin user role
Each entry carries the operation (insert, update, or delete), a changeset mapping each changed field to its [old, new] pair, and the transaction with the issued_at time and the user who made the change.
Example request and response
Request:
curl -X GET "https://your-instance.qualytics.io/api/teams/7/history" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (user entry trimmed for brevity):
{
"items": [
{
"operation": "update",
"operation_type": 1,
"changeset": {
"display_name": [null, "Production Analysts"],
"permission": ["Viewer", "Author"]
},
"transaction": {
"id": 9812,
"issued_at": "2026-09-10T16:40:02Z",
"user": {
"id": 1,
"user_id": "admin@example.com",
"name": "Platform Admin"
}
}
}
],
"total": 1,
"page": 1,
"size": 50,
"pages": 1
}
Create Team
Create a new team with optional user and datastore assignments.
Endpoint: POST /api/teams
Permission: Admin user role
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | The team name, up to 255 characters, unique across the platform. Leading and trailing spaces are removed. This is the value group sync matches against directory groups. |
display_name |
string |
No | A friendly label shown instead of the name, up to 255 characters. Not unique, and never used for group matching. Omit it, or send null or an empty string, for no label, so the team shows its name. |
description |
string |
No | A description of the team. |
user_ids |
array of integer |
No | The IDs of the users to add to the team. |
datastore_ids |
array of integer |
No | The IDs of the datastores the team can access, source and enrichment alike. |
permission |
string |
No | The team permission: Editor, Author, Drafter, Viewer, or Reporter. Defaults to Viewer. |
Example request and response
Request:
curl -X POST "https://your-instance.qualytics.io/api/teams" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "WF-DQ-PROD-ANALYSTS-RW",
"display_name": "Production Analysts",
"description": "Analysts with write access to production quality checks",
"user_ids": [42],
"datastore_ids": [10, 20],
"permission": "Author"
}'
Response: the created team object, with users and datastores resolved from the IDs you sent.
For the UI equivalent, see the Add a Team page.
Update Team
Update a team's name, display name, description, users, datastores, or permission level.
Endpoint: PUT /api/teams/{id}
Permission: Admin user role
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | The team name. Send the current name to keep it. A new name must not belong to another team. |
display_name |
string |
No | The friendly label. Leave the field out of the request to keep the current label. Send null or an empty string to clear it, so the team shows its name again. |
description |
string |
No | The new description. Unlike the other optional fields, leaving it out clears the current description, so resend the current value to keep it. |
user_ids |
array of integer |
No | The full list of user IDs the team should have. Replaces the current members; send [] to remove everyone. |
datastore_ids |
array of integer |
No | The full list of datastore IDs the team should cover. Replaces the current assignments. |
permission |
string |
No | The new team permission. |
Note
user_ids and datastore_ids replace the entire list. They are not additive, so pass the full desired list of IDs. display_name, permission, user_ids, and datastore_ids are unchanged when left out of the request, but description is not: an omitted description is saved as empty, so resend the current description whenever you update a team that has one.
Warning
The Public team's name, display_name, description, and user_ids are ignored on update; only its permission and datastore_ids can change. A datastore must belong to at least one team, so removing it from its only team returns a 409 Conflict error.
Example request and response
Request (clears the display name and moves the team to Editor, resending the description so it is kept):
curl -X PUT "https://your-instance.qualytics.io/api/teams/7" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "WF-DQ-PROD-ANALYSTS-RW",
"display_name": null,
"description": "Analysts with write access to production quality checks",
"permission": "Editor"
}'
Response (trimmed): the updated team object. With the display name cleared, display_label falls back to the name.
For the UI equivalent, see the Edit a Team page.
Delete Team
Permanently remove a team. Its members lose the access granted through the team, and its links to users and datastores are removed.
Endpoint: DELETE /api/teams/{id}
Permission: Admin user role
Status Code: 204 No Content on success
Warning
The Public team cannot be deleted. If a datastore would be left with no team, the request returns a 409 Conflict error naming that datastore; assign it to another team first.
Example request
For the UI equivalent, see the Delete a Team page.
Error Responses
| Status Code | Description |
|---|---|
401 Unauthorized |
Missing or invalid API token. |
403 Forbidden |
The caller's role is not allowed to perform the operation. |
404 Not Found |
No team, user, or datastore exists with the given ID. |
409 Conflict |
The team name is already taken, the Public team was targeted for deletion, or the change would leave a datastore with no team. |
422 Unprocessable Entity |
Invalid field values, such as a name over 255 characters or an unknown permission. |
Error response examples
409 Conflict (duplicate name):
409 Conflict (deleting the only team of a datastore):
{ "detail": "Attempt to orphan datastore: Production Warehouse. A datastore must be apart of another team before deleting" }
409 Conflict (deleting the Public team):
404 Not Found:
Permission Summary
| Operation | Minimum Permission |
|---|---|
| List Teams | Manager user role |
| List Teams (Non-Paginated) | Member user role |
| Get Team | Manager user role |
| Get Team History | Manager user role |
| Create Team | Admin user role |
| Update Team | Admin user role |
| Delete Team | Admin user role |