Skip to content
synthreo.ai

User Management API

User Management API reference — create, update, and manage users, roles, and application permissions across Synthreo tenant instances via REST API.

The User Management API provides comprehensive functionality for managing users, their permissions, and access to applications within the Synthreo platform. This includes adding users to companies, managing application permissions, and controlling user access across the tenant hierarchy.

https://auth.synthreo.ai
```text
## Authentication
**Description**: All endpoints require authentication via JWT Bearer token.
**URL**: `POST /auth/token`
**Request Body**:
```json
{
"email": "example@company.com",
"password": "password",
"customerId": 123
}
```text
**Field Descriptions**:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `email` | string | Yes | Your email address |
| `password` | string | Yes | Your password |
| `customerId` | integer | No | The customer you want to generate a token for. If omitted, generates a token for your default customer. |
**Example Response**:
```json
{
"token": "token here",
"customerOptions": [
{
"customerId": 123,
"displayName": "MyCompany",
"roleName": "Admin",
"isOwner": false
}
]
}
```text
The value in Token is your JWT token.
The list of customers is the customers you have access to.
**Append the following to your header in all future calls**
```text
Authorization: Bearer your_jwt_token
```text
---
## User Management Endpoints
### Get Users in Company
**Description**: Retrieves all users associated with a company and their detailed permission information.
**URL**: `GET /tenant/users/{cid?}`
**Requirements**:
- Authentication required
**Parameters**:
- `cid` (optional): Company ID. If omitted, returns users for the company you generated a token for.
**Example Request**:
```http
GET /tenant/users/123 HTTP/1.1
Host: auth.synthreo.ai
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```text
**Example Response**:
```json
[
{
"id": 456,
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@company.com",
"createdAt": "2024-01-15T10:30:00Z",
"hasPassword": true,
"otpMethod": "Email",
"lastAccess": "2024-08-28T09:15:00Z",
"name": "John Doe",
"permissions": [
{
"id": 1,
"lastAccess": "2025-08-28T18:16:24.330121",
"disabled": false,
"createdAt": "2025-08-20T17:53:49.876681",
"role": { ... },
"account": { ... },
"instanceActive": true,
"application": { ... },
"region": { ... }
}
]
}
]
```text
### Add User to Company
**Description**: Creates a new user account and adds them to the specified company with Threo access.
**URL**: `POST /tenant/user`
**Requirements**:
- Authentication required
**Request Body**:
```json
{
"email": "newuser@company.com",
"firstName": "Jane",
"lastName": "Smith",
"name": "Jane Smith"
}
```text
**Field Descriptions**:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `customerId` | integer | No | Company ID (defaults to current company if omitted) |
| `email` | string | Yes | Valid email address for the new user |
| `firstName` | string | No | First name of the user |
| `lastName` | string | No | Last name of the user |
| `name` | string | No | Full name (automatically splits into firstName/lastName if other fields are empty) |
**Example Request**:
```http
POST /tenant/user HTTP/1.1
Host: auth.synthreo.ai
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"customerId": 123,
"email": "newuser@company.com",
"firstName": "Jane",
"lastName": "Smith"
}
```text
**Response**: `201 Created` on success
### Reinitiate User Account
**Description**: Resends the initial setup email to a user who hasn't completed account setup (users without passwords).
**URL**: `POST /tenant/user/init`
**Requirements**:
- Authentication required
**Request Body**:
```json
{
"id": 456
}
```text
**Example Request**:
```http
POST /tenant/user/init HTTP/1.1
Host: auth.synthreo.ai
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"id": 456
}
```text
**Response**: `204 No Content` on success
**Notes**:
- Only works for users who haven't set up their password yet
- Returns 400 error if user has already initiated their account
- For password reset of existing users, use the `/auth/reset` endpoint instead
---
## Permission Management Endpoints
### Get Permission Options
**Description**: Retrieves available options for creating permissions including applications, regions, accounts, roles, and users.
**URLs**:
`GET /permission/options?{queryparameters}` - Shows list of applications with their values
`GET /permission/options/{type}?{queryparameters}` - Shows list of regions with their values
`GET /permission/options/{type}/{region}?{queryparameters}` - Shows list of accounts with their values
`GET /permission/options/{type}/{region}/{account}?{queryparameters}` - Shows roles and users
**Requirements**:
- Authentication required
**Route Parameters**:
| Field | Type | Description |
|---|---|---|
| `type` | string | Application value |
| `region` | integer | Region value |
| `account` | string | account value |
**Query Parameters**:
| Field | Type | Required | Description |
|---|---|---|---|
| `cid` | integer | No | customerId |
| `all` | boolean | No | Include disabled accounts |
**Example Request**:
```http
GET /permission/options/1/1/101?cid=123 HTTP/1.1
Host: auth.synthreo.ai
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```text
**Example Response**:
```json
{
"applications": [
{
"value": 1,
"title": "TheoBuilder",
"selected": true
},
{
"value": 2,
"title": "ThreoAI",
"selected": false
},
{
"value": 3,
"title": "Tenant management",
"selected": false
}
],
"regions": [
{
"value": 1,
"title": "US East",
"selected": true
},
{
"value": 2,
"title": "US West",
"selected": false
}
],
"accounts": [
{
"value": 101,
"title": "Builder Production (id: builder_prod_123)",
"selected": true
}
],
"roles": [
{
"value": 1,
"title": "Admin",
"selected": false
},
{
"value": 2,
"title": "User",
"selected": false
}
],
"users": [
{
"value": 456,
"title": "John Doe (john.doe@company.com)",
"selected": false
},
{
"value": 457,
"title": "Jane Smith (jane.smith@company.com)",
"selected": false
}
]
}
```text
### Create Account Permission
**Description**: Creates a new permission granting a user access to an application account with a specific role.
**URL**: `POST /permission`
**Requirements**:
- Authentication required
**Request Body**:
```json
{
"appAccountId": 101,
"appRoleId": 2,
"userIdentityId": 456,
"disabled": false
}
```text
**Field Descriptions**:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `appAccountId` | integer | Yes | ID of the application account to grant access to |
| `appRoleId` | integer | Yes | ID of the role to assign |
| `userIdentityId` | integer | Yes | User ID |
| `disabled` | boolean | No | Whether permission is disabled (default: false) |
**Example Request**:
```http
POST /permission HTTP/1.1
Host: auth.synthreo.ai
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"appAccountId": 101,
"appRoleId": 2,
"userIdentityId": 456,
"disabled": false
}
```text
**Example Response**:
```json
{
"id": 789,
"appAccountId": 101,
"userIdentityId": 456,
"appRoleId": 2,
"lastAccess": null,
"disabled": false,
"createdAt": "2024-08-28T15:30:00Z",
"createdBy": "{\"id\":123,\"email\":\"admin@company.com\"}"
}
```text
### Update Account Permission
**Description**: Updates an existing permission's role assignment.
**URL**: `PUT /permission`
**Requirements**:
- Authentication required
**Request Body**:
```json
{
"id": 789,
"appRoleId": 123
}
```text
**Example Request**:
```http
PUT /permission HTTP/1.1
Host: auth.synthreo.ai
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"id": 789,
"appRoleId": 1
}
```text
**Response**: `204 No Content` on success
### Toggle Account Permission
**Description**: Enables or disables an existing account permission.
**URL**: `PATCH /permission/{permId}`
**Requirements**:
- Authentication required
**Parameters**:
- `permId` (integer): Permission ID to toggle
**Example Request**:
```http
PATCH /permission/789 HTTP/1.1
Host: auth.synthreo.ai
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```text
**Response**: `204 No Content` on success
### Delete Account Permission
**Description**: Permanently deletes an account permission, removing user access to the application account.
**URL**: `DELETE /permission/{permId}`
**Requirements**:
- Authentication required
**Parameters**:
- `permId` (integer): Permission ID to delete
**Example Request**:
```http
DELETE /permission/789 HTTP/1.1
Host: auth.synthreo.ai
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```text
**Response**: `204 No Content` on success
---
### Permission and Access Rules
**User Access Requirements**:
- Users can only be managed within companies you have access to (your company or its descendants)
- Account permissions can only be created for application accounts belonging to accessible companies
- Role assignments must belong to the same company as the application account or be system-wide roles
**Permission Management Rules**:
- Cannot create duplicate permissions for the same user and application account
- Disabled permissions preserve the relationship but prevent access
- Deleting permissions permanently removes user access to the application account
- Role changes require the new role to be valid for the application type
---
## Code Examples
### Add User (Python)
```python
import requests
def add_user_to_company(customer_id, email, first_name, last_name):
url = "https://auth.synthreo.ai/tenant/user"
headers = {
"Authorization": f"Bearer {access_token}"
}
data = {
"customerId": customer_id,
"email": email,
"firstName": first_name,
"lastName": last_name
}
try:
response = requests.post(url, headers=headers, json=data)
if not response.ok:
error_detail = response.json().get('detail', 'Unknown error')
raise Exception(f"Failed to add user: {error_detail}")
return True
except requests.exceptions.RequestException as e:
print(f"Error adding user: {e}")
return False
```text
### Print Company Users with Permissions (Python)
```python
def get_company_users(customer_id=None):
url = "https://auth.synthreo.ai/tenant/users"
if customer_id:
url += f"/{customer_id}"
headers = {
"Authorization": f"Bearer {access_token}"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
users = get_company_users(123):
for user in users:
print(f"User: {user['firstName']} {user['lastName']} <{user['email']}>")
print(f" Has Password: {user['hasPassword']}")
print(f" 2FA Method: {user['otpMethod']}")
print(f" Permissions:")
for perm in user['permissions']:
app_name = perm['application']['name']
role_name = perm['role']['name']
account_name = perm['account']['name']
status = "Disabled" if perm['disabled'] else "Active"
print(f" - {app_name}: {role_name} on {account_name} ({status})")
```text
### Create Account Permission (Python)
```python
def create_account_permission(app_account_id, role_id, user_id):
url = "https://auth.synthreo.ai/permission"
headers = {
"Authorization": f"Bearer {access_token}"
}
data = {
"appAccountId": app_account_id,
"appRoleId": role_id,
"userIdentityId": user_id,
"disabled": False
}
response = requests.post(url, headers=headers, json=data)
if not response.ok:
error_detail = response.json().get('detail', 'Unknown error')
if 'Permission already exists' in error_detail:
print('User already has permission for this account')
return False
raise Exception(f"Failed to create permission: {error_detail}")
return response.json()
```text
### Get Permission Options (Python)
```python
def get_permission_options(app_type=None, region_id=None, account_id=None, customer_id=None):
url = "https://auth.synthreo.ai/permission/options"
# Build URL path
if app_type:
url += f"/{app_type}"
if region_id:
url += f"/{region_id}"
if account_id:
url += f"/{account_id}"
headers = {
"Authorization": f"Bearer {access_token}"
}
params = {}
if customer_id:
params['cid'] = customer_id
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
return response.json()
options = get_permission_options(customer_id=123)
options = get_permission_options(1, customer_id=123)
options = get_permission_options(1, 1, customer_id=123)
```text
### Reinitiate User Setup (Python)
```python
def reinitiate_user(user_id):
url = "https://auth.synthreo.ai/tenant/user/init"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
data = {
"id": user_id
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 400:
error_detail = response.json().get('detail', '')
if 'already initiated' in error_detail:
print("User has already set up their account.")
return False
elif response.status_code == 204:
print(f"Setup email sent")
return True
else:
response.raise_for_status()
return False
```text
---
## Common Workflows
### Complete User Onboarding Workflow
```python
def onboard_new_user(customer_id, email, first_name, last_name, permissions):
"""
Complete user onboarding workflow with permission assignment
permissions: list of {'applicationId': int, 'roleId': int}
"""
try:
# Step 1: Add user to company
add_user_to_company(customer_id, email, first_name, last_name)
print(f"User {email} added to customer {customer_id}")
# Step 2: Get user id
user_id = next((u['id'] for u in get_company_users(customer_id) if u['email'] == email), None)
if not user_id:
print("Failed to find user Id")
return False
# Step 3: Create permissions
for perm in permissions:
create_account_permission(perm['applicationId'], perm['roleId'], user_id)
print(f"Permission created: {perm['applicationName']} - {perm['roleName']}")
return True
except Exception as error:
print(f"Onboarding failed: {error}")
return False
onboard_new_user(123, 'jsmith@company.com', 'Jane', 'Smith', [
{'applicationId': 1, 'roleId': 4}, # Full Power User for Builder
{'applicationId': 2, 'roleId': 3} # Admin for ThreoAI
])
```text
---
## Authorization Notes
1. **Authentication**: All endpoints require a valid JWT token in the Authorization header
2. **Hierarchical Access Control**:
- Users can only manage other users within their accessible company hierarchy
- Parent companies can manage users in subsidiary companies
- Users cannot manage permissions for companies above them in the hierarchy
3. **Permission Validation**:
- Account permissions can only be created for accounts belonging to accessible companies
- Roles must be compatible with the application type and company
- Cannot create duplicate permissions for the same user and account combination
4. **User Identity Management**:
- Email addresses are used as unique identifiers for users
- Users can be created automatically when adding permissions if they don't exist
- Name parsing automatically splits full names into first/last name components
## Best Practices
### User Management
- Always validate email addresses before creating users
- Use the permission options endpoint to populate UI dropdowns
- Check user `hasPassword` status before attempting reinitialization
- Implement proper error handling for duplicate user scenarios
### Permission Management
- Retrieve available options before creating permissions to ensure valid combinations
- Use toggle functionality for temporary access control instead of delete/recreate
- Monitor `lastAccess` timestamps to identify inactive users
- Consider role hierarchies when assigning permissions (Admin vs User roles)
### Performance Optimization
- Cache permission options for form population
- Batch permission operations when onboarding multiple users
- Use company-specific queries to reduce data transfer
### Security Considerations
- Validate user access to target companies before making permission changes
- Log all permission modifications for audit trails
- Implement proper session management for long-running operations
- Use principle of least privilege when assigning roles