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

# Create portal

`POST /v2/portal.createPortal`

Create a portal for one app or keyspace in your workspace.

Unreleased and subject to change without notice.

Send exactly one of `keyspaceId` or `appId`. That resource must belong to your
workspace, and it can back only one portal, so a second portal for the same
resource is a **409**.

`displayName` is what your end users see. It is yours to set and change
independently of the resource the portal serves.

**Required Permissions**

Your root key must have `portal.*.create_portal`. A grant scoped to a specific
portal id does not authorize creation, because the id does not exist yet.

## Request body

- union
  - object
    - `slug` string, required — URL-safe handle for this portal, unique within your workspace. Lowercase alphanumerics and single hyphens, 3-64 characters, not starting or ending with a hyphen.
    - `displayName` string, required — Human-readable name your end users see in the portal header and page titles. Unlike `slug` it is not part of any URL, so it can be changed freely.
    - `keyspaceId` string, required — The id of the keyspace this portal serves keys for. Must belong to your workspace. A portal serves exactly one resource, so `keyspaceId` and `appId` are mutually exclusive.
    - `appId` string — The id of the app this portal serves keys for. Must belong to your workspace. A portal serves exactly one resource, so `appId` and `keyspaceId` are mutually exclusive.
    - `enabled` boolean — Whether sessions can be minted for this portal immediately. Defaults to true; send false to create it dormant and enable it later.
    - `logoUrl` string, uri — Absolute `https://` URL of the logo shown in the portal header. Loaded by your end users' browsers, so the host you name receives their IP and user agent on every page view.
    - `primaryColor` string — Six-digit hex colour used for primary actions and accents in the portal.
  - object
    - `slug` string, required — URL-safe handle for this portal, unique within your workspace. Lowercase alphanumerics and single hyphens, 3-64 characters, not starting or ending with a hyphen.
    - `displayName` string, required — Human-readable name your end users see in the portal header and page titles. Unlike `slug` it is not part of any URL, so it can be changed freely.
    - `keyspaceId` string — The id of the keyspace this portal serves keys for. Must belong to your workspace. A portal serves exactly one resource, so `keyspaceId` and `appId` are mutually exclusive.
    - `appId` string, required — The id of the app this portal serves keys for. Must belong to your workspace. A portal serves exactly one resource, so `appId` and `keyspaceId` are mutually exclusive.
    - `enabled` boolean — Whether sessions can be minted for this portal immediately. Defaults to true; send false to create it dormant and enable it later.
    - `logoUrl` string, uri — Absolute `https://` URL of the logo shown in the portal header. Loaded by your end users' browsers, so the host you name receives their IP and user agent on every page view.
    - `primaryColor` string — Six-digit hex colour used for primary actions and accents in the portal.

## Response `200`

Portal created successfully.

- V2PortalCreatePortalResponseBody
  - `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` V2PortalCreatePortalResponseData, required
    - `portalId` string, required — The unique identifier of the newly created portal, generated by Unkey. Always begins with 'pc_' followed by a unique alphanumeric sequence.

## Other responses

- `400` — Bad request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — The named app or keyspace does not exist in your workspace.
- `409` — The slug is taken in your workspace, or the named app or keyspace already backs a portal.
- `429` — Too Many Requests
- `500` — Internal server error

## Changes

- **2026-08-25** `4b9df35712fd` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/unkeyed/apis/unkey-api/changes/v2/portal.createPortal/post.md)

---

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