Developers
SDKs

Admin SDK — TypeScript

Manage AuthPI from TypeScript backends with @authpi/admin — issuers, users, organizations, webhooks, and API keys, with typed responses, retries, and auto-pagination.

Last updated 2026-09-17

@authpi/admin is the official TypeScript SDK for the AuthPI Core API — everything you can do from the dashboard (issuers, users, organizations, clients, webhooks, API keys, events), callable from your backend with typed requests and responses.

Server-side only. The SDK authenticates with API keys, which are secrets. It runs on Node.js 18+, Bun, Deno, and Cloudflare Workers.

Install

npm install @authpi/admin

Initialize

Authenticate with an API key — an id + secret pair sent as HTTP Basic credentials:

import { AuthPIAdmin } from '@authpi/admin';

const admin = new AuthPIAdmin({
  apiKey: { id: process.env.AUTHPI_KEY_ID!, secret: process.env.AUTHPI_KEY_SECRET! },
});

accountId is optional: when omitted, the SDK resolves it once via GET /v1/me on the first request and caches it — an API key always maps to exactly one account. Pass it explicitly to skip that lookup.

For server-side calls on behalf of a user session, pass accessToken instead, optionally with an onTokenExpired callback — the SDK calls it on 401s and retries with the fresh token, deduplicating concurrent refreshes.

Common tasks

Manage users in an issuer. Most resources are scoped: account-level ones hang off admin directly (issuers, webhooks, events, apiKeys, domains, credits), per-issuer ones off admin.issuer(id):

const user = await admin.issuer('i_4r8w2k9m5x1p7q3e6t0y2u4i8').users.create({
  username_type: 'email',
  username: 'alice@example.com',
  profile: { first_name: 'Alice', last_name: 'Smith' },
});

const users = await admin.issuer('i_4r8w2k9m5x1p7q3e6t0y2u4i8').users.list({ limit: 50 });

Paginate everything. list() returns one page (page.data, cursor in hand); listAll() returns an async iterator that follows cursors for you:

for await (const user of admin.issuer('i_4r8w2k9m5x1p7q3e6t0y2u4i8').users.listAll()) {
  console.log(user.id);
}

Subscribe to events with a webhook:

const webhook = await admin.webhooks.create({
  name: 'Lifecycle events',
  url: 'https://api.example.com/hooks/authpi',
  auth: { type: 'bearer' }, // token generated and returned once in the response
  events: ['user.created', 'organization.suspended', 'organization.deleted'],
});

When sending an update body, the SDK removes only the top-level _etag it attaches to resource responses. It preserves nested customer data, including underscore-prefixed keys in metadata and scope-description maps. Send only the fields supported by the update endpoint.

Error handling

Failures throw typed subclasses of ApiErrorAuthenticationError (401), ForbiddenError (403), NotFoundError (404), ValidationError (400, with field details), ConflictError, RateLimitError, ServerError:

import { NotFoundError, ValidationError } from '@authpi/admin';

try {
  await admin.issuer(issuerId).users.get(userId);
} catch (err) {
  if (err instanceof NotFoundError) return null;
  if (err instanceof ValidationError) console.error(err.fields);
  throw err;
}

Retries with exponential backoff are built in for transient failures (429/5xx) and configurable via the retries option.

Next steps