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:

  • attributes is 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, groups and organisations each replace the current values in full when supplied.
  • Supplying roles resets the service account’s permissions to the default permissions of those roles before any permissions in the same request are applied.
  • A blank or absent name leaves 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

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

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


[EARLY DRAFT RELEASE] Copyright 2020-2026 Telicent Limited. All rights reserved