Skip to main content

User Provisioning API v1

O
Written by Okke Formsma
Updated this week

API v3 is the preferred and full-featured API for user management. However, you may still need to use API v1 if you need to isolate access to user provisioning per sub-company or data source.


Status of API v1

  • The bulk user import in API v1 is deprecated

  • It has been replaced by the API v3 User Management API

  • If you can use API v3, you should: Link to API v3 docs


When API v1 is still useful

API v3 allows read access to all users on a platform. If your setup includes multiple user sources (like in a reseller model) and you want to avoid exposing users across sub-companies, API v1 can still be useful.

Why: API v1 is write-only, ideal when you need to provision users without reading platform-wide user data (write-only).


Base URL and authentication

Base URL

Use your platform domain:

https://your-name.platform.co.nl/

Authentication

Use an OAuth2 token with the write.users scope.

Token endpoint:

POST /o/token/

To request credentials (client ID, secret, and scopes), contact service@tinqwise.com.


How to import users

Endpoint

POST /api/accounts/user/bulk_import/

Required scope

  • write.users

JSON body structure

{
"users": [
{
"user_identifier": "EMP-123",
"first_name": "Alex",
"last_name": "Nguyen",
"email": "alex@example.com",
"groups": [
{"group_identifier": "manager", "group_type": "jobtitle"},
{"group_identifier": "amsterdam", "group_type": "city"}
],
"contract_start_at": "2026-01-01",
"contract_end_at": "2026-12-31",
"country": "NL",
"manager_identifier": "EMP-001",
"language": "en",
"uses_single_signon": false,
"status": "active"
}
]
}

Field references

  • users (required): Array of user objects.

    • user_identifier (required): Unique user key (max 150 chars). Used to update existing users.

    • first_name (optional, max 30 chars)

    • last_name (optional, max 150 chars)

    • email (required)

    • groups (optional): Array of {group_identifier, group_type}

    • contract_start_at (optional): YYYY-MM-DD

    • contract_end_at (optional): YYYY-MM-DD

    • country (optional, max 30 chars): deprecated

    • manager_identifier (optional): user_identifier of the manager

    • language (optional): en, nl, or another language code. Defaults to the platform default language.

    • uses_single_signon (optional): Boolean (default false). When true, no “set password” email is sent.

    • status (optional): active (default) or delete. delete suspends the user.

Response

{   "success": true }

💡 Tip:

To verify success, go to Users > Integrations > User importer in the Control environment.


How to assign users to groups

Users can be assigned to groups via the groups field in each user object (see the request body example above).

Each group entry has two fields:

  • group_identifier: the group’s unique key

  • group_type: the category the group belongs to (for example jobtitle or city)

Optionally, groups can be nested using parent fields:

  • parent_identifier (optional): the parent group’s identifier

  • parent_type (optional): the parent group’s type

Notes:

  • Best practice: create one root “sorting” group per type, and place all groups of that type under it. For example, create jobtitles with group_type: "sorting" and set all group_type: "jobtitle" groups to have parent_identifier: "jobtitles" and parent_type: "sorting" (see the Python example, step 2).

  • Group identifiers are matched exactly. If the group does not exist yet, create it first using the groups bulk import endpoint (see the Python example below, step 2).

  • A user can be in multiple groups (for example one job title and one city).


🧪 Example usage (Python)

import requests

base_url = "https://yourname.platform.co.nl"
client_id = "put your client id here"
client_secret = "put your secret here"

Step 1. Authenticate

token_payload = {
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"scope": "write.users write.groups",
}
token_response = requests.post(f"{base_url}/o/token/", data=token_payload).json()
token = token_response["access_token"]
headers = {"Authorization": f"Bearer {token}"}

Step 2. Create or update groups

groups_payload = {
"groups": [
{
"group_identifier": "jobtitles",
"group_type": "sorting",
"name": "Job Titles"
},
{
"group_identifier": "cities",
"group_type": "sorting",
"name": "Cities"
},
{
"group_identifier": "manager",
"group_type": "jobtitle",
"name": "Manager",
"parent_identifier": "jobtitles",
"parent_type": "sorting"
},
{
"group_identifier": "sales_associate",
"group_type": "jobtitle",
"name": "Sales Associate",
"parent_identifier": "jobtitles",
"parent_type": "sorting"
},
{
"group_identifier": "amsterdam",
"group_type": "city",
"name": "Amsterdam",
"parent_identifier": "cities",
"parent_type": "sorting"
}
]
}

groups_response = requests.post(
f"{base_url}/api/groups/tree-group/bulk_import/",
json=groups_payload,
headers=headers,
).json()

Step 3. Import users

# Note: The manager (EMP-001) must be listed before users that reference them 

users_payload = {
"users": [
{
"user_identifier": "EMP-001",
"first_name": "Sarah",
"last_name": "Johnson",
"email": "sarah.johnson@example.com",
"groups": [
{"group_identifier": "manager", "group_type": "jobtitle"},
{"group_identifier": "amsterdam", "group_type": "city"}
],
"country": "NL",
"language": "en",
"status": "active"
},
{
"user_identifier": "EMP-123",
"first_name": "Alex",
"last_name": "Nguyen",
"email": "alex@example.com",
"groups": [
{"group_identifier": "sales_associate", "group_type": "jobtitle"},
{"group_identifier": "amsterdam", "group_type": "city"}
],
"contract_start_at": "2026-01-01",
"contract_end_at": "2026-12-31",
"country": "NL",
"manager_identifier": "EMP-001",
"language": "en",
"uses_single_signon": False,
"status": "active"
}
]
}

users_response = requests.post(
f"{base_url}/api/accounts/user/bulk_import/",
json=users_payload,
headers=headers,
).json()

Did this answer your question?