SDK

Authentication

Authenticate the SDK with a personal access token or a service account.

GithubEdit

Kortix accepts one bearer token per request. Pass it through getToken in createKortix. The SDK sends it as Authorization: Bearer <token>.

typescript
import { createKortix } from '@kortix/sdk';

const kortix = createKortix({
  backendUrl: 'https://api.kortix.com/v1',
  getToken: async () => process.env.KORTIX_API_KEY!,
});

backendUrl and getToken are required. The SDK caches nothing: it calls getToken on every request, so your app owns token storage and refresh.

Set clientSource to api, cli, mobile, or web when your host needs a separate source in the centralized audit log. This value identifies the client surface. It does not change the authenticated actor or their permissions.

Personal access tokens

A personal access token (PAT) is the credential for the SDK, the CLI, and CI. Create one in your own settings, at Settings → API keys (/settings/tokens). The key starts with kortix_pat_ and shows only once, at creation. Store it as a secret.

A PAT acts as the user who created it and holds exactly that user's role assignments. It adds no access of its own. Its scope only narrows the reach:

ScopeReach
Account (default)Every project in the account
ProjectOne project only; every other project returns 403

Choose the project scope for CI and other narrow-purpose credentials. kortix login mints a PAT and stores it locally — it is the same credential type, not a separate token kind.

Service accounts

A service account is a separate credential family for non-human callers, prefixed kortix_sa_. Create one at Account → Tokens (/accounts/<account-id>?tab=tokens), the account-level surface for credentials that are not a person's.

A service account is its own principal (service_account), not a person's credential. It has no membership, so it holds only the roles assigned to it directly. An agent's identity is a service account, which is how you assign a role to an agent. See Accounts & access.

A new service account has no assignments and therefore no project access. If you point getToken at one before you assign it a role, every call returns 403 "You do not have access to this project". Assign it a project role first, or use a personal access token for the SDK, the CLI, and demos instead.

OAuth access tokens (Sign in with Kortix)

A third-party app that signs users in through Kortix receives a kortix_oat_ token per user. With the kortix scope it acts as that user on the whole API, exactly like a personal access token, but it expires after an hour and rotates through a refresh token. createKortixAuth in @kortix/sdk/server owns the whole lifecycle — see Sign in with Kortix.

Supabase JWT

If your app uses Kortix's own sign-in, return the live session token instead of a PAT:

typescript
getToken: async () =>
  (await supabase.auth.getSession()).data.session?.access_token ?? null,

The SDK calls getToken on every request, so a refreshed token takes effect automatically.

Every ordinary sign-in flow is available through the Kortix API, so a CLI, a native app, a script, or your own backend signs users up and in without a Supabase URL or key — on kortix.com and on a self-host alike.

typescript
import { createKortix } from '@kortix/sdk';

const session = createKortix({ backendUrl, getToken: async () => null }).auth.session({
  storage: {                                    // optional: any get/set/remove
    get: () => localStorage.getItem('kortix'),
    set: (v) => localStorage.setItem('kortix', v),
    remove: () => localStorage.removeItem('kortix'),
  },
});
const kortix = createKortix({ backendUrl, getToken: session.getToken });   // refreshes itself

const { session: s, user } = await kortix.auth.signInWithPassword({ email, password });
await session.set(s, user);
await kortix.projects.list();                   // as that user
CallRouteNotes
auth.signUp({ email, password, redirect_to? })POST /v1/auth/signuprequires_email_confirmation: true → no session until the emailed link/code is used.
auth.signInWithPassword({ email, password })POST /v1/auth/sign-in/password
auth.sendMagicLink({ email, redirect_to? })auth.verifyOtp({ email, token, type: 'magiclink' })/sign-in/magic-link, /verify-otpThe email carries a link and a 6-digit code.
auth.signInWithProvider({ provider, redirect_to })auth.exchangeCode({ code, code_verifier })/sign-in/oauth, /oauth/exchangePKCE: keep code_verifier until the provider redirects back with ?code=. redirect_to must be on the instance's redirect allow-list.
auth.refresh({ refresh_token })POST /v1/auth/refreshcreateKortixSession calls it for you.
auth.resetPassword({ email, redirect_to? })auth.verifyOtp({ type: 'recovery' })auth.updatePassword({ password }, token)/password/reset, /verify-otp, /password/update
auth.user(token) / auth.signOut(token)GET /v1/auth/user, POST /v1/auth/sign-outSign-out revokes at Supabase and in the Kortix session gate.

Errors throw HeadlessAuthError with code, message and the upstream status (invalid_credentials, over_request_rate_limit, …). Each route is limited to 30 attempts per minute per IP. Multi-factor enrolment/challenge is not on the API yet — it stays on the Kortix web app.

Choose a credential

You are buildingUse
A backend, script, or CI jobA personal access token, account-wide or project-scoped
The Kortix CLIkortix login (mints a personal access token)
A web app, CLI, or native app signing users in itselfkortix.auth.* + createKortixSession (headless sign-in, above)
An automated caller with its own project assignmentA service account
Your own app, signed in by its users with their Kortix accountSign in with Kortix — an OAuth access token the SDK manages for you

On this page