Service account API reference

Use the following REST API endpoints, field definitions, and error codes to manage service accounts and authenticate with the client credentials grant flow.

Service account endpoints

All service account management endpoints are under /api/v1/service_accounts. Project scoping is enforced through the project_id field in the request body (for creation) and visibility filters (for listing).

Table 1. Service account endpoints
Method Path Description
POST /api/v1/service_accounts Create a service account.
GET /api/v1/service_accounts List service accounts. Supports pagination and filtering. Results are scoped to projects visible to the authenticated user.
GET /api/v1/service_accounts/{service_account_id} Get details for a specific service account.
PATCH /api/v1/service_accounts/{service_account_id} Update name or description. Theproject_id field is immutable after creation.
DELETE /api/v1/service_accounts/{service_account_id} Delete a service account. Tokens issued to the account are rejected.
POST /api/v1/service_accounts/{service_account_id}/enable Set the service account status toactive.
POST /api/v1/service_accounts/{service_account_id}/disable Set the service account status todisabled. Tokens are rejected while disabled.

Create request body

{
  "name": "CI Pipeline",
  "description": "Service account for Jenkins CI integration",
  "project_id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}
Table 2. Create request body fields
Field Type Required Description
name string Yes Human-readable name. Maximum 255 characters.
description string No Purpose or context for the service account. Maximum 2000 characters.
project_id UUID Yes UUID of the project that owns this service account.

Labels are not accepted in the create request. To add labels to a service account, use the PATCH endpoint after creation.

Create response body

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "CI Pipeline",
  "description": "Service account for Jenkins CI integration",
  "status": "active",
  "project_id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
  "last_authenticated_at": null,
  "created_by": "12345678-abcd-efab-cdef-1234567890ab",
  "created_at": "2026-07-02T14:30:00Z",
  "updated_at": "2026-07-02T14:30:00Z",
  "labels": {}
}

The create response does not include credentials. To generate a client ID and client secret, create a credential as a separate step. For more information, see Create a service account.

Credential endpoints

Credentials are sub-resources of service accounts. Each service account can have up to 10 credentials.

Table 3. Credential endpoints
Method Path Description
POST /api/v1/service_accounts/{sa_id}/credentials Create a credential. Returns the one-time plain text client secret (201).
GET /api/v1/service_accounts/{sa_id}/credentials List credentials for a service account. Supports pagination.
GET /api/v1/service_accounts/{sa_id}/credentials/{cred_id} Get details for a specific credential.
DELETE /api/v1/service_accounts/{sa_id}/credentials/{cred_id} Delete a credential (204).
POST /api/v1/service_accounts/{sa_id}/credentials/{cred_id}/rotate Rotate the secret. Returns the new plain text secret once.
POST /api/v1/service_accounts/{sa_id}/credentials/{cred_id}/enable Set the credential status toactive.
POST /api/v1/service_accounts/{sa_id}/credentials/{cred_id}/disable Disable the credential.

Credential create request body

{
  "credential_type": "client_credentials",
  "expires_at": "2027-01-02T14:31:00Z"
}
Table 4. Credential create request body fields
Field Type Required Description
credential_type string Yes Type of credential. Onlyclient_credentials is supported.
expires_at datetime (ISO 8601 with timezone) No Custom expiration timestamp. If omitted, auto-set from the configured maximum credential lifetime. Rejected if it exceeds the configured limit or is in the past.
grace_period_seconds integer (0--86400) No Duration in seconds that the old secret remains valid after rotation. Default:3600.

Credential create response body

{
  "id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "service_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "credential_type": "client_credentials",
  "identifier": "nx_sa_7kx9m2p4q1w3n5v8",
  "client_secret": "generated-plaintext-secret",
  "status": "active",
  "grace_period_seconds": 3600,
  "expires_at": "2026-12-29T14:31:00Z",
  "old_secret_valid_until": null,
  "last_used_at": null,
  "created_by": "12345678-abcd-efab-cdef-1234567890ab",
  "created_at": "2026-07-02T14:31:00Z"
}
Warning:

The client_secret field is included only in the credential create response and in the secret rotation response. It is not returned by any other endpoint. Record the secret immediately.

Grace period behavior

When you rotate a credential's secret, both the old and new secrets are accepted during a configurable grace period. This prevents downtime when multiple consumers need time to update their credentials.

The default grace period is 3600 seconds (1 hour). You can override the grace period per rotation by including grace_period_seconds in the rotate request body. This field accepts values from 0 to 86400 seconds (24 hours). Setting the grace period to 0 means the old secret is rejected immediately after rotation.

Token endpoint

Table 5. Token endpoint
Method Path Description
POST /api/v1/auth/token Exchange client credentials for a JWT access token.

