Reference

SDK Reference

Generated from the SDKs' TypeScript types. For the HTTP endpoints, see the API reference.

← Back to docs

@relipay/node

pnpm add @relipay/node

Server SDK. One client per Application, constructed with the secret key. Auth, billing, organizations, licenses, usage, and credits live as namespaces on the client.

ReliPay

Top-level ReliPay client. Auth and billing live as namespaces (`relipay.applications`, `relipay.auth`, `relipay.billing`) so an agent reading `relipay.` in an editor sees a discoverable surface.

new ReliPay(config: ReliPayConfig)
relipay.applicationsApplicationsClient
me(): Promise<ApplicationDto>

Verify credentials and fetch the calling Application. Use this as your SDK smoke test — if it returns, your secret key is good and you're pointed at the right ReliPay deployment.

relipay.authAuthClient
signUp(input: SignUpRequest): Promise<AuthResultDto>

Create a new end-user in the calling Application via email + password. Returns the user and a JWT to use for subsequent per-user calls (e.g. `getCurrentUser(token)`).

signIn(input: SignInRequest): Promise<SignInOutcomeDto>

Authenticate an existing end-user with email + password.

mfaVerify(input: MfaVerifyRequest): Promise<AuthResultDto>

Exchange an MFA challenge token + TOTP/backup code for a real session. Use after `signIn` (or OAuth callback) returns `mfaRequired: true`.

requestMagicLink(input: { email: string; signInUrl?: string; }): Promise<{ delivered: boolean; emailSent: boolean; magicLinkToken: string | null; }>

Request a magic-link sign-in email. Enumeration-safe: same response shape whether the email exists or not. When the Application has email transport configured, the link is sent and `magicLinkToken` is null; otherwise the raw token is returned for you to forward.

verifyMagicLink(input: { token: string }): Promise<SignInOutcomeDto>

Consume a magic-link token. Returns `SignInOutcome` — branch on `mfaRequired` before reading `accessToken`. For MFA-enrolled users the response carries `mfaChallengeToken` and you must complete via `mfaVerify(...)`.

startPasskeyAuthentication(input?: { email?: string }): Promise<{ options: unknown; expectedChallenge: string; }>

Begin a passkey authentication ceremony. Returns the WebAuthn options to forward to the browser (`navigator.credentials.get(...)`) along with `expectedChallenge` — bind the challenge to your session and pass both back via `verifyPasskeyAuthentication(...)`.

verifyPasskeyAuthentication(input: { response: unknown; expectedChallenge: string; }): Promise<SignInOutcomeDto>

Complete a passkey authentication. Returns the same `SignInOutcome` shape as `signIn` — but passkeys are themselves a strong factor, so `mfaRequired` will always be `false` in practice.

startPasskeyRegistration(accessToken: string): Promise<{ options: unknown; expectedChallenge: string; }>

Begin a passkey registration ceremony for an authenticated user. Forward `options` to `navigator.credentials.create(...)`; store `expectedChallenge` in session; POST both back via `verifyPasskeyRegistration(...)`.

verifyPasskeyRegistration(accessToken: string, input: { response: unknown; expectedChallenge: string; deviceName?: string; }): Promise<{ credentialId: string; deviceName: string | null }>
listPasskeys(accessToken: string): Promise< Array<{ id: string; credentialId: string; deviceName: string | null; lastUsedAt: string | null; createdAt: string; }> >

List the user's registered passkeys.

deletePasskey(accessToken: string, credentialRowId: string): Promise<{ deleted: boolean }>

Remove a passkey. Returns `{deleted: false}` if the row doesn't belong to this user.

getCurrentUser(accessToken: string): Promise<EndUserDto>

Resolve the end-user behind a presented access token.

refresh(refreshToken: string): Promise<AuthResultDto>

Exchange a refresh token for a fresh {access, refresh} pair. The presented refresh is revoked atomically — call this **once** and store the new `refreshToken` from the response immediately.

signOut(refreshToken: string): Promise<{ signedOut: true }>

Revoke a refresh token. Idempotent — no-op for unknown tokens. The access token paired with this refresh remains valid until its short (15 min) expiry; for true "log out everywhere" semantics, also clear the access token from your client.

