Radon

API reference

The full Radon surface — the constructor, provider methods, session helpers, HTTP routes, entities, and error codes.

A complete reference to the @radonsdk/auth public API. For guided walkthroughs, start with the Quickstart or an auth method.

new Radon(config)

Creates the SDK instance. See Configuration for every option in detail.

import { Radon } from "@radonsdk/auth";

const auth = new Radon({
  adapter,                                  // required
  session: { secret: process.env.RADON_SECRET! }, // required
  providers: { /* enabled methods */ },
  appName: "Acme",
  code: { length: 6, ttlMs: 600_000, maxAttempts: 5 },
  rateLimit: { maxPerWindow: 3, windowMs: 600_000 },
  licenseKey: process.env.RADON_LICENSE_KEY, // Pro
  encryptionKey: process.env.RADON_ENCRYPTION_KEY, // TOTP
});

createRadon(config) is an equivalent factory function.

Instance methods

MemberSignatureDescription
init()() => Promise<void>Create tables (SQL adapters) and verify the Pro license. Call once on boot.
close()() => Promise<void>Adapter teardown.
createSessionToken()(userId, { claims?, expiresInSec? }?) => { token, expiresAt }Issue a JWT session token.
verifyToken()(token) => JwtClaimsVerify a token; throws if invalid/expired. claims.sub is the user id.
getSessionUser()(token) => Promise<RadonUser>Verify + load the user (sanitized).
on()(event, handler) => UnsubscribeSubscribe to an event. Pro.
licensedbooleanWhether the Pro tier is unlocked.

Provider accessors

Each returns the provider or throws ProviderNotConfiguredError if it wasn't enabled. Pro accessors also require a verified license.

AccessorProviderTier
auth.emailCodeEmail one-time codeFree
auth.magicLinkMagic linkFree
auth.emailPasswordEmail + passwordFree
auth.googleGoogle OAuthFree
auth.oauth(name)A configured OAuth providerPro
auth.phoneOtpPhone / SMS OTPPro
auth.totp2FA / TOTPPro
auth.webauthnPasskeys / WebAuthnPro
auth.refreshRefresh tokensPro
auth.sessionsProviderMulti-device sessionsPro
auth.apiKeysAPI keysPro
auth.orgsOrgs / teamsPro
auth.accountData export / deletionPro

Provider methods

auth.emailCode

sendCode({ email, metadata? }): Promise<{ expiresAt: Date }>
verify({ email, code }): Promise<{ user: RadonUser; created: boolean }>
sendLink({ email, redirectTo?, metadata? }): Promise<{ url: string; expiresAt: Date }>
verify(signedToken): Promise<{ user: RadonUser; created: boolean }>

auth.emailPassword

signup({ email, password, metadata? }): Promise<{ user: RadonUser }>
login({ email, password }): Promise<{ user: RadonUser }>
requestReset({ email, redirectTo? }): Promise<{ sent: boolean }>
setPassword({ token, newPassword }): Promise<{ user: RadonUser }>

auth.google

getAuthUrl({ state?, scopes?, accessType?, prompt?, loginHint? }): string
handleCallback(code): Promise<{ user: RadonUser; created: boolean; profile: GoogleProfile }>

auth.oauth(name) (Pro)

getAuthUrl({ state?, scopes?, params? }): { url: string; codeVerifier?: string; state?: string }
handleCallback({ code, codeVerifier? }): Promise<{ user; created; profile; tokens }>
// auth.oauthProviders → string[] of configured provider names

auth.phoneOtp (Pro)

sendCode({ phone, metadata? }): Promise<{ expiresAt: Date }>
verify({ phone, code }): Promise<{ user: RadonUser; created: boolean }>

auth.totp (Pro)

beginEnrollment(userId): Promise<{ secret: string; uri: string }>
confirmEnrollment(userId, code): Promise<{ recoveryCodes: string[] }>
verify(userId, code): Promise<boolean>
verifyRecoveryCode(userId, code): Promise<boolean>
isEnabled(userId): Promise<boolean>
regenerateRecoveryCodes(userId): Promise<string[]>
disable(userId): Promise<void>

auth.webauthn (Pro)

startRegistration(userId): Promise<{ options; challenge: string }>
finishRegistration({ userId, response, expectedChallenge }): Promise<{ credential }>
startAuthentication(userId?): Promise<{ options; challenge: string }>
finishAuthentication({ userId?, response, expectedChallenge }): Promise<{ user: RadonUser }>
listCredentials(userId): Promise<Array<Omit<StoredCredential, "publicKey">>>
removeCredential(userId, credentialId): Promise<void>

auth.refresh (Pro)

issue({ userId, claims?, device? }): Promise<TokenPair>
refresh(refreshToken, { claims?, device? }?): Promise<TokenPair>
revoke(refreshToken): Promise<void>
revokeAllForUser(userId): Promise<void>
// TokenPair = { accessToken, accessExpiresAt, refreshToken, refreshExpiresAt, familyId }

