Provision users and manage channel membership through tenant-scoped API keys, with SCIM 2.0 support for identity providers and native JSON endpoints for direct integrations.
The public API gives each workspace a stable tenant-scoped endpoint for provisioning users and managing channel membership. It is designed for two common paths: SCIM 2.0 from an identity provider, and direct JSON requests from your own internal systems. Every request is authenticated with a tenant API key. Keys are created by an administrator, scoped to the exact API areas the integration needs, and can be rotated or revoked without changing the tenant slug.
https://api.whoot.me/v1/{tenantSlug}. Replace {tenantSlug} with the workspace slug shown in your admin dashboard.api_keys.manage permission.Okta SCIM production.scim:users:read - List and retrieve SCIM users.scim:users:write - Create, update, and deactivate SCIM users.scim:groups:read - List and retrieve SCIM groups.scim:groups:write - Update SCIM group membership mappings.api:users:read - List and retrieve users through the native API.api:users:write - Create, update, and deactivate users through the native API.api:channels:read - Read channel membership through the native API.api:channels:write - Add and remove channel members through the native API.Send the key as a bearer token on every request. JSON endpoints expect Content-Type: application/json. SCIM endpoints return SCIM-compatible response bodies where applicable.
curl https://api.whoot.me/v1/acme/scim/v2/Users \
-H "Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json"The API Keys page shows each key by name and prefix, never by full secret. You can see whether a key is active, expired, or revoked, which scopes it has, when it was last used, and when it expires.
Revoking a key is immediate. Any request using that token will fail authentication as soon as the key status changes to revoked.
GET /scim/v2/ServiceProviderConfig - SCIM capability metadata. Requires any valid SCIM read scope.GET /scim/v2/ResourceTypes - SCIM resource type metadata. Requires any valid SCIM read scope.GET /scim/v2/Schemas - SCIM schema metadata. Requires any valid SCIM read scope.GET /scim/v2/Users - List SCIM users. Requires scim:users:read.GET /scim/v2/Users/{id} - Retrieve one SCIM user. Requires scim:users:read.POST /scim/v2/Users - Create a SCIM user. Requires scim:users:write.PUT /scim/v2/Users/{id} - Replace user attributes. Requires scim:users:write.PATCH /scim/v2/Users/{id} - Patch user attributes. Requires scim:users:write.DELETE /scim/v2/Users/{id} - Deactivate a user. Requires scim:users:write.GET /scim/v2/Groups - List SCIM groups mapped to channels. Requires scim:groups:read.GET /scim/v2/Groups/{id} - Retrieve one SCIM group. Requires scim:groups:read.PATCH /scim/v2/Groups/{id} - Add or remove group members. Requires scim:groups:write.GET /users - List users through the native API. Requires api:users:read.GET /users/{id} - Retrieve one user through the native API. Requires api:users:read.POST /users - Create a user through the native API. Requires api:users:write.PUT /users/{id} - Replace user attributes through the native API. Requires api:users:write.PATCH /users/{id} - Patch user attributes through the native API. Requires api:users:write.DELETE /users/{id} - Deactivate a user through the native API. Requires api:users:write.GET /channels/{channelId}/members - List channel members. Requires api:channels:read.POST /channels/{channelId}/members - Add a channel member. Requires api:channels:write.DELETE /channels/{channelId}/members - Remove a channel member. Requires api:channels:write.Use GET /scim/v2/Users to list active and deactivated users in SCIM format. A simple userName eq "email@example.com" filter is supported.
GET /v1/acme/scim/v2/Users?filter=userName%20eq%20%22alex@example.com%22&count=100
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 1,
"Resources": [
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c",
"externalId": "00u123",
"userName": "alex@example.com",
"active": true,
"name": { "formatted": "Alex Morgan" },
"emails": [{ "value": "alex@example.com", "primary": true }],
"meta": {
"resourceType": "User",
"location": "/v1/acme/scim/v2/Users/7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c"
}
}
]
}Use POST /scim/v2/Users to provision a user. The request must include a valid userName or primary email. New users are assigned the default end-user role.
POST /v1/acme/scim/v2/Users
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"externalId": "00u123",
"userName": "alex@example.com",
"active": true,
"name": { "formatted": "Alex Morgan" },
"emails": [{ "value": "alex@example.com", "primary": true }]
}HTTP/1.1 201 Created
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c",
"externalId": "00u123",
"userName": "alex@example.com",
"active": true,
"name": { "formatted": "Alex Morgan" },
"emails": [{ "value": "alex@example.com", "primary": true }]
}PATCH /scim/v2/Users/{id} supports common SCIM patch operations for active, userName, and name.formatted. Setting active to false deactivates the user, removes tenant memberships, and removes channel memberships.
PATCH /v1/acme/scim/v2/Users/7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false }
]
}DELETE /v1/acme/scim/v2/Users/7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HTTP/1.1 204 No ContentSCIM groups map to whoot. channels. Identity providers can read mapped groups and add or remove members. Channel defaults, recording, transcription, retention, and region settings remain controlled by workspace administrators.
PATCH /v1/acme/scim/v2/Groups/0fcb33a8-9f3d-4a53-8127-64e7d22f65f5
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "add",
"value": {
"members": [
{ "value": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c" }
]
}
}
]
}{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "0fcb33a8-9f3d-4a53-8127-64e7d22f65f5",
"externalId": "ops-channel",
"displayName": "Operations",
"members": [
{
"value": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c",
"display": "Alex Morgan"
}
]
}The native user endpoints use compact JSON for internal tools that do not speak SCIM.
POST /v1/acme/users
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"email": "alex@example.com",
"full_name": "Alex Morgan",
"external_id": "hris-123",
"active": true
}HTTP/1.1 201 Created
Content-Type: application/json
{
"user": {
"id": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c",
"email": "alex@example.com",
"full_name": "Alex Morgan",
"active": true,
"created_at": "2026-05-04T10:30:00.000Z"
}
}Use channel member endpoints to add or remove an existing user from a channel. Set tx_permission to false when the user should listen but not transmit.
POST /v1/acme/channels/0fcb33a8-9f3d-4a53-8127-64e7d22f65f5/members
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"user_id": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c",
"tx_permission": true
}HTTP/1.1 201 Created
Content-Type: application/json
{ "ok": true }DELETE /v1/acme/channels/0fcb33a8-9f3d-4a53-8127-64e7d22f65f5/members
Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{ "user_id": "7e1f5dd7-8e4d-4e11-a9bb-9a86f2d58e2c" }
HTTP/1.1 204 No ContentAuthentication, authorization, validation, and capacity failures return explicit status codes. SCIM endpoints use SCIM error bodies where possible; native endpoints return standard JSON errors.
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{ "error": "Missing or invalid API key" }HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "Insufficient API key scope",
"required_scope": "scim:users:write"
}HTTP/1.1 403 Forbidden
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "403",
"scimType": "invalidValue",
"detail": "Not enough user licenses available",
"code": "NO_LICENSE_CAPACITY",
"licensed": 25,
"used": 25
}