Get started
Quickstart
By the end of this page a person can sign in to your application, you will have a session you can trust on every request, and the same code path will already work for social login, magic links and enterprise SSO.
Before you start
You need an application that can serve two routes over HTTPS in production, or over localhost in development: one that starts the sign-in and one that receives the redirect back. Everything else is handled for you.
- A Paycux account, with an environment you are willing to break
- A server-side runtime — API keys must never reach the browser
- A redirect URI you control, registered in the dashboard
Environments
Every account starts with two environments: staging and production. They are fully separate — separate API keys, separate users, separate connections, separate webhook endpoints, separate rate limit budgets. Nothing crosses between them, including test data you would rather forget.
| Environment | Key prefix | Intended for |
|---|---|---|
| Staging | sk_test_ | Local development, CI, preview deployments |
| Production | sk_live_ | Real customers and real identity providers |
Samples on this site use sk_example_... so that nothing here can ever be a real credential. Your own keys start with sk_test_ or sk_live_.
API keys
Two values identify your application: a public client id, which is safe to put in a redirect URL, and a secret key, which is not. Copy both from the dashboard into your environment file — the secret is shown once at creation and never again.
1# Public — appears in redirect URLs2PAYCUX_CLIENT_ID=client_01HQ8ZK3M4N5P6R7S8T9V0W1X234# Secret — server only, never bundled into client code5PAYCUX_API_KEY=sk_example_12345678967# Where Paycux sends the user back after sign-in8PAYCUX_REDIRECT_URI=http://localhost:3000/callback910# 32+ characters, used to encrypt the session cookie11PAYCUX_COOKIE_PASSWORD=a-long-random-string-you-generate
- Rotate a key from the dashboard at any time; the old value stops working immediately
- Keys are scoped to one environment — a staging key cannot read production data
- Every request is attributed to the key that made it, and appears in your audit log
Install the SDK
Pick the client for your language. The rest of this page uses Node.js, but the method names are deliberately the same everywhere.
1npm install @paycux/node
Create the client once and reuse it. It is stateless, safe to share across requests, and reads the secret from the environment if you do not pass one.
1import Paycux from '@paycux/node';23export const paycux = new Paycux(process.env.PAYCUX_API_KEY, {4 clientId: process.env.PAYCUX_CLIENT_ID,5});
Redirect to AuthKit
AuthKit is the hosted sign-in experience. You do not build a form, a password reset, an MFA prompt or an SSO discovery screen — you send the person to a URL and get them back with an authorisation code.
1import { redirect } from 'next/navigation';2import { paycux } from '@/lib/paycux';34export async function GET() {5 const url = paycux.userManagement.getAuthorizationUrl({6 provider: 'authkit',7 redirectUri: process.env.PAYCUX_REDIRECT_URI,8 clientId: process.env.PAYCUX_CLIENT_ID,9 });1011 redirect(url);12}
The same call covers every authentication method you have enabled. Turning on Microsoft sign-in or requiring a second factor is a dashboard setting, not a deployment.
Handle the callback
The redirect arrives with a single-use code parameter. Exchange it for the authenticated user and a sealed session, then set a cookie and send the person where they were going.
1import { cookies } from 'next/headers';2import { redirect } from 'next/navigation';3import { paycux } from '@/lib/paycux';45export async function GET(request: Request) {6 const code = new URL(request.url).searchParams.get('code');78 const { user, sealedSession } =9 await paycux.userManagement.authenticateWithCode({10 code,11 clientId: process.env.PAYCUX_CLIENT_ID,12 session: { sealSession: true, cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD },13 });1415 const store = await cookies();16 store.set('paycux-session', sealedSession, {17 path: '/', httpOnly: true, secure: true, sameSite: 'lax',18 });1920 console.log('signed in', user.email);21 redirect('/dashboard');22}
Read the session
On every request, unseal the cookie. If the access token has expired the SDK refreshes it in place and hands you a new sealed value to store. Roles and permissions ride inside the session, so an authorisation check costs no network call.
1import { cookies } from 'next/headers';2import { paycux } from '@/lib/paycux';34export async function currentUser() {5 const store = await cookies();6 const sealed = store.get('paycux-session');7 if (!sealed) return null;89 const session = paycux.userManagement.loadSealedSession({10 sessionData: sealed.value,11 cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD,12 });1314 const result = await session.authenticate();15 if (!result.authenticated) return null;1617 // result.permissions comes from the role assigned in this organization18 return result;19}
Sessions are per organization. When someone belongs to more than one tenant, switching organization issues a new token with that tenant’s roles — see Role-Based Access Control.
Sign out
Clearing your own cookie is not enough — the person is still signed in to the identity provider. Ask for the logout URL so the session ends on both sides.
1const session = paycux.userManagement.loadSealedSession({2 sessionData: sealed.value,3 cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD,4});56const url = await session.getLogoutUrl();78const store = await cookies();9store.delete('paycux-session');1011redirect(url);
Social login
Social providers are enabled per environment in the dashboard and appear on the AuthKit screen automatically. If you would rather send someone straight to one provider — a “Continue with Google” button of your own — name it in the authorization URL.
1const url = paycux.userManagement.getAuthorizationUrl({2 provider: 'GoogleOAuth',3 redirectUri: process.env.PAYCUX_REDIRECT_URI,4 clientId: process.env.PAYCUX_CLIENT_ID,5});
The callback is identical. Accounts are matched on verified email address, so a person who signed up with a password and later uses Google keeps the same user record.
Magic Auth
Passwordless sign-in with a six-digit code sent by email. Two calls: send the code, then verify it. Useful for invitations, low-friction trials, and anyone who will never remember a password.
1// 1 — send the code2await paycux.userManagement.createMagicAuth({3 email: 'alan@foo-corp.example',4});56// 2 — verify what the person typed7const { user, sealedSession } =8 await paycux.userManagement.authenticateWithMagicAuth({9 code: '493021',10 email: 'alan@foo-corp.example',11 clientId: process.env.PAYCUX_CLIENT_ID,12 session: { sealSession: true, cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD },13 });
Next steps
Sign-in is the door. These are the rooms behind it — and the reason an enterprise buyer signs the contract.