requestPasswordReset(input: ForgotPasswordRequest): Promise<ForgotPasswordResultDto>

Request a password-reset token for an email. Always succeeds — never tells you whether the email exists. **You must email the returned `resetToken` to the user**: ReliPay does not send email.

resetPassword(input: ResetPasswordRequest): Promise<{ ok: true }>

Consume a reset token + set a new password. Single-use. On success, every refresh token for the user is revoked.

changePassword(accessToken: string, input: ChangePasswordRequest): Promise<{ ok: true }>

Authenticated password change. Pass the user's *current* access token. On success, every refresh token for the user is revoked — other devices are signed out.

signOutEverywhere(accessToken: string): Promise<{ revokedCount: number }>

Revoke every refresh token for the calling user. "Sign out of all devices." The caller's access token remains valid until 15-min expiry — clear it client-side for full logout.

sendVerificationEmail(accessToken: string, input?: { verifyUrl?: string }): Promise<{ emailSent: boolean; verificationToken: string | null }>

Send (or re-send) an email-verification link to the current user. If email transport is configured on the Application, ReliPay sends the email and `verificationToken` is null. Otherwise the raw token is returned for the caller to forward via their own provider.

verifyEmail(input: { token: string }): Promise<{ verified: true; endUser: EndUserDto }>

Consume an email-verification token. Single-use, 24-hour lifetime. Marks `emailVerified: true` on the user record. Cross-Application tokens are refused with `EMAIL_VERIFICATION_TOKEN_WRONG_APPLICATION`.

listSessions(accessToken: string): Promise< Array<{ id: string; createdAt: string; expiresAt: string; userAgent: string | null; ip: string | null; }> >

List the current user's active sessions (live refresh tokens), newest first. Each carries the User-Agent + IP captured at issue time and an `id` you can pass to `revokeSession(...)`.

revokeSession(accessToken: string, sessionId: string): Promise<{ revoked: boolean }>

Revoke one session by id. Idempotent — `{ revoked: false }` if it isn't this user's.

mfaStatus(accessToken: string): Promise<{ enabled: boolean; remainingBackupCodes: number | null; policy: 'off' | 'optional' | 'required'; }>

MFA enrollment status for the current user, plus the Application's policy.

mfaSetup(accessToken: string): Promise<{ otpauthUrl: string; backupCodes: string[]; warning: string; }>

Begin TOTP enrollment: mints a secret (as an `otpauthUrl` for the QR) and 10 single-show backup codes. **Not enrolled until `confirmMfaSetup(...)`.** Only SHA-256 hashes of the backup codes are stored — show them once.

confirmMfaSetup(accessToken: string, code: string): Promise<{ ok: true }>

Confirm enrollment by submitting the current 6-digit TOTP code.

mfaChallenge(accessToken: string, code: string): Promise<{ ok: boolean }>

Verify a TOTP or backup code as a step-up check (does NOT issue a session). Backup codes are single-use — consumed on success. Returns `{ ok }`.

disableMfa(accessToken: string): Promise<{ disabled: true }>

Disable MFA for the current user.

startOAuth(provider: string, state: string): Promise<{ authorizationUrl: string }>

Get the provider authorization URL to redirect the browser to. Pass an unguessable `state` and verify it on return before calling `completeOAuth`.

completeOAuth(provider: string, code: string): Promise<SignInOutcomeDto>

Exchange the provider `code` for a ReliPay session. Returns a `SignInOutcome` — branch on `mfaRequired` before reading `accessToken`. Verify the `state` CSRF value yourself before calling.

listOAuthIdentities(accessToken: string): Promise< Array<{ provider: string; providerAccountId: string; email: string | null; createdAt: string; }> >

List the OAuth providers linked to the current user.

startOAuthLink(accessToken: string, provider: string, state: string): Promise<{ authorizationUrl: string }>

Begin linking a provider to the *currently authenticated* user.

completeOAuthLink(accessToken: string, provider: string, code: string): Promise<{ provider: string; providerAccountId: string; alreadyLinked: boolean }>

Complete an OAuth link — attaches the provider identity to the current user. Refuses on unverified provider emails (account-takeover guard) or when the provider account already belongs to a different user.

unlinkOAuth(accessToken: string, provider: string): Promise<{ unlinked: boolean }>

Remove a linked provider. Refuses with `OAUTH_UNLINK_WOULD_LOCK_OUT` (409) if it would leave the account with no way to sign in.

relipay.billingBillingClient
getPlans(): Promise<PlanDto[]>

List the calling Application's active plans. Public — pricing pages typically render straight from this. Application API key only; no user JWT needed.

getSubscription(accessToken: string): Promise<SubscriptionDto | null>

Fetch the current end-user's active subscription, or `null` if they have none. Returns the most recent ACTIVE / PENDING / PAST_DUE row.

createCheckout(accessToken: string, input: CreateCheckoutRequest & { couponCode?: string }): Promise<CheckoutResultDto>

Start a hosted-checkout session. Returns the URL to redirect the user to and the local PENDING Subscription row. Subscription activation happens via the provider's webhook — not synchronously here.

validateCoupon(accessToken: string, input: ValidateCouponRequest): Promise<ValidateCouponResultDto>

Validate a coupon for the current user against a plan, *without* applying it. Render "$50 off" on a pricing page before submit.

getProviders(country?: string): Promise<ProvidersListDto>

List the billing providers configured + enabled for this Application, in the order the geo router would prefer them. Forward the end-user's `country` (ISO 3166-1 alpha-2) when you have it — the panel/SDK will surface India-specific providers (Razorpay) for IN-country users, etc.

relipay.creditsCreditsClient

Prepaid credits — the "lead pack" / pay-as-you-go drawdown model. The customer's backend grants credits (by selling a CREDIT-kind plan, which grants automatically on payment) and draws them down per unit consumed.

getBalance(endUserId: string): Promise<CreditBalanceDto>

Current spendable balance for an end-user (0 if they've never held credits).

consume(input: ConsumeCreditsRequest & { endUserId: string }): Promise<ConsumeCreditsResultDto>

Deduct credits from an end-user. Throws `RelipayError` with `code: "CREDITS_INSUFFICIENT"` (HTTP 402) when the balance is too low.

listLedger(endUserId: string, limit?: number): Promise<CreditLedgerEntryDto[]>

Recent ledger entries for an end-user, newest first.

relipay.licensesLicensesClient
verify(input: { key: string; machineFingerprint: string; label?: string; }): Promise<LicenseVerifyResultDto>

Verify a license key + record an activation for this machine. Call once at app startup; you'll get a deterministic body (`ok=false` for invalid licenses — never an HTTP error — so your software can loop on the result without try/catch noise).

relipay.organizationsOrganizationsClient
create(accessToken: string, input: { name: string; slug: string; metadata?: Record<string, unknown> }): Promise<{ organization: OrganizationDto; membership: { id: string; role: 'OWNER' } }>

Create an organization; the calling user becomes the OWNER.

listMine(accessToken: string): Promise<OrganizationWithRoleDto[]>

List organizations the calling user belongs to, with their role.

get(accessToken: string, organizationId: string): Promise<OrganizationWithRoleDto>

Fetch one organization the caller belongs to.

update(accessToken: string, organizationId: string, input: { name?: string; metadata?: Record<string, unknown> }): Promise<OrganizationDto>

Update org name / metadata. OWNER + ADMIN only.

listMembers(accessToken: string, organizationId: string): Promise<OrganizationMemberDto[]>

List members of an organization the caller belongs to.

invite(accessToken: string, organizationId: string, input: { email: string; role: 'OWNER' | 'ADMIN' | 'MEMBER' }): Promise<{ invitation: OrganizationInvitationDto; token: string }>

Invite a user. Returns the raw token ONCE — surface via your own email/share channel. OWNER + ADMIN only.

revokeInvitation(accessToken: string, organizationId: string, invitationId: string): Promise<{ revoked: boolean }>

Revoke a pending invitation. OWNER + ADMIN only. Idempotent.

setMemberRole(accessToken: string, organizationId: string, targetEndUserId: string, input: { role: 'OWNER' | 'ADMIN' | 'MEMBER' }): Promise<{ id: string; organizationId: string; endUserId: string; role: 'OWNER' | 'ADMIN' | 'MEMBER'; }>

Change a member's role. OWNER manages anyone; ADMIN manages MEMBER only. Last-OWNER guard refuses demoting the only OWNER.

removeMember(accessToken: string, organizationId: string, targetEndUserId: string): Promise<{ removed: true }>

Remove a member (or self). Refuses removing the last OWNER.

leave(accessToken: string, organizationId: string): Promise<{ left: true }>

Self-leave. Refuses leaving as the last OWNER.

acceptInvitation(accessToken: string, input: { token: string }): Promise<{ membership: { id: string; organizationId: string; role: 'OWNER' | 'ADMIN' | 'MEMBER'; }; }>

Accept an organization invitation by raw token. Refuses cross- Application invitations. Idempotent if the caller is already a member.

relipay.usageUsageClient
record(input: { meterSlug: string; quantity: number; endUserId?: string; occurredAt?: string; metadata?: Record<string, unknown>; }): Promise<UsageRecordDto>

Record a usage event against a named meter. `quantity` can be negative to credit back (e.g. refunds). `occurredAt` defaults to server time; pass an ISO string when ingesting historical events.

aggregate(input: { meterSlug: string; from?: string; to?: string; endUserId?: string; }): Promise<UsageAggregateDto>

Sum recorded quantity for a meter, optionally bounded by a time window and/or scoped to one end-user. Use to drive in-app "you've used X of your Y quota this month" displays.

verifyWebhookSignature

Verify the HMAC signature on an inbound webhook from ReliPay. Returns `true` only when (a) the timestamp is fresh (within `toleranceSeconds`, default 300) AND (b) the signature matches a constant-time compare.

verifyWebhookSignature(args: { header: string | null | undefined; payload: string | Buffer; secret: string; toleranceSeconds?: number; now?: () => number; }): boolean

@relipay/react

pnpm add @relipay/react

Browser SDK + React hooks/components. Holds only the user access token — never the secret key.

RelipayBrowserClient
new RelipayBrowserClient(config: ReliPayBrowserConfig)
getCurrentUser(accessToken: string, meEndpoint = '/api/v1/auth/me'): Promise<EndUserDto | null>

Fetch the current end-user given an access token. Returns null on USER_TOKEN_INVALID so callers can render signed-out state without try/catch noise.

Loading
Loading({ children }: { children: React.ReactNode }): React.JSX.Element | null
RelipayProvider
RelipayProvider({ children, apiUrl, initialUser = null, accessToken = null, meEndpoint, }: RelipayProviderProps): React.JSX.Element
SignedIn
SignedIn({ children }: { children: React.ReactNode }): React.JSX.Element | null
SignedOut
SignedOut({ children }: { children: React.ReactNode }): React.JSX.Element | null
useRelipay

Manual session refresh. Usually called after a sign-in / sign-out round-trip the customer's server handles, so the provider re-fetches the latest user state.

useRelipay(): { refresh: () => Promise<void>; }
useUser

The current end-user, or `null` if signed out. The narrowing is the same pattern Clerk uses — check `user` for null, then TypeScript narrows.

useUser(): { user: EndUserDto | null; signedIn: boolean; loading: boolean; }

@relipay/nextjs

pnpm add @relipay/nextjs

Next.js App Router adapters — middleware + server helpers built on @relipay/node.

auth

Resolve the current session from cookies. Tries access first; on USER_TOKEN_INVALID, attempts refresh-and-retry once. Returns null when signed out (or when refresh fails).

auth(): Promise<Session | null>
relipayMiddleware
relipayMiddleware(config: MiddlewareConfig = {})
signIn

Server action: sign in with email + password.

signIn(input: { email: string; password: string; }): Promise<SignInOutcome>
signOut

Server action: revoke the refresh token + clear cookies. Optionally pass `redirectTo` to bounce afterwards.

signOut(redirectTo?: string): Promise<void>
signUp

Server action: sign up + create the user + start a session.

signUp(input: { email: string; password: string; metadata?: Record<string, unknown>; }): Promise<Session>