---
title: "Create portal session"
method: POST
path: "/v2/portal.createSession"
tags: ["portal"]
---

# Create portal session

`POST /v2/portal.createSession`

Create a portal session for an end user and get the URL to redirect them to.

The URL carries a single-use exchange code valid for 15 minutes, which the portal
redeems exactly once for a 24-hour access token via `portal.exchangeCode`.

**Required Permissions**

Your root key must be associated with a workspace that has an enabled portal.

## Request body

- V2PortalCreateSessionRequestBody
  - `portal` string, required — Identifies a resource by either its unique ID or its slug. Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug.
  - `externalId` string, required — The end user's identifier in the customer's system. Accepts arbitrary string values (user IDs, emails, UUIDs, etc.).
  - `scopes` string[], required — The capabilities granted to the end user in the Portal, from a fixed vocabulary. All capabilities are scoped to this end user: key capabilities (`keys:*`) apply only to keys the end user owns within the keyspace configured on the portal, and `analytics:read` returns only the end user's own verification events. An end user can never see another identity's keys or analytics. Tab visibility is derived from the scopes: - Keys tab: any `keys:*` scope - Analytics tab: `analytics:read` - Docs tab: visible when any scope is present
  - `preview` boolean — When true, creates a preview session for testing the portal experience.
  - `returnUrl` string, uri — Absolute URL the end user is sent back to when they leave the portal, or when their session expires mid-visit. Set per session rather than per portal, so one portal can serve several entry points and return each user to the page they came from. When omitted, the portal shows no return link.

## Response `200`

Session created successfully. Redirect the end user to the returned URL.

- V2PortalCreateSessionResponseBody
  - `meta` Meta, required — Metadata object included in every API response. This provides context about the request and is essential for debugging, audit trails, and support inquiries. The `requestId` is particularly important when troubleshooting issues with the Unkey support team.
    - `requestId` string, required — A unique id for this request. Always include this ID when contacting support about a specific API request. This identifier allows Unkey's support team to trace the exact request through logs and diagnostic systems to provide faster assistance.
  - `data` V2PortalCreateSessionResponseData, required
    - `id` string, required — The portal session's identifier. Not a credential: it is safe to log and to store against your own records of the end user's visit.
    - `url` string, uri, required — The full portal URL to redirect the end user to. Carries a single-use exchange code that is valid for 15 minutes.

## Other responses

- `400` — Bad request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `429` — Too Many Requests
- `500` — Internal server error

---

[API](https://skmtc.net/unkeyed/apis/unkey-api.md) · [All operations](https://skmtc.net/unkeyed/apis/unkey-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/unkeyed/unkey-api/revisions/060c53b503ce/schema)
