Skip to content

API reference — OAuth client management

OAuth M2M (machine-to-machine) clients enable server-side applications to authenticate to Arbitex using the OAuth 2.0 client credentials grant. Each client has a client_id and client_secret pair. Secrets are generated at creation time, returned once in plaintext, and stored only as SHA-256 hashes — they cannot be retrieved after creation.

All endpoints are admin-only. Authentication: Authorization: Bearer arb_live_<admin-key>.

Base path: /api/v1/admin/oauth-clients

For the token issuance endpoint (POST /oauth/token) used by clients at runtime, see OAuth M2M API guide.


Returned by all endpoints except create. Does not include the client secret.

Field Type Description
id UUID Internal record identifier
client_id UUID Public-facing OAuth client ID (used in token requests)
name string Display name for the client application
scopes string[] Granted OAuth scope strings
tenant_id UUID | null Owning tenant UUID (multi-tenant isolation)
created_by UUID | null Admin user UUID who created the record
enabled boolean Whether the client can authenticate
rate_limit_tier string Rate-limit policy: standard, premium, or unlimited
token_lifetime_seconds integer Access token TTL in seconds (max: 86400)
created_at datetime ISO 8601 creation timestamp
last_used datetime | null Timestamp of most recent token issuance

Extends OAuthClientResponse with the plaintext secret — returned only at creation time.

Field Type Description
client_secret string Plaintext client secret. Store immediately — not retrievable again.
(all OAuthClientResponse fields)

Returned by the secret rotation endpoint.

Field Type Description
client_id UUID Public-facing client ID
new_client_secret string New plaintext secret. Store immediately — not retrievable again.
grace_period_seconds integer Seconds the old secret remains valid after rotation
previous_secret_expires_at datetime When the old secret will be rejected

GET /api/v1/admin/oauth-clients/

Returns all registered OAuth M2M clients, ordered by created_at descending.

Query parameters:

Parameter Type Default Description
limit integer 50 Records to return (1–500)
offset integer 0 Number of records to skip

Request:

Terminal window
GET /api/v1/admin/oauth-clients/?limit=50&offset=0
Authorization: Bearer arb_live_your-admin-key

Response (200):

Returns a flat JSON array of OAuthClientResponse objects:

[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "CI/CD Pipeline",
"scopes": ["chat:write", "audit:read"],
"tenant_id": null,
"created_by": "7c8d9e0f-...",
"enabled": true,
"rate_limit_tier": "standard",
"token_lifetime_seconds": 3600,
"created_at": "2026-03-01T00:00:00Z",
"last_used": "2026-03-12T13:58:00Z"
}
]

POST /api/v1/admin/oauth-clients/

Creates a new M2M client registration. Returns the client record with the plaintext secret (client_secret). The secret is not stored and cannot be retrieved again — copy it immediately.

Request body:

Field Required Default Description
name Yes Display name (1–255 characters)
scopes No [] List of OAuth scope strings to grant
tenant_id No null Tenant UUID for multi-tenant isolation
rate_limit_tier No standard standard, premium, or unlimited
token_lifetime_seconds No 3600 Token TTL in seconds (1–86400)

Request:

Terminal window
POST /api/v1/admin/oauth-clients/
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"name": "CI/CD Pipeline",
"scopes": ["chat:write", "audit:read"],
"rate_limit_tier": "standard",
"token_lifetime_seconds": 3600
}

Response (201 Created):

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"client_secret": "Xk4mPz9rJqNv...(48 chars, URL-safe base64)",
"name": "CI/CD Pipeline",
"scopes": ["chat:write", "audit:read"],
"tenant_id": null,
"created_by": "admin-uuid",
"enabled": true,
"rate_limit_tier": "standard",
"token_lifetime_seconds": 3600,
"created_at": "2026-03-12T14:00:00Z",
"last_used": null
}

Error (422 Unprocessable Entity):

{ "detail": "Invalid rate_limit_tier 'gold'. Must be one of: premium, standard, unlimited" }

GET /api/v1/admin/oauth-clients/{client_id}

Where client_id is the public-facing OAuth client UUID (the client_id field, not id).

Response (200): Returns the OAuthClientResponse object (no secret).

Error (404 Not Found):

{ "detail": "OAuth client not found" }

PUT /api/v1/admin/oauth-clients/{client_id}

Only non-null fields in the request body are applied. Fields omitted or set to null are left unchanged.

Updatable fields: name, scopes, enabled, rate_limit_tier, token_lifetime_seconds.

Disable a client:

Terminal window
PUT /api/v1/admin/oauth-clients/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{ "enabled": false }

Update scopes:

Terminal window
PUT /api/v1/admin/oauth-clients/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer arb_live_your-admin-key
Content-Type: application/json
{
"scopes": ["chat:write", "audit:read", "dlp:read"],
"rate_limit_tier": "premium"
}

Response (200): Returns the updated OAuthClientResponse object.


DELETE /api/v1/admin/oauth-clients/{client_id}

Permanently removes the client registration. Active tokens issued to this client will continue to work until they expire — delete and then revoke existing tokens if immediate termination is required.

Response: 204 No Content


POST /api/v1/admin/oauth-clients/{client_id}/rotate-secret

Generates a new client secret. The old secret remains valid for a grace period to allow zero-downtime secret rotation in deployed applications. After the grace period, the old secret is rejected.

Request:

Terminal window
POST /api/v1/admin/oauth-clients/a1b2c3d4-e5f6-7890-abcd-ef1234567890/rotate-secret
Authorization: Bearer arb_live_your-admin-key

Response (200):

{
"client_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"new_client_secret": "Yk7nQw2sFpMx...(48 chars, URL-safe base64)",
"grace_period_seconds": 3600,
"previous_secret_expires_at": "2026-03-12T15:00:00Z"
}

Secret rotation procedure:

  1. Call POST /rotate-secret and copy the new_client_secret.
  2. Update your application’s secret store with the new value.
  3. Deploy the updated application configuration.
  4. Verify the application successfully authenticates with the new secret.
  5. The old secret automatically expires at previous_secret_expires_at.

Tier Description
standard Default rate limits — suitable for most automation workloads
premium Higher rate limits — for high-throughput integrations
unlimited No rate limits — use only for trusted internal services

Contact your Arbitex administrator to understand the specific request-per-second limits for each tier.


Common scopes granted to M2M clients:

Scope Description
chat:write Submit AI requests via /api/chat/completions
audit:read Read audit log entries
dlp:read Read DLP configuration
groups:read Read group memberships
groups:write Create and update groups

Scopes are enforced by the OAuthScopeEnforcer when OAUTH_SCOPE_ENFORCEMENT=true. See OAuth scope enforcement guide.


After creating a client, obtain an access token using the client credentials grant:

Terminal window
POST https://api.arbitex.ai/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890
&client_secret=Xk4mPz9rJqNv...
&scope=chat:write

Response:

{
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 3600,
"scope": "chat:write"
}

Use the access_token in subsequent API requests:

Terminal window
POST https://api.arbitex.ai/api/chat/completions
Authorization: Bearer eyJ...