Integrations
Integrate Admin Portal
Admin Portal replaces the setup call. You generate a signed, short-lived link, your customer's IT admin opens it and configures their own SSO connection or directory, and you find out it worked from a webhook. The whole integration is one endpoint.
Before you begin
- An organization for the customer. The portal session is scoped to it, and that scoping is what keeps one customer out of another's configuration.
- An admin surface of your own where a link can be generated. Anyone who can create a portal link can configure that tenant's identity, so protect the route.
- A webhook endpoint if you want to know when setup finishes without asking.
- Your logo and brand colour, if the portal should look like part of your product.
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.
1npm i @paycux/node
Configure
The portal has no separate credentials. It uses your API key, and the return URL you pass decides where the admin lands when they are finished.
1PAYCUX_API_KEY=sk_example_7f4c1b9ad2e84c6f2PAYCUX_PORTAL_RETURN_URL=https://yourapp.example/settings/sso3PAYCUX_WEBHOOK_SECRET=whsec_example_2b6d9f31
Then, in the dashboard:
- 1Open Admin Portal and upload your logo, set the brand colour and write the short intro line the admin reads first.
- 2Choose which intents to allow: SSO, directory sync, domain verification, or a combination.
- 3Set the link lifetime. A few minutes is right for a link you generate on demand; longer only if you email it.
- 4Set the default return URL, then override it per link when you need to send someone back to a specific screen.
- 5Subscribe to connection and directory events so setup completion reaches your app on its own.
Implement
Generate the link at the moment the admin clicks, never in advance, and never store it. Portal links are bearer credentials with an expiry, and the shorter their life the less there is to leak.
Generate a portal link
Check the caller's permission first, then request a link for the intent you want. Redirect straight to it rather than rendering it into the page, so it does not end up in a screenshot or a browser history.
1import { Paycux } from "@paycux/node";2import { requirePermission } from "@/lib/authz";34const paycux = new Paycux(process.env.PAYCUX_API_KEY);56export async function POST(request: Request) {7 const { organizationId } = await requirePermission("organization:manage");8 const { intent } = await request.json();910 const link = await paycux.portal.generateLink({11 organization: organizationId,12 intent,13 returnUrl: process.env.PAYCUX_PORTAL_RETURN_URL,14 successUrl: process.env.PAYCUX_PORTAL_RETURN_URL + "?setup=done",15 });1617 return Response.redirect(link.url, 303);18}
Show the current setup state
Your settings screen should say what is connected before it offers to connect anything. Read the organization's connections and directories and render one row each.
1import { Paycux } from "@paycux/node";23const paycux = new Paycux(process.env.PAYCUX_API_KEY);45export async function ssoState(organizationId: string) {6 const [connections, directories] = await Promise.all([7 paycux.sso.listConnections({ organizationId }),8 paycux.directorySync.listDirectories({ organizationId }),9 ]);1011 return {12 sso: connections.data.map((c) => ({ id: c.id, type: c.connectionType, state: c.state })),13 directory: directories.data.map((d) => ({ id: d.id, type: d.type, state: d.state })),14 };15}
React to a finished setup
The admin will not always tell you they are done. Listen for the activation events and update your own onboarding checklist from them.
1import { Paycux } from "@paycux/node";23const paycux = new Paycux(process.env.PAYCUX_API_KEY);45export async function POST(request: Request) {6 const payload = await request.text();7 const signature = request.headers.get("paycux-signature");89 const event = paycux.webhooks.verify({10 payload,11 signature,12 secret: process.env.PAYCUX_WEBHOOK_SECRET,13 });1415 if (event.event === "connection.activated" || event.event === "dsync.activated") {16 await completeOnboardingStep(event.data.organizationId, event.event);17 }1819 return new Response("ok", { status: 200 });20}
Verify
Walk the portal as your customer will, from your own settings screen rather than from a link you pasted into the address bar.
- 1Open your settings screen as an organization admin and confirm the setup button is hidden for a member without the permission.
- 2Click through to the portal and confirm it shows your logo, your colour and only the intents you enabled.
- 3Complete an SSO setup with a provider tenant you control and confirm you are returned to your success URL.
- 4Confirm your app received the activation event and that the settings screen now shows the connection as active.
- 5Reuse the same portal link after it expires and confirm it is refused rather than reopened.
Reference
Request and response shapes for each of these live in the API reference. Paths are relative to https://api.paycux.com.
| Method | Path | What it does |
|---|---|---|
| POST | /portal/generate_link | Create a short-lived setup link for one organization. |
| GET | /organizations/:id | Read the organization the link will be scoped to. |
| GET | /connections | List SSO connections for an organization. |
| GET | /directories | List directories for an organization. |
| GET | /organization_domains | List claimed domains and their verification state. |
| POST | /organization_domains | Claim a domain so it can be verified in the portal. |