API methods - service accounts
A service account is a non-human identity used for machine-to-machine (M2M) access. It holds the roles, permissions, groups, organisations and attributes that are encoded into the access token issued to a confidential client that has been linked to it.
A confidential client on its own only authenticates the calling application — it is the linked service account that gives the issued token its identity and authority. A service account may be linked to more than one client, but a client may be linked to at most one service account.
Service accounts can also be created at startup from seed data. Unlike client seed data, service account seed data is matched by id and updated in place, so by default changes made through this API to a service account that is also declared in seed data are overwritten the next time the Auth Server restarts. Enable bootstrap.seedOnce to preserve them.
Permissions
| API method | Endpoint | Required permission |
|---|---|---|
Get service accounts | GET /service-accounts | users.read |
Get service account by ID | GET /service-accounts/{serviceAccountId} | users.read |
Create a service account | POST /service-accounts | users.write |
Update a service account | PUT /service-accounts/{serviceAccountId} | users.write |
Delete a service account | DELETE /service-accounts/{serviceAccountId} | users.write |
Enable a service account | POST /service-accounts/{serviceAccountId}/enable | users.write |
Disable a service account | POST /service-accounts/{serviceAccountId}/disable | users.write |
Link a client to a service account | PUT /service-accounts/{serviceAccountId}/clients/{clientId} | client.write |
Unlink a client from a service account | DELETE /service-accounts/{serviceAccountId}/clients/{clientId} | client.write |
Note that the two linking endpoints require client.write, which is held by the ADMIN_SYSTEM role, rather than the users.write permission held by ADMIN_USER that the other endpoints require. Further information can be found on the Roles and Permissions page.
A request made without the required permission returns 403 Forbidden with no response body.
Get service accounts
To access this endpoint you must have users.read permission.
GET /service-accounts
This endpoint does not provide the same level of detail for service accounts as the Get service account by ID endpoint.
Query parameters:
| Parameter | Default | Description |
|---|---|---|
status | — | Filter by status. ACTIVE or INACTIVE, case-insensitive. Any other value is ignored and all service accounts are returned. |
name | — | Filter to service accounts whose name contains this value, case-insensitive. |
clientId | — | Return the single service account linked to this client_id. When supplied, status and name are ignored, and an empty list is returned if no service account is linked to the client. |
page | 0 | Zero-based page number. |
size | 50 | Page size. Must be between 1 and 100. |
sort | created-at | Field to sort by. name or created-at. Unrecognised values fall back to created-at. |
order | asc | Sort direction. asc or desc. Unrecognised values fall back to asc. |
For example, GET /service-accounts?status=ACTIVE&sort=name&order=desc&size=20.
Responses:
Status: 200 - a summary of the matching service accounts returned
Response body example:
{ "count": 1, "page": 0, "size": 50, "totalPages": 1, "hasNext": false, "serviceAccounts": [ { "id": "4b6f1d2e-83a1-4e0b-9f7c-1d2a3b4c5d6e", "name": "svc-my-service", "description": "Service account for My Service", "active": true } ] }
count is the total number of matching service accounts, not the number returned on this page.
Status: 400 - invalid pagination
{ "error": "invalid_request", "error_description": "page must be non-negative and size must be between 1 and 100" }
Get service account by ID
To access this endpoint you must have users.read permission.
GET /service-accounts/{serviceAccountId}
Responses:
Status: 200 - service account returned
Response body example:
{ "id": "4b6f1d2e-83a1-4e0b-9f7c-1d2a3b4c5d6e", "name": "svc-my-service", "description": "Service account for My Service", "active": true, "createdAt": "2025-11-19T12:23:02.209370", "updatedAt": "2025-11-21T12:12:44.257464", "attributes": { "permitted_nationalities": ["GBR"] }, "rolesList": [ { "id": "33118966-7462-4f99-beb5-39943b2e303b", "name": "USER", "description": "Standard user of the platform with data access to apps and APIs", "priority": 100, "active": true, "systemRole": false, "createdAt": "2025-11-19T12:09:26.401003", "updatedAt": "2025-11-19T12:09:26.401008" } ], "permissionsList": [ { "id": "4477e79e-b368-46fc-9ac8-68cf4af52bdf", "name": "api.knowledge.read", "description": "Read from the knowledge dataset ", "resource": "core", "action": "read", "active": true, "createdAt": "2025-11-19T12:09:26.400427", "updatedAt": "2025-11-19T12:09:26.400444" } ], "groupsList": [ { "id": "9e815e51-e0ea-47c6-ab35-2cb312f8ee70", "urn": "urn:telicent:groups:admin", "name": "admin", "description": "Administrator group", "active": true } ], "organisationsList": [ { "id": "0f2d1c8e-5b3a-4c52-9d0b-7a6f2b1e4c93", "name": "Telicent", "countryOfRegistration": "GBR" } ] }
Status: 404 - service account not found
Create a service account
To access this endpoint you must have users.write permission.
POST /service-accounts
Request body example:
{ "name": "svc-my-service", "description": "Service account for My Service", "active": true, "roles": ["33118966-7462-4f99-beb5-39943b2e303b"], "permissions": ["4477e79e-b368-46fc-9ac8-68cf4af52bdf"], "groups": ["9e815e51-e0ea-47c6-ab35-2cb312f8ee70"], "organisations": ["0f2d1c8e-5b3a-4c52-9d0b-7a6f2b1e4c93"], "attributes": { "permitted_nationalities": ["GBR"] }, "clientId": "my-service" }
| Field | Required | Description |
|---|---|---|
name | Yes | The name of the service account. Must be unique. |
description | No | A description of the service account. Defaults to an empty string. |
active | No | Whether the service account is active. Defaults to true. |
roles | No | IDs of the roles assigned to the service account. Assigning roles also assigns their default permissions. |
permissions | No | IDs of the permissions assigned to the service account. Permissions may only be assigned alongside roles — see below. |
groups | No | IDs of the groups the service account belongs to. |
organisations | No | IDs of the organisations the service account is assigned to. Each organisation must already exist. |
attributes | No | Attributes held against the service account, encoded into its issued tokens. |
clientId | No | The client_id of a confidential client to link to the service account on creation. The client must already exist and be eligible for linking. |
Roles and permissions
Setting roles assigns the default permissions of those roles. Any permission listed in permissions that is not a default permission of the assigned roles must still be aligned with one of them — a permission outside the assigned roles is rejected. Sending permissions without roles is also rejected.
Responses:
Status: 200 - service account created and returned
The response body is the same as that of the Get service account by ID endpoint.
Status: 400 - invalid request
Returned with no response body when the name is missing, when permissions are supplied without roles, when a permission falls outside the assigned roles, when an organisation does not exist, or when a clientId was supplied and the client could not be linked.
Status: 409 - a service account with this name already exists
Returned with no response body.
Update a service account
To access this endpoint you must have users.write permission.
PUT /service-accounts/{serviceAccountId}
Request body example:
{ "description": "Service account for My Service (updated)", "active": false }
Only the values to be updated need to be sent in the request. The fields are those of the create request, except that clientId cannot be set here — use the linking endpoints instead.
Note the following behaviour:
attributesis merged into the existing attributes. Attributes present in the request replace those of the same name; attributes not mentioned in the request are left as they are.roles,permissions,groupsandorganisationseach replace the current values in full when supplied.- Supplying
rolesresets the service account’s permissions to the default permissions of those roles before anypermissionsin the same request are applied. - A blank or absent
nameleaves the existing name unchanged.
Responses:
Status: 200 - service account updated and returned
The response body is the same as that of the Get service account by ID endpoint.
Status: 400 - invalid request
Returned with no response body when the new name is already in use by another service account, when permissions are supplied without roles, when a permission falls outside the assigned roles, or when an organisation does not exist.
Status: 404 - service account not found
Link a client to a service account
To access this endpoint you must have client.write permission.
PUT /service-accounts/{serviceAccountId}/clients/{clientId}
The client must be a confidential client that supports the client_credentials grant. A client that is already linked to another service account is relinked to this one.
Responses:
Status: 204 - client linked to the service account
Status: 400 - client is not eligible for linking
Returned when the client does not support the client_credentials grant or is not a confidential client.
Status: 404 - client or service account not found
Unlink a client from a service account
To access this endpoint you must have client.write permission.
DELETE /service-accounts/{serviceAccountId}/clients/{clientId}
The link is removed from the client, which will no longer be issued tokens carrying a service account identity. The service account itself is not deleted.
Responses:
Status: 204 - client unlinked
Status: 404 - client not found
Delete a service account
To access this endpoint you must have users.write permission.
DELETE /service-accounts/{serviceAccountId}
Any clients linked to the service account are unlinked before it is deleted. Those clients continue to exist and can still authenticate, but will no longer be issued tokens carrying a service account identity until they are linked to another service account.
Responses:
Status: 204 - service account deleted
Status: 404 - service account not found
Enable a service account
To access this endpoint you must have users.write permission.
POST /service-accounts/{serviceAccountId}/enable
Responses:
Status: 204 - service account enabled
Status: 404 - service account not found
Disable a service account
To access this endpoint you must have users.write permission.
POST /service-accounts/{serviceAccountId}/disable
Responses:
Status: 204 - service account disabled
Status: 404 - service account not found