Skip to content

Integrations

Integrate User Management

User Management is the identity layer the rest of Paycux hangs off. This page takes you from an empty project to a working sign-in, a session you can trust on every request, and users grouped into the organizations that will later carry their SSO connection, roles and audit trail.

Before you begin

  • A server-side runtime. The secret key must never reach the browser, so a static-only front end needs a small API route or edge function alongside it.
  • Two routes you control: one that starts the sign-in and one that receives the redirect back. In development these can both live on localhost.
  • A Paycux account with at least one environment. Staging and production are separate environments with separate keys and separate user pools.
  • A cookie or session store. The examples below use an encrypted cookie, which needs a 32-character secret of your own.

Install

Every example on this page uses the Node.js client. The same calls exist in the Python, Go, Ruby, PHP and Java SDKs, following the naming conventions of each language.

terminal
1npm i @paycux/node

Configure

Two values identify your application: a publishable client ID that is safe to ship to the browser, and a secret API key that authenticates server-to-server calls. Keep the secret key in your server environment only, and rotate it if it is ever printed into a log.

.env.local
1PAYCUX_API_KEY=sk_example_7f4c1b9ad2e84c6f
2PAYCUX_CLIENT_ID=client_01HQZX8N4T
3PAYCUX_REDIRECT_URI=http://localhost:3000/callback
4PAYCUX_COOKIE_PASSWORD=a-32-character-or-longer-secret

Then, in the dashboard:

  1. 1Open Authentication and enable the methods you want to offer: email and password, magic links, social providers, or all three.
  2. 2Add http://localhost:3000/callback to the list of allowed redirect URIs. Anything not on that list is refused, which is what stops an attacker from redirecting your tokens elsewhere.
  3. 3Set the sign-out redirect so people land somewhere sensible after ending a session.
  4. 4Copy the client ID and create an API key. The secret is shown once; store it in your secret manager, not in the repository.

Implement

The flow has three moving parts. Your app sends people to a hosted sign-in URL, the callback exchanges a single-use code for a session, and from then on every request reads that session. Creating and inviting users happens through the same API from your server.

Start the sign-in

Build the authorization URL on the server so the client ID and redirect URI are always the ones you configured. The provider argument decides which sign-in surface people see first.

app/login/route.ts
1import { Paycux } from "@paycux/node";
2
3const paycux = new Paycux(process.env.PAYCUX_API_KEY);
4
5export async function GET() {
6 const url = paycux.userManagement.getAuthorizationUrl({
7 clientId: process.env.PAYCUX_CLIENT_ID,
8 redirectUri: process.env.PAYCUX_REDIRECT_URI,
9 provider: "authkit",
10 });
11
12 return Response.redirect(url);
13}

Handle the callback

The code in the query string is single use and short lived. Exchange it for a user and a sealed session, store the session in an HTTP-only cookie, and send the person on to your application.

app/callback/route.ts
1import { Paycux } from "@paycux/node";
2import { cookies } from "next/headers";
3
4const paycux = new Paycux(process.env.PAYCUX_API_KEY);
5
6export async function GET(request: Request) {
7 const code = new URL(request.url).searchParams.get("code");
8 if (!code) return Response.redirect("/login?error=missing_code");
9
10 const { user, sealedSession } = await paycux.userManagement.authenticateWithCode({
11 clientId: process.env.PAYCUX_CLIENT_ID,
12 code,
13 session: { sealSession: true, cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD },
14 });
15
16 const jar = await cookies();
17 jar.set("px_session", sealedSession, {
18 httpOnly: true,
19 secure: process.env.NODE_ENV === "production",
20 sameSite: "lax",
21 path: "/",
22 });
23
24 console.log("signed in", user.email);
25 return Response.redirect("/");
26}

Read the session on every request

Never trust a user ID that arrives from the browser. Unseal the cookie on the server, refresh it when the access token has aged out, and treat a failure as signed out.

lib/session.ts
1import { Paycux } from "@paycux/node";
2import { cookies } from "next/headers";
3
4const paycux = new Paycux(process.env.PAYCUX_API_KEY);
5
6export async function currentUser() {
7 const jar = await cookies();
8 const sealed = jar.get("px_session")?.value;
9 if (!sealed) return null;
10
11 const session = paycux.userManagement.loadSealedSession({
12 sessionData: sealed,
13 cookiePassword: process.env.PAYCUX_COOKIE_PASSWORD,
14 });
15
16 const result = await session.authenticate();
17 if (!result.authenticated) return null;
18
19 return result.user;
20}

Invite someone into an organization

Invitations are how a workspace grows without an admin handing out passwords. Paycux sends the email, records the acceptance and creates the membership with the role you name.

app/api/invite/route.ts
1import { Paycux } from "@paycux/node";
2
3const paycux = new Paycux(process.env.PAYCUX_API_KEY);
4
5export async function POST(request: Request) {
6 const { email, organizationId } = await request.json();
7
8 const invitation = await paycux.userManagement.sendInvitation({
9 email,
10 organizationId,
11 roleSlug: "member",
12 expiresInDays: 14,
13 });
14
15 return Response.json({ id: invitation.id, state: invitation.state });
16}

Verify

Run the flow end to end once before wiring it into your product. A working integration produces a visible record on both sides: a session in your browser and a user in the dashboard.

  1. 1Start your app, open /login and complete a sign-up with an address you can receive mail at.
  2. 2Confirm the callback set the px_session cookie, that it is marked HttpOnly, and that a page render shows the signed-in email.
  3. 3Delete the cookie by hand and reload. The page should behave as signed out rather than throwing.
  4. 4Open Users in the dashboard and confirm the new record, its email verification state and its last sign-in time.
  5. 5Send an invitation to a second address, accept it, and check that the organization membership appears with the role you passed.

Reference

Request and response shapes for each of these live in the API reference. Paths are relative to https://api.paycux.com.

MethodPathWhat it does
POST/user_management/authenticateExchange a code, password or refresh token for a session.
GET/user_management/usersList users with filters for email, organization and verification state.
POST/user_management/usersCreate a user directly, without the hosted sign-up screen.
GET/user_management/users/:idFetch one user with profile fields and identity links.
PUT/user_management/users/:idUpdate profile fields, email verification or password.
DELETE/user_management/users/:idDelete a user and revoke every session it holds.
POST/user_management/invitationsInvite an address into an organization with a role.
GET/user_management/organization_membershipsList which users belong to which organization.
POST/user_management/sessions/logoutRevoke the current session and return a sign-out URL.

Next steps