Skip to content

Management client

IntelliAuthManagement is the admin client. It authenticates via client credentials and exposes IntelliAuth's REST surface as typed methods.

import { IntelliAuthManagement } from '@intelliauth/node-sdk'
const mgmt = new IntelliAuthManagement({
tenantUrl: 'https://banking-cymmetri.intelliauth.local',
clientId: process.env.INTELLIAUTH_M2M_CLIENT_ID!,
clientSecret: process.env.INTELLIAUTH_M2M_CLIENT_SECRET!,
audience: 'https://banking-cymmetri.intelliauth.local/api',
scope: 'users:read users:write groups:read groups:write audit:read',
})
OptionRequiredDefaultDescription
tenantUrlyesBase URL of the IntelliAuth tenant.
clientIdyesClient id of the M2M application.
clientSecretyesClient secret of the M2M application. Keep this in a secret manager — never in code.
audienceyesThe API audience the access token is for.
scopenoemptySpace-separated scopes to request on token issuance.
fetchnoglobal fetchOverride the fetch implementation. Useful for tests and for environments without a global fetch.
retryno{ attempts: 3, baseMs: 200 }Retry policy for 5xx / network errors on idempotent operations.

The constructor does not make any network calls. The first call to a method triggers token acquisition.

Methods are grouped on the client by resource.

GroupMethods
mgmt.userslist, create, get, update, delete, disable, enable, resetPassword, forceMfaReset
mgmt.groupslist, create, get, update, delete, addMember, removeMember, listMembers
mgmt.applicationslist, get, update, rotateSecret, disable, enable
mgmt.auditlist, stream
mgmt.invitationslist, create, revoke, resend
mgmt.sessionslistForUser, revoke, revokeAllForUser

Each method returns a Promise and throws an IntelliAuthApiError on failure.

const user = await mgmt.users.create({
email: 'finance.lead@cymmetri.com',
name: 'Finance Lead',
password: generateTemporaryPassword(),
password_must_be_reset: true,
email_verified: true,
})
console.log(user.id) // 'usr_01HZX...'

If you want the user to verify their email themselves rather than skipping verification, omit email_verified. The platform sends the verification email automatically.

for (const record of csvRows) {
await mgmt.users.create({ email: record.email, name: record.name })
}

This serialises one user at a time. For thousands of users, the Users API supports a bulk-import endpoint that streams rows — the management client's mgmt.users.bulkImport(readable) wraps it.

await mgmt.users.disable('usr_01HZX...')

Disabled users cannot sign in but their record remains. Use delete to fully erase the record (subject to retention policy).

const { client_secret, expires_at } = await mgmt.applications.rotateSecret('app_01HZX...')
console.log('new secret (single-show):', client_secret)
console.log('overlap window ends at:', expires_at)

The new secret is returned exactly once. Store it. The previous secret stays valid until expires_at so deployments can roll forward without downtime.

const page = await mgmt.audit.list({
start: '2026-05-01T00:00:00Z',
end: '2026-05-17T00:00:00Z',
event_types: ['user.signed_in', 'mfa.factor_added'],
limit: 100,
})
for (const event of page.events) {
console.log(event.id, event.event_type, event.actor.id, event.created_at)
}
// Pagination — repeat with page.next_cursor until it's null.

For long-running export jobs, use mgmt.audit.stream({ ... }) instead — it yields events asynchronously without materialising the whole result set.

The client manages its access token internally:

  • The first method call triggers a client_credentials token request.
  • The token is cached in memory.
  • On the next call, if the token's exp is more than 60 s away, it is reused.
  • If the token has expired or the previous call returned 401, the client transparently re-fetches the token and retries the original request once.

You do not need to think about token rotation. If you want explicit control:

await mgmt.refreshToken() // force a token refresh
mgmt.clearToken() // drop the cached token; next call will re-fetch

IntelliAuthApiError carries the HTTP status, the platform error code, the request id, and an optional cause:

try {
await mgmt.users.delete('usr_doesnt_exist')
} catch (e) {
if (e instanceof IntelliAuthApiError) {
console.error(e.status, e.code, e.request_id)
}
}

The request_id is the value to quote when opening a support ticket — it lets the platform team find the exact request in the audit log.

The client is safe to use concurrently from many code paths. Internally, the token-refresh logic deduplicates simultaneous requests — if 100 concurrent calls find an expired token, only one token refresh actually goes out; the rest await the same in-flight promise.

For multi-instance backends, share a single client per instance. Different instances will each acquire their own token; this is fine — the platform handles the load.

The client secret is the most sensitive artefact in this surface. Reasonable storage:

  • A secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault).
  • Kubernetes Secrets (with encryption-at-rest enabled).
  • An env var injected at boot time from one of the above.

Never the source repo. Never a .env checked into git. Never a screenshot in a support ticket.