Skip to content

Authentication

Service Accounts authenticate with the standard OAuth 2.0 client credentials grant (RFC 6749 section 4.4). Exchange the account's credentials for an access token, then send that token as a Bearer token on all subsequent API calls. Any standard OAuth 2.0 client library can be used with the token URL /api/v1/service-account/auth.

Obtaining an Access Token

Send the credentials using HTTP Basic authentication (recommended):

POST /api/v1/service-account/auth
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(client_id:client_secret)>

grant_type=client_credentials

Or send them in the request body:

POST /api/v1/service-account/auth
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=svc_abc123def456ghi789jkl012mno345pq&client_secret=your-64-char-secret-here
Parameter Required Description
grant_type Yes Must be client_credentials
client_id Unless using HTTP Basic The svc_-prefixed client identifier
client_secret Unless using HTTP Basic The plaintext secret (shown once at creation or regeneration)
scope No Space-delimited scopes. Each must already be granted to the account

Use only one of HTTP Basic or body credentials per request. A JSON request body is also accepted.

Example with curl:

curl -s -u 'svc_abc123...:your-64-char-secret-here' \
  -d grant_type=client_credentials \
  https://<your-zaita-host>/api/v1/service-account/auth

Success response (200 OK):

{
  "access_token": "64-char-alphanumeric-session-token",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "policies:write couriers:read"
}

The response is sent with Cache-Control: no-store. Do not cache or log the token outside your secrets handling.

Access tokens are valid for 24 hours (expires_in is in seconds). No refresh token is issued; request a new token when it expires. The token always carries all the scopes granted to the account. Use the returned token as a Bearer token on all subsequent API calls:

Authorization: Bearer <access_token>

To find the account's UUID, name or absolute expiry time, call Verify.

Authentication Errors

Errors follow the OAuth 2.0 format:

{
  "error": "invalid_client",
  "error_description": "Invalid credentials"
}
HTTP error Condition
400 invalid_request grant_type missing, or both HTTP Basic and body credentials were sent
400 unsupported_grant_type grant_type is not client_credentials
400 invalid_scope A requested scope is not granted to the account
401 invalid_client Unknown client_id, incorrect secret, account inactive or expired, or IP not in the allowlist

error_description explains invalid_client failures: "Invalid credentials", "Service account is inactive", "Service account has expired" or "IP address not allowed". Unknown client IDs and incorrect secrets both return "Invalid credentials" so the response does not reveal which value was wrong.

Verifying a Session

GET /api/v1/service-account/auth/verify
Authorization: Bearer <access_token>

Returns the current session state and confirms the service account is still active. Use this endpoint to check whether a cached token is still valid before making API calls.

If the account has been deactivated or deleted after the session was created, the session is immediately invalidated and 401 SERVICE_ACCOUNT_INACTIVE is returned.

Revoking a Session

POST /api/v1/service-account/auth/revoke
Authorization: Bearer <access_token>

Immediately invalidates the session token. Call this endpoint at the end of a pipeline run or automated job to limit the window of exposure for the token.

Session Lifecycle

Credentials → POST /auth → Session token (24h TTL)
                                  ↓
                    Use as Bearer token on API calls
                                  ↓
                    POST /auth/revoke (optional, ends session early)

Sessions are stored server-side. The token itself contains no claims — its validity is verified on each request against the server-side session store. If the service account is disabled or deleted, all of its sessions are invalidated immediately regardless of their remaining TTL.