Token request

The token endpoint accepts application/x-www-form-urlencoded requests with the following parameters:

Table 6. Token request parameters
Parameter Required Description
grant_type Yes Must beclient_credentials.
client_id Yes The credential'sidentifier value (client ID). Required when not using HTTP Basic authentication.
client_secret Yes The credential's client secret. Required when not using HTTP Basic authentication.

Alternatively, you can provide the client_id and client_secret by using HTTP Basic authentication (RFC 6749 section 2.3.1). Encode the credentials as client_id:client_secret in Base64 and pass them in the Authorization header.

Token response

{
  "access_token": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6Im5leHVzLTEifQ...",
  "token_type": "Bearer",
  "expires_in": 900
}
Table 7. Token response fields
Field Type Description
access_token string ES256-signed JWT access token.
token_type string AlwaysBearer.
expires_in integer Token lifetime in seconds. The default is 900 seconds (15 minutes). The administrator can configure this value between 1 and 60 minutes.

No refresh token is issued. When the access token expires, request a new one by repeating the client credentials grant flow.

ServiceAccount fields

Table 8. ServiceAccount fields
Field Type Description
id UUID Automatically generated primary key. Also the principal ID in theprincipals table.
name string (max 255) Human-readable name.
description string (max 2000) Optional description.
status string Operational status:active ordisabled.
project_id UUID UUID of the owning project.
last_authenticated_at datetime ornull Timestamp of the most recent successful authentication.
created_by UUID UUID of the user who created the service account.
updated_by UUID ornull UUID of the user who last modified the service account.
created_at datetime Creation timestamp.
updated_at datetime Last modification timestamp.
labels object Key-value metadata. Both keys and values must be strings.

ServiceAccountStatus values

Table 9. ServiceAccountStatus values
Value Description
active The service account can authenticate and access resources.
disabled The service account cannot authenticate. Existing tokens are rejected.

ServiceAccountCredential fields

Table 10. ServiceAccountCredential fields
Field Type Description
id UUID Automatically generated primary key.
service_account_id UUID UUID of the parent service account.
credential_type string Type of credential:client_credentials.
identifier string (max 64, unique) Public client ID. Uses thenx_sa_ prefix, for examplenx_sa_7kx9m2p4q1w3n5v8.
old_secret_valid_until datetime ornull When the previous secret stops being accepted.
grace_period_seconds integer (0--86400) Duration in seconds that the old secret remains valid after rotation. Default:3600.
status string Operational status:active ordisabled.
expires_at datetime ornull Credential expiry timestamp. Auto-set from the configured maximum credential lifetime if not specified at creation. Reset to a new full lifetime on rotation.
last_used_at datetime ornull Timestamp of last use.
created_by UUID UUID of the user who created the credential.
updated_by UUID ornull UUID of the user who last modified the credential.
created_at datetime Creation timestamp.
updated_at datetime Last modification timestamp.

Access token JWT claims

Service account access tokens include the following claims:

Table 11. Service account JWT claims
Claim Type Description
sub string Service account UUID.
iss string Automation orchestrator server URL (same issuer as human tokens).
iat integer Issued-at timestamp (UNIX epoch seconds).
exp integer Expiration timestamp (UNIX epoch seconds).
token_type string Set toservice_account to distinguish from human user tokens.
preferred_username string Service account name.
aud string Token audience, for exampleorchestrator-api.
token_ver integer Token version, used for per-account revocation.
cred_id string ornull UUID of the credential used to obtain this token. Used for per-credential token revocation.
groups array Always empty for service accounts (service accounts do not support group membership).

Error responses

All error responses use the application/problem+json format (RFC 9457).

Token endpoint errors

Table 12. Token endpoint error codes
HTTP status Error code Condition
401 AUTHENTICATION_REQUIRED Unknown client ID, incorrect secret, disabled account, or deleted account. The error is generic to prevent client ID enumeration.

Management endpoint errors

Table 13. Management endpoint error codes
HTTP status Error code Condition
400 Invalid request body (validation error).
400 CREDENTIAL_EXPIRATION_EXCEEDED The requestedexpires_at exceeds the configured maximum credential lifetime.
400 CREDENTIAL_EXPIRATION_IN_PAST The requestedexpires_at is in the past.
401 Missing or invalid authentication credentials.
403 Insufficient permissions for the requested action.
404 Service account or project not found.
409 SERVICE_ACCOUNT_NAME_CONFLICT A service account with the same name already exists in the project.
409 SERVICE_ACCOUNT_CREDENTIAL_LIMIT The service account has reached the maximum of 10 credentials.
422 Request body fails schema validation.