auth.sessionsProvider (Pro)

create({ userId, device?, ttlMs? }): Promise<{ token; session }>
listDevices(userId, currentToken?): Promise<DeviceSession[]>
revokeDevice(sessionId): Promise<void>
revoke(token): Promise<void>
revokeAll(userId): Promise<void>
createGuest({ device?, metadata? }?): Promise<{ user; token; session }>
isGuest(userId): Promise<boolean>
upgrade({ userId, provider, providerAccountId, email?, emailVerified? }): Promise<{ user }>
impersonate(adminUserId, targetUserId, { expiresInSec?, reason? }?): Promise<{ token; expiresAt }>

auth.apiKeys (Pro)

create({ userId?, orgId?, name, scopes?, expiresAt?, metadata? }): Promise<{ key; record }>
verify(presentedKey): Promise<PublicApiKey>
list({ userId?, orgId? }): Promise<PublicApiKey[]>
revoke(apiKeyId): Promise<void>

auth.orgs (Pro)

create({ name, slug?, ownerUserId, metadata? }): Promise<{ org; membership }>
get(idOrSlug): Promise<RadonOrg | null>
listForUser(userId): Promise<RadonOrgMembership[]>
listMembers(orgId): Promise<RadonOrgMembership[]>
roleOf(orgId, userId): Promise<OrgRole | null>
invite({ orgId, email, role?, invitedByUserId? }): Promise<{ invite; token; url? }>
acceptInvite(token, userId): Promise<RadonOrgMembership>
addMember(orgId, userId, role?): Promise<RadonOrgMembership>
setRole(orgId, userId, role): Promise<RadonOrgMembership>
removeMember(orgId, userId): Promise<void>
assertRole(orgId, userId, min): Promise<void>
delete(orgId): Promise<void>

auth.account (Pro)

exportData(userId): Promise<UserDataExport>
deleteUser(userId): Promise<void>

Standalone helpers

Verify a session token anywhere without a Radon instance — same secret:

import { verifyToken } from "@radonsdk/auth";

const claims = verifyToken(cookieValue, process.env.RADON_SECRET!, {
  clockToleranceSec: 0, // optional
});
// claims.sub is the user id

HTTP routes

Mounted by every framework integration, relative to your base path (e.g. /api/auth). A successful sign-in sets an HttpOnly, SameSite=Lax cookie named radon_session.

Method & pathBody / queryEffect
POST /email-code/send{ email }Emails a 6-digit code
POST /email-code/verify{ email, code }Signs in → cookie
POST /magic-link/send{ email }Emails a sign-in link
GET /magic-link/verify?token=…Signs in → cookie, redirects
POST /password/signup{ email, password }Creates account → cookie
POST /password/login{ email, password }Signs in → cookie
POST /password/request-reset{ email }Emails a reset link (always 200)
POST /password/reset{ token, newPassword }Sets a new password
GET /google/start?state=…Redirects to Google
GET /google/callback?code=…Signs in → cookie, redirects
POST /logoutClears the session cookie
GET /session{ user } or 401

Errors come back as { error: "<code>", message } with the status from the table below.

Entities

The records adapters store and return.

interface RadonUser {
  id: string;
  email: string | null;
  emailVerified: boolean;
  metadata: Record<string, unknown>;
  createdAt: Date;
  updatedAt: Date;
}

Also exported: RadonIdentity, RadonSession, RadonOneTimeCode, and the Pro entities RadonRefreshToken, RadonApiKey, RadonOrg, RadonOrgMembership, RadonOrgInvite, plus OrgRole and DeviceInfo.

Errors

Every failure is a RadonError subclass with a stable code. Integrations map each to an HTTP status automatically.

Error classcodeHTTP
RateLimitErrorrate_limit_exceeded429
CodeInvalidErrorcode_invalid401
CodeExpiredErrorcode_expired401
CodeNotFoundErrorcode_not_found401
MaxAttemptsErrormax_attempts_exceeded401
InvalidCredentialsErrorinvalid_credentials401
TokenInvalidErrortoken_invalid401
ApiKeyInvalidErrorapi_key_invalid401
RefreshTokenInvalidErrorrefresh_token_invalid401
NotAuthorizedErrornot_authorized403
UserNotFoundErroruser_not_found404
EmailExistsErroremail_exists409
WeakPasswordErrorweak_password400
OrgErrororg_error400
EncryptionRequiredErrorencryption_required400
ProviderNotConfiguredErrorprovider_not_configured501
LicenseRequiredErrorlicense_required501
AdapterCapabilityErroradapter_capability501
EmailSendErroremail_send_failed500
OAuthErroroauth_error400
import { RateLimitError } from "@radonsdk/auth";

try {
  await auth.emailCode.sendCode({ email });
} catch (err) {
  if (err instanceof RateLimitError) {
    // err.retryAfterMs — ms until the caller can retry
  }
}

Next steps

On this page