Every option new Threshold1(...) accepts, generated directly from the installed package's own type declarations.
Generated directly from @threshold1/auth@0.3.0 — the real, currently-installed package, not hand-typed. Regenerated on every build; if this page and the actual SDK ever disagree, the SDK is right and this page needs a rebuild, not an edit.
new Threshold1(config): Threshold1;
Threshold1
apiKey: string;
Your Threshold1 API key (starts with th_live_).
Issued from the Threshold1 developer dashboard.
optional auth?: AuthConfig;
Optional authentication orchestration settings for login().
optional baseUrl?: string;
Override the default API base URL. Defaults to https://threshold1.phantomclick.in/api/v1 (the hosted production API) — no baseUrl needed for a normal integration. Set this to e.g. http://localhost:3000/api/v1 when developing against a local server.
optional debug?: boolean;
Enable debug logging for the login/register fallback chain.
optional redirectUrl?: string;
Optional URL to redirect back to after magic-link verification. The JWT and userId will be appended as query parameters.
type AuthConfig = object;
optional fallback?: FallbackMode;
Controls login()/register() cascade behavior and whether device
recognition (State B) is engaged. See FallbackMode above.
Defaults to "smart".
optional onAfterAuth?: (user, method) => Promise<void> | void;
Called after any successful authentication (register or login). Receives the authenticated user and which method succeeded. Use to link the threshold1 user to your own database.
Fires consistently across every successful auth path: register(), login(), registerPasskey(), loginWithPasskey(), verifyOtp(), loginDiscoverable(), verifyDeviceCode(), verifyBackupCode(), and resumeSession() — whether called directly or through the register()/login() orchestrators.
Exception: registerWithMagic() / loginWithMagic() do NOT fire this — they only queue an email, there is no authenticated user yet. For magic-link flows this fires later, when the link is verified inside resumeSession() on the page the link redirects back to.
Exception: addPasskey(), enrollTotp(), verifyTotp(), sendSmsOtp(), verifySmsOtp(), and generateBackupCodes() do NOT fire this either — they attach or confirm a factor on an ALREADY-authenticated session (they all require requireToken()), so there's no new register/login event to report. verifyBackupCode() is the one exception among the Sprint 3 methods: unlike the others, it establishes a brand new session (account recovery when the primary factor is unavailable), so it fires this hook like any other login path.
Promise<void> | void
onAfterAuth: async (user, method) => {
await myDB.upsert({ email: user.email, t1UserId: user.id })
}
optional onFallback?: (attempted, usedMethod) => void;
Called when a method fails and SDK falls back to the next. Use to show UI feedback during fallback.
string
string
void
type FallbackMode = "manual" | "automatic" | "smart";
Controls how aggressively login()/register() move past a failed attempt, and whether the three-state device-recognition model (State A/B/C — see README) is engaged at all.
"manual" — Never auto-cascades. A failed passkey attempt (with an identifier) or a failed discoverable attempt (without one) is surfaced immediately (thrown) for the app to handle — call sendOtp()/loginWithMagic()/loginWithPasskey() etc. yourself. Device recognition is never consulted.
"automatic" — Auto-cascades through passkey → magic → otp when an
identifier is known (same order the old auth.methods
default used). Without an identifier, behaves like
"manual" for the entry point itself (there's no
identifier to cascade to) — device recognition is still
never consulted, so a failed discoverable attempt always
surfaces as "no identifier", never a one-tap confirm.
"smart" — (default) Same cascade as "automatic" when an identifier
is known. Without one, a failed discoverable attempt
triggers a device-recognition check: if this device is
recognized and has a fallback method enrolled, login()
resolves with { status: "confirm_required", ... }
instead of throwing — call confirmDeviceSend() once the
user taps confirm, then verifyDeviceCode(code). This is
never silent: per the three-state model's hard rule, a
recognized device still requires an explicit user tap
before anything is sent.