Reference
SDK Reference
Generated from the SDKs' TypeScript types. For the HTTP endpoints, see the API reference.
@relipay/node
pnpm add @relipay/nodeServer SDK. One client per Application, constructed with the secret key. Auth, billing, organizations, licenses, usage, and credits live as namespaces on the client.
ReliPayTop-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.applicationsApplicationsClientme(): 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.authAuthClientsignUp(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.billingBillingClientgetPlans(): 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.creditsCreditsClientPrepaid 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.licensesLicensesClientverify(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.organizationsOrganizationsClientcreate(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.usageUsageClientrecord(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.
verifyWebhookSignatureVerify 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/reactBrowser SDK + React hooks/components. Holds only the user access token — never the secret key.
RelipayBrowserClientnew 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.
LoadingLoading({ children }: { children: React.ReactNode }): React.JSX.Element | nullRelipayProviderRelipayProvider({ children, apiUrl, initialUser = null, accessToken = null, meEndpoint, }: RelipayProviderProps): React.JSX.ElementSignedInSignedIn({ children }: { children: React.ReactNode }): React.JSX.Element | nullSignedOutSignedOut({ children }: { children: React.ReactNode }): React.JSX.Element | nulluseRelipayManual 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>; }useUserThe 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/nextjsNext.js App Router adapters — middleware + server helpers built on @relipay/node.
authResolve 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>relipayMiddlewarerelipayMiddleware(config: MiddlewareConfig = {})signInServer action: sign in with email + password.
signIn(input: { email: string; password: string; }): Promise<SignInOutcome>signOutServer action: revoke the refresh token + clear cookies. Optionally pass `redirectTo` to bounce afterwards.
signOut(redirectTo?: string): Promise<void>signUpServer action: sign up + create the user + start a session.
signUp(input: { email: string; password: string; metadata?: Record<string, unknown>; }): Promise<Session>