User Management
This guide covers how to create and manage users on an Amili account. It applies to both partner platforms (after completing account setup via the Partner Onboarding guide) and direct account customers whose accounts are set up directly by Amili.
This guide uses the AuthTokenProvider for authentication in examples — see the Authentication guide for setup details.
Access Groups
Access groups control what a user can see and do within Amili. They are created automatically — account-level groups are generated when the account is created, and creditor-level groups are generated each time a creditor is created.
There are three access group types relevant to user management:
| Type | Scope | Description |
|---|---|---|
account_admin | Account | Full access across all creditors on the account. Can manage users, settings, and creditor configuration for the entire account. |
admin | Creditor | Can manage users and settings for a specific creditor. |
user | Creditor | Can handle cases and day-to-day operations for a specific creditor. |
A user can be assigned to multiple access groups — for example, a user who handles cases for more than one creditor can hold a user role on each.
Finding Access Groups
Before creating users you need the IDs of the relevant access groups. Query GET /access--groups filtered by account to retrieve all groups associated with an account:
const accountId = '674dbeaf08847b9501cc9132'
const token = await auth.getValidToken()
const where = encodeURIComponent(JSON.stringify({ account: accountId }))
const response = await axios.get(
`https://api-sandbox.amili.se/access--groups?where=${where}`,
{ headers: { 'X-API-Key': token } }
)
const accessGroups = response.data._itemsimport json
account_id = '674dbeaf08847b9501cc9132'
token = auth.get_valid_token()
where = json.dumps({'account': account_id})
response = requests.get(
'https://api-sandbox.amili.se/access--groups',
params={'where': where},
headers={'X-API-Key': token},
)
response.raise_for_status()
access_groups = response.json()['_items']Example response (abbreviated):
{
"_items": [
{
"_id": "674dbec008847b9501cc9140",
"account": "674dbeaf08847b9501cc9132",
"type": "account_admin",
"name": "account_admin"
},
{
"_id": "674dbec008847b9501cc9141",
"account": "674dbeaf08847b9501cc9132",
"creditor": "674dbeb208847b9501cc9138",
"type": "admin",
"name": "admin",
"creditor_name": "Exempel Företag AB"
},
{
"_id": "674dbec008847b9501cc9142",
"account": "674dbeaf08847b9501cc9132",
"creditor": "674dbeb208847b9501cc9138",
"type": "user",
"name": "user",
"creditor_name": "Exempel Företag AB"
}
]
}To find a specific group, add type and optionally creditor to the filter:
// Account-level group
{ account: accountId, type: 'account_admin' }
// Creditor-level groups for a specific creditor
{ account: accountId, creditor: creditorId, type: 'user' }Creating Users
Users authenticate via OAuth. Provide oauth_type ("google" or "microsoft") and email_oauth to identify the user's identity provider account. Access is granted by adding one or more access group IDs to the data_access array.
Account Admin User
An account admin has full access across all creditors on the account. This is the appropriate role for a client user who needs to manage the account or complete onboarding in the Amili App.
const token = await auth.getValidToken()
const userResponse = await axios.post(
'https://api-sandbox.amili.se/users',
{
account: '674dbeaf08847b9501cc9132',
name: 'Anna Andersson',
email_data: { email: 'anna.andersson@example.com' },
is_enabled: true,
oauth_type: 'google',
email_oauth: 'anna.andersson@example.com',
data_access: [
{ access_group: '674dbec008847b9501cc9140' }, // type: account_admin
],
},
{ headers: { 'X-API-Key': token, 'Content-Type': 'application/json' } }
)token = auth.get_valid_token()
headers = {'X-API-Key': token, 'Content-Type': 'application/json'}
user_response = requests.post(
'https://api-sandbox.amili.se/users',
json={
'account': '674dbeaf08847b9501cc9132',
'name': 'Anna Andersson',
'email_data': {'email': 'anna.andersson@example.com'},
'is_enabled': True,
'oauth_type': 'google',
'email_oauth': 'anna.andersson@example.com',
'data_access': [
{'access_group': '674dbec008847b9501cc9140'}, # type: account_admin
],
},
headers=headers,
)
user_response.raise_for_status()Creditor Admin User
A creditor admin can manage users and settings for a specific creditor. Use the admin access group ID for the relevant creditor.
const token = await auth.getValidToken()
const userResponse = await axios.post(
'https://api-sandbox.amili.se/users',
{
account: '674dbeaf08847b9501cc9132',
name: 'Erik Eriksson',
email_data: { email: 'erik.eriksson@example.com' },
is_enabled: true,
oauth_type: 'microsoft',
email_oauth: 'erik.eriksson@example.com',
data_access: [
{ access_group: '674dbec008847b9501cc9141' }, // type: admin, creditor: Exempel Företag AB
],
},
{ headers: { 'X-API-Key': token, 'Content-Type': 'application/json' } }
)token = auth.get_valid_token()
headers = {'X-API-Key': token, 'Content-Type': 'application/json'}
user_response = requests.post(
'https://api-sandbox.amili.se/users',
json={
'account': '674dbeaf08847b9501cc9132',
'name': 'Erik Eriksson',
'email_data': {'email': 'erik.eriksson@example.com'},
'is_enabled': True,
'oauth_type': 'microsoft',
'email_oauth': 'erik.eriksson@example.com',
'data_access': [
{'access_group': '674dbec008847b9501cc9141'}, # type: admin, creditor: Exempel Företag AB
],
},
headers=headers,
)
user_response.raise_for_status()Creditor User
A creditor user can handle cases and day-to-day operations for a creditor. A user can be assigned to multiple creditors by including a user access group for each in the data_access array.
const token = await auth.getValidToken()
const userResponse = await axios.post(
'https://api-sandbox.amili.se/users',
{
account: '674dbeaf08847b9501cc9132',
name: 'Maria Svensson',
email_data: { email: 'maria.svensson@example.com' },
is_enabled: true,
oauth_type: 'google',
email_oauth: 'maria.svensson@example.com',
data_access: [
{ access_group: '674dbec008847b9501cc9142' }, // type: user, creditor: Exempel Företag AB
{ access_group: '674dbec008847b9501cc9143' }, // type: user, creditor: Annat Företag AB
],
},
{ headers: { 'X-API-Key': token, 'Content-Type': 'application/json' } }
)token = auth.get_valid_token()
headers = {'X-API-Key': token, 'Content-Type': 'application/json'}
user_response = requests.post(
'https://api-sandbox.amili.se/users',
json={
'account': '674dbeaf08847b9501cc9132',
'name': 'Maria Svensson',
'email_data': {'email': 'maria.svensson@example.com'},
'is_enabled': True,
'oauth_type': 'google',
'email_oauth': 'maria.svensson@example.com',
'data_access': [
{'access_group': '674dbec008847b9501cc9142'}, # type: user, creditor: Exempel Företag AB
{'access_group': '674dbec008847b9501cc9143'}, # type: user, creditor: Annat Företag AB
],
},
headers=headers,
)
user_response.raise_for_status()Example response (same structure for all user types):
{
"_id": "674dbef008847b9501cc9150",
"_created": "Tue, 07 Oct 2025 08:00:00 GMT",
"_updated": "Tue, 07 Oct 2025 08:00:00 GMT",
"_etag": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0",
"_status": "OK"
}Managing Users
All update operations use PATCH /users/{userId} and require an If-Match header containing the user's current _etag value. Retrieve the user first to obtain both the current state and the _etag.
Disabling a User
Set is_enabled: false to prevent a user from logging in without deleting their account. This is reversible — set is_enabled: true to restore access.
const userId = '674dbef008847b9501cc9150'
const token = await auth.getValidToken()
// Retrieve the user to get the current _etag
const userResponse = await axios.get(
`https://api-sandbox.amili.se/users/${userId}`,
{ headers: { 'X-API-Key': token } }
)
const etag = userResponse.data._etag
// Disable the user
await axios.patch(
`https://api-sandbox.amili.se/users/${userId}`,
{ is_enabled: false },
{
headers: {
'X-API-Key': token,
'Content-Type': 'application/json',
'If-Match': etag,
},
}
)user_id = '674dbef008847b9501cc9150'
token = auth.get_valid_token()
headers = {'X-API-Key': token, 'Content-Type': 'application/json'}
# Retrieve the user to get the current _etag
user_response = requests.get(
f'https://api-sandbox.amili.se/users/{user_id}',
headers={'X-API-Key': token},
)
user_response.raise_for_status()
etag = user_response.json()['_etag']
# Disable the user
patch_response = requests.patch(
f'https://api-sandbox.amili.se/users/{user_id}',
json={'is_enabled': False},
headers={**headers, 'If-Match': etag},
)
patch_response.raise_for_status()Removing Access
To revoke a user's access to one or more creditors, fetch the current data_access array, remove the relevant entries, and PATCH with the updated array. All read-only cascade fields (access_group_name, access_group_type, etc.) should be omitted — they are managed by the system.
const userId = '674dbef008847b9501cc9150'
const accessGroupToRemove = '674dbec008847b9501cc9143' // creditor to revoke
const token = await auth.getValidToken()
// Retrieve the user to get the current data_access and _etag
const userResponse = await axios.get(
`https://api-sandbox.amili.se/users/${userId}`,
{ headers: { 'X-API-Key': token } }
)
const { _etag, data_access } = userResponse.data
// Remove the entry for the access group to revoke
const updatedDataAccess = data_access
.filter(
(entry: { access_group: string }) =>
entry.access_group !== accessGroupToRemove
)
.map((entry: { access_group: string }) => ({
access_group: entry.access_group,
}))
await axios.patch(
`https://api-sandbox.amili.se/users/${userId}`,
{ data_access: updatedDataAccess },
{
headers: {
'X-API-Key': token,
'Content-Type': 'application/json',
'If-Match': _etag,
},
}
)user_id = '674dbef008847b9501cc9150'
access_group_to_remove = '674dbec008847b9501cc9143' # creditor to revoke
token = auth.get_valid_token()
headers = {'X-API-Key': token, 'Content-Type': 'application/json'}
# Retrieve the user to get the current data_access and _etag
user_response = requests.get(
f'https://api-sandbox.amili.se/users/{user_id}',
headers={'X-API-Key': token},
)
user_response.raise_for_status()
user = user_response.json()
# Remove the entry for the access group to revoke
updated_data_access = [
{'access_group': entry['access_group']}
for entry in user['data_access']
if entry['access_group'] != access_group_to_remove
]
patch_response = requests.patch(
f'https://api-sandbox.amili.se/users/{user_id}',
json={'data_access': updated_data_access},
headers={**headers, 'If-Match': user['_etag']},
)
patch_response.raise_for_status()Next Steps
- Partner Onboarding — Full account and creditor provisioning flow
- Case Flow Examples — Register cases against a creditor
- Invoice Flow Examples — Register invoices for a creditor
- Users Endpoint — Complete API reference for user management
- Access Group Endpoint — Full access group reference
