These endpoints manage tenant users and provide read access to roles, permissions, authentication settings, and API clients. POST /api/public/users is the only write endpoint on the Public API; every other endpoint here is read-only. All endpoints are tenant-scoped: a request only returns users, roles, settings, and clients belonging to the tenant that issued the token.
List Users
Returns a paginated list of users in your tenant, ordered by creation date with the oldest user first.
Request:
GET /api/public/users
Authentication:
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Users_Read
Query Parameters

Response Fields

Sample Response
json
{
"data": [
{
"userId": 2141,
"firstName": "Ada",
"lastName": "Lovelace",
"email": "[email protected]",
"state": "Active",
"mfaStatus": true,
"mfaAction": true,
"roleId": null,
"roleName": "Tenant Admin",
"createdAt": "2025-11-03T14:22:00Z"
}
],
"pagination": {
"limit": 50,
"nextCursor": "eyJwYWdlTnVtYmVyIjoxfQ==",
"hasMore": true
},
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:00:00Z"
}
}
Users are ordered by creation date, oldest first, so a client that has caught up keeps its position and picks up new users on the next poll rather than seeing existing rows shift. A malformed or invalid cursor is rejected with a 400 error rather than falling back silently to the first page.
Error Responses
400 BAD_REQUEST:cursorandupdatedAfterwere supplied together.400 VALIDATION_FAILED: the cursor is malformed or invalid.401 UNAUTHORIZED: the request is missing a token or the token lacksApi_Users_Read.500 INTERNAL_ERROR: an unexpected server error.

Get a User
Returns a single user by ID within your tenant.
Request
GET /api/public/users/{id}
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Users_Read
{id} is the userId returned by GET /api/public/users. Not paginated; pagination is null. The response fields are the same as the list endpoint, with roleId populated.
Sample Response{
"data": {
"userId": 2141,
"firstName": "Ada",
"lastName": "Lovelace",
"email": "[email protected]",
"state": "Active",
"mfaStatus": true,
"mfaAction": true,
"roleId": 12,
"roleName": "Tenant Admin",
"createdAt": "2025-11-03T14:22:00Z"
},
"pagination": null,
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:05:00Z"
}
}
This is the only way to retrieve a user's roleId through the Public API; the list endpoint always returns null for this field. A user belonging to more than one tenant has a role per tenant, and only the calling tenant's role is returned.
Error Responses
404 NOT_FOUND: the user does not exist, or belongs to a different tenant. The two cases are indistinguishable by design.401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_Users_Read.500 INTERNAL_ERROR: an unexpected server error.

Create a User
Creates a user in your tenant with exactly one role assigned. This is the only write endpoint on the Public API.
Request
POST /api/public/users
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Users_Create. This is a separate permission from Api_Users_Read; a read-only client cannot create users.
Request Body: All Fields Required

Sample Request
{
"firstName": "Grace",
"lastName": "Hopper",
"email": "[email protected]",
"roleId": 12
}
Sample Response (201 Created)
{
"data": {
"userId": 2288,
"firstName": "Grace",
"lastName": "Hopper",
"email": "[email protected]",
"state": "Invited",
"mfaStatus": false,
"mfaAction": true,
"roleId": 12,
"roleName": "Security Analyst",
"createdAt": "2026-08-13T10:10:00Z"
},
"pagination": null,
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:10:00Z"
}
}
The new user is created in an Invited state. An invitation is sent, and the account activates once the user completes enrollment. This endpoint is not idempotent and has no request-deduplication key: if a request times out and you retry it, a 409 CONFLICT response may mean the first attempt actually succeeded. Treat it as "already created" rather than a failure.
Error Responses
409 CONFLICT: a user with this email address already exists in your tenant.422 VALIDATION_FAILED: a field is missing, out of length, not a valid email, orroleIdis missing, not greater than 0, or does not match a role in your tenant.401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_Users_Create.500 INTERNAL_ERROR: an unexpected server error.

List Roles
Returns every role in your tenant, along with each role's assigned permissions.
Request
GET /api/public/roles
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Roles_Read
Not paginated. pagination is null; the full list is returned in data.
Response Fields

Sample Response
{
"data": [
{
"roleId": 12,
"name": "Tenant Admin",
"description": "Full administrative access within the tenant",
"state": "Active",
"type": "User",
"isReadOnly": true,
"permissions": [
{
"permissionId": 269,
"name": "Read",
"module": "API",
"function": "Users",
"code": "Api_Users_Read"
}
]
}
],
"pagination": null,
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:15:00Z"
}
}
Only roles with type: "User" are valid for the roleId field on POST /api/public/users. Inactive roles are returned; filter on state if you only want assignable roles. No ordering is guaranteed, so sort client-side if you need a stable order.
Error Responses
401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_Roles_Read.500 INTERNAL_ERROR: an unexpected server error, including an upstream failure. This endpoint returns an error rather than an empty list when role data cannot be retrieved, so an emptydataarray always means your tenant genuinely has no roles.

Get a Role
Returns a single role by ID, scoped to your tenant.
Request
GET /api/public/roles/{id}
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Roles_Read
{id} is the roleId returned by GET /api/public/roles. Not paginated. The response is the same shape as the list endpoint. If you need several roles, prefer one call to GET /api/public/roles over multiple calls to this endpoint.
Error Responses
404 NOT_FOUND: the roles does not exist, or belongs to a different tenant.401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_Roles_Read.500 INTERNAL_ERROR: an unexpected server error.

List Permissions
Returns the catalog of permissions that can be assigned to roles.
Request
GET /api/public/permissions
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_Roles_Read
Not paginated.
Response Fields

Sample Response
{
"data": [
{
"permissionId": 269,
"name": "Read",
"module": "API",
"function": "Users",
"code": "Api_Users_Read"
}
],
"pagination": null,
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:25:00Z"
}
}
This catalog may include permissions that do not yet gate any endpoint. Ordering is not guaranteed; sort client-side if you need a stable order.
Error Responses
401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_Roles_Read.500 INTERNAL_ERROR: an unexpected server error, including an upstream failure. As with roles, an emptydataarray always means your tenant genuinely has no assignable permissions.

Get Authentication Settings
Returns your tenant's authentication configuration: SSO settings and multi-factor authentication policy.
Request
GET /api/public/authentication-settings
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_AuthSettings_Read
Not paginated. data is a single object.
Response Fields

Sample Response: SSO Configured
{
"data": {
"ssoEnabled": true,
"ssoEnforced": false,
"providerType": "AzureAD",
"tenantName": "contoso",
"mfaEnabled": true
},
"pagination": null,
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:30:00Z"
}
}
Sample Response: No SSO Configured
{
"data": {
"ssoEnabled": false,
"ssoEnforced": false,
"providerType": null,
"tenantName": null,
"mfaEnabled": false
},
"pagination": null,
"error": null,
"meta": {
"requestId": "7b8c9d0e-1f2a-4b3c-9d4e-5f6a7b8c9d0e",
"timestamp": "2026-08-13T10:30:01Z"
}
}
A tenant without SSO configured returns 200 with these defaults, not an error. mfaEnabled is the tenant-wide policy, not a per-user state; combine it with GET /api/public/users to find users who have not yet enrolled under an enforcing policy.
Error Responses
401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_AuthSettings_Read.500 INTERNAL_ERROR: an unexpected server error.

List API Clients
Returns metadata for the API clients registered in your tenant, including the client you are using to make this request.
Request
GET /api/public/api-clients
Authentication
Bearer token. See Authentication & Generating Credentials.
Required Permission
Api_ApiClients_Read
Query Parameters

Response Fields

Sample Response
{
"data": [
{
"clientId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"name": "ServiceNow connector",
"roleName": "Default API Role",
"secretExpirationDate": "2027-07-17T00:00:00Z",
"createdAt": "2026-07-17T10:00:00Z"
}
],
"pagination": {
"nextCursor": "cDox",
"hasMore": true
},
"error": null,
"meta": {
"requestId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2026-08-13T10:35:00Z"
}
}
Client secrets are never returned by this or any endpoint; a secret is shown once, at create, in the portal. secretExpirationDate is the main reason to poll this endpoint. Alert ahead of expiry so a client's secret doesn't lapse without warning. A malformed or invalid cursor is ignored and the first page is returned, rather than rejected, which differs from GET /api/public/users. An empty data array with hasMore: false can mean either that your tenant has no API clients or that the request could not be completed; re-poll to confirm before treating an empty result as authoritative.
Error Responses
401 UNAUTHORIZED: the request is missing a token, or the token lacksApi_ApiClients_Read.500 INTERNAL_ERROR: an unexpected server error.





