Sign a user in
Your backend mints a session
Call
portal.createSession with the portal, the user’s externalId, and the scopes they should have. You get { "id": "ps_...", "url": "https://portal.unkey.com/?code=pec_..." }. The URL works once, within 15 minutes.The portal exchanges the code
The portal swaps the code for an access token that lasts 24 hours. If the code is expired, already used, or unknown, the user sees
err:unkey:authentication:portal_session_not_found, “Session is invalid, expired, or has already been used.”portal.exchangeCode yourself if you build your own portal front end. It returns { "accessToken": "pat_...", "expiresAt": <ms> }.
Request
You need a root key with the permissions listed on this page. Create one in the dashboard under Settings > Root Keys. See Permission reference for every permission.
string
required
The portal’s
pc_ ID or slug.string
required
The user’s ID in your system, 1 to 256 characters. A session for
user_123 shows the keys whose identity is user_123.string[]
required
One or more of
keys:read, keys:reroll, and analytics:read. Scopes decide what the user can see and do. See What portal users can do. keys:reroll and analytics:read each need keys:read too. Without it, the request fails with 400 and err:unkey:application:invalid_input.string
Full URL, up to 500 characters, to send the user back to when they leave or the session expires. You set it per session, so different users can go back to different pages.
boolean
default:"false"
Create a preview session to try the portal yourself.
Permissions your root key needs
Your root key needsportal.*.create_portal_session or portal.<portalId>.create_portal_session. Without it, the request fails with 404, not 403.
It also needs a matching permission for each scope, on every keyspace the portal shows, either as * or for each api_ ID:
If the root key is missing one, the whole request fails with 403. A disabled portal can’t create sessions at all.
What ends a session
A session ends when its 24 hour token expires, or when the portal is deleted or pointed at a different keyspace or app. That usually takes effect within about 10 seconds, but can take up to 5 minutes. Disabling a portal doesn’t end live sessions. You can’t end a single session, so choose scopes with the 24 hour lifetime in mind. Creating and exchanging a session writeportal.session.create and portal.session.exchange audit log entries. What the user does in the portal is logged under a portalEndUser actor.