Skip to content

Machine clients (client credentials)

A machine client is for scripts, scheduled jobs and integrations (a GRC tool, a ticketing system, a data pipeline) that call the API as themselves, not as a person. It uses the OAuth 2 client credentials grant.

In Admin → API → Clients, select New API client and choose Machine client:

  • Acting role: User, Reviewer or Approver. The client acts with that role. It can never be an admin.
  • Scopes: what the client may ask for, limited to what its acting role allows. See Scopes.
  • Libraries (optional): restrict the client to some libraries. None ticked means every library.
  • audit:read: a separate checkbox, because it lets the client read your organization’s whole audit log (for a SIEM).
  • Secret expires in: 90 days by default, at most 365.

Tradecraft shows the client id (tco_…) and the client secret (tcs_…). Copy the secret now: it is shown once and Tradecraft keeps only a hash. If you lose it, create a new secret.

A machine client belongs to your organization, not to the admin who created it, and keeps working if that admin leaves.

Send the client id and secret with HTTP Basic authentication (client_secret_basic; secrets in the body are not accepted) to the token endpoint. scope is optional: leave it out to get every scope the client is allowed, or ask for fewer.

Terminal window
curl -s -u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials \
-d "scope=assessments:read knowledge:read knowledge:ask" \
https://api.tradecrafthub.ai/oauth/token
async function getToken(scope?: string): Promise<string> {
const res = await fetch("https://api.tradecrafthub.ai/oauth/token", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.CLIENT_ID}:${process.env.CLIENT_SECRET}`)}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({ grant_type: "client_credentials", ...(scope ? { scope } : {}) }),
})
if (!res.ok) throw new Error(`token: ${res.status} ${JSON.stringify(await res.json())}`)
const body = (await res.json()) as { access_token: string; expires_in: number; scope: string }
return body.access_token
}

The response:

{ "access_token": "tca_…", "token_type": "Bearer", "expires_in": 3600, "scope": "assessments:read knowledge:ask knowledge:read" }

Access tokens last one hour. There is no refresh token with client credentials: ask for a new token when the old one expires. Then call the API with Authorization: Bearer <access_token>.

The token endpoint answers OAuth errors ({ "error", "error_description" }):

  • invalid_client (401): wrong client id or secret, an expired or revoked secret, or a disabled client.
  • unauthorized_client: the client is not a machine client, the plan has no API, or the API is turned off.
  • invalid_scope: a scope the client is not allowed.
  • invalid_target: a resource other than the API (https://api.tradecrafthub.ai).

The token endpoint allows 60 requests a minute per client: reuse a token until it expires instead of asking for one per call.

  • The same as a person with its acting role, within its scopes and libraries.
  • It cannot Send to Finalize or Finalize: those scopes are for people only (see Apps acting for people).
  • Answers it proposes always wait for an approver, whatever its acting role, labelled API · client name in the review queue.
  • Its actions are audited as service:<client id> with the client’s name.

A client can have at most two active secrets, so you can rotate without downtime:

  1. In Admin → API → Clients, rotate the secret and choose when the old one ends: Rotate (end old now), (old ends in 24 h) or (old ends in 7 days).
  2. Deploy the new secret to your integration.
  3. The old secret stops working at the time you chose.

Admins and your organization’s security contacts are warned 14 and 3 days before a secret expires. Revoking a secret takes effect at the next token request; access tokens already issued with it keep working until they expire, at most one hour later. Disabling the client stops it at once.

Admin → API → Usage shows requests, errors and rate-limited requests per client per day.

Privacy preference center

When you visit tradecrafthub.ai, we store or read a small number of cookies in your browser. Strictly necessary cookies make the website and the Tradecraft app work. Analytics cookies are used only if you allow them. Open a category to learn more, and see our privacy policy for how we handle the information you enter on this site.

Manage consent preferences

  • Always active