Skip to main content

Documentation Index

Fetch the complete documentation index at: https://unkey.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

The Customer Portal is a white-labeled web app you can offer to your end users. They get key management, usage analytics, and API documentation — without you building any UI. Authentication uses a Stripe-style session flow: your backend creates a session, redirects the user, and the portal handles the rest.
The portal is in development. Key management, analytics, and docs pages are placeholder UI for now.

How it works

Your Backend                    Unkey API                     Portal
    │                              │                            │
    ├─ POST /v2/portal.createSession ─►│                        │
    │◄── sessionId + portal URL ───┤                            │
    │                              │                            │
    ├─ Redirect user to portal URL ─────────────────────────────►│
    │                              │◄─ POST /v2/portal.exchangeSession ─┤
    │                              │──── browser session token ──►│
    │                              │                            │
    │                              │◄── Direct API calls ───────┤
  1. Your backend authenticates the user in your own system
  2. Your backend calls POST /v2/portal.createSession with a root key
  3. You redirect the user to the returned portal URL
  4. The portal exchanges the session ID for a 24-hour browser session
  5. The browser calls Unkey API directly with the session token

1. Configure a portal

Enable the Customer Portal for your workspace in the Unkey dashboard.
Dashboard configuration UI is coming soon. During early access, reach out to the Unkey team to get your portal configured.
When configuring your portal, you’ll choose a slug — a short, human-readable identifier like my-portal or billing-dashboard. Use this slug when creating sessions. Slugs must be 3–64 characters, lowercase alphanumeric and hyphens only, and cannot start or end with a hyphen. Optionally, you can customize branding with your logo and brand colors.

2. Create a session

When your user wants to access the portal, create a session from your backend:
curl -X POST https://api.unkey.com/v2/portal.createSession \
  -H "Authorization: Bearer YOUR_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "my-portal",
    "externalId": "user_123",
    "permissions": ["api.*.read_key", "api.*.create_key", "api.*.read_analytics"]
  }'
The response:
{
  "meta": { "requestId": "req_..." },
  "data": {
    "sessionId": "pst_xxx",
    "url": "https://portal.unkey.com/?session=pst_xxx",
    "expiresAt": 1742000000000
  }
}

Required parameters

ParameterTypeDescription
slugstringHuman-readable identifier for your portal configuration
externalIdstringYour user’s identifier in your system
permissionsstring[]Controls which portal tabs are visible

Optional parameters

ParameterTypeDescription
previewbooleanShows a “Preview mode” banner — useful for testing as a specific user
curl -X POST https://api.unkey.com/v2/portal.createSession \
  -H "Authorization: Bearer YOUR_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "my-portal",
    "externalId": "user_123",
    "permissions": ["api.*.read_key", "api.*.read_analytics"],
    "preview": true
  }'

3. Redirect your user

Send the user to the portal URL. The session ID is valid for 15 minutes and can only be used once.
// In your backend route handler
return Response.redirect(data.url, 302);
The portal will:
  1. Exchange the session ID for a 24-hour browser session
  2. Set an httpOnly cookie
  3. Redirect to the first visible tab based on permissions

Permissions and tabs

Permissions use the RBAC tuple format {resourceType}.{resourceId}.{action}. Use * as the resourceId to grant access to all resources of that type. Tab visibility is derived from the action segment (third part) of each permission:
ActionTab
read_key, create_key, update_key, delete_keyAPI Keys
read_analyticsAnalytics
Any permission presentDocumentation
Examples:
  • api.*.read_key → shows the Keys tab
  • api.api_123.create_key → shows the Keys tab (specific resource)
  • api.*.read_analytics → shows the Analytics tab
  • Docs tab is visible whenever at least one permission is present
The API requires at least one permission. An empty permissions array is rejected with HTTP 400.

Session lifecycle

TokenLifetimeUsage
Session ID (pst_xxx)15 minutesSingle-use, exchanged for browser session
Browser session24 hoursStored as httpOnly cookie, used for API calls
When the browser session expires:
  • If return_url is set on the portal config → redirects to {return_url}?reason=session_expired
  • Otherwise → shows a “Session expired” error page

Branding

The portal supports basic white-labeling:
SettingDefault
Primary color#2563eb
LogoNone
Logo URLs must be HTTPS.

Error responses

ScenarioStatusMessage
Missing or invalid JSON body400Bad Request
Invalid root key401Unauthorized
Portal disabled403Portal is disabled.
Portal config not found404Portal configuration not found.
Invalid/expired/used session on exchange401Session is invalid, expired, or has already been used.
Last modified on May 6, 2026