> ## 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.

> ## Agent Instructions
> Unkey is two separate products. Compute builds, deploys, and runs apps behind a gateway. API Management issues API keys, enforces rate limits, manages identities and permissions, and reports usage. Say which product a page belongs to; a reader can use either without the other.
> Every Unkey API endpoint is an HTTP POST to https://api.unkey.com/v2/{service}.{procedure} with a root key in the Authorization: Bearer header. Root keys are workspace scoped.
> Error codes have the form err:{system}:{category}:{specific} and each has a page at /errors/{system}/{category}/{specific}.
> The word environment means production or preview in Compute. Rate limiting has four meanings on this site; the glossary lists them.

# unkey api portal create-portal

> Create a portal for one app or keyspace.

<Note>
  You need a root key with the permissions listed on this page. Create one in the dashboard under **Settings > Root Keys**. See [Permission reference](/docs/platform/root-keys/permissions-legacy) for every permission.
</Note>

Create a [portal](/docs/api-management/portal/overview) for one keyspace or one app in your workspace. Each keyspace or app can have only one portal. A second portal for the same one, or a slug that's already taken, returns 409 [`err:unkey:data:portal_already_exists`](/docs/errors/unkey/data/portal_already_exists). Calls `POST /v2/portal.createPortal`. The portal management commands are unreleased and may change without notice.

## Usage

```bash theme={"system"}
unkey api portal create-portal --slug=<slug> --display-name=<name> (--keyspace-id=<id> | --app-id=<id>) [flags]
```

## Flags

<ParamField body="--slug" type="string" required>
  Portal handle, unique in your workspace. 3 to 64 lowercase letters, digits, and hyphens, not starting or ending with a hyphen. You pass it as `--portal` to the other portal commands. End users never see it.
</ParamField>

<ParamField body="--display-name" type="string" required>
  Name shown to end users in the portal header, up to 64 characters. You can change it later.
</ParamField>

<ParamField body="--keyspace-id" type="string">
  Keyspace this portal serves. Pass exactly one of `--keyspace-id` or `--app-id`.
</ParamField>

<ParamField body="--app-id" type="string">
  App this portal serves. Pass exactly one of `--keyspace-id` or `--app-id`.
</ParamField>

<ParamField body="--enabled" type="boolean" default="true">
  Whether you can create sessions for the portal. Pass `--enabled=false` to create it turned off.
</ParamField>

<ParamField body="--logo-url" type="string">
  Absolute HTTPS URL of the logo shown in the portal header, up to 500 characters.
</ParamField>

<ParamField body="--primary-color" type="string">
  Six-digit hex color used for primary actions, for example `#6366f1`.
</ParamField>

### Shared flags

Every `unkey api` command takes these. See [CLI output and shared flags](/docs/platform/cli/output-and-flags).

<ParamField body="--root-key" type="string">
  Root key used for the request. Falls back to `UNKEY_ROOT_KEY`, then to the key stored by `unkey auth login`.
</ParamField>

<ParamField body="--api-url" type="string" default="https://api.unkey.com">
  Base URL of the API. Falls back to `UNKEY_API_BASE_URL`. You don't normally need to set it.
</ParamField>

<ParamField body="--config" type="string" default="~/.unkey/config.toml">
  Path of the config file written by `unkey auth login`. Falls back to `UNKEY_CONFIG`.
</ParamField>

<ParamField body="--output" type="string">
  Output format. Falls back to `UNKEY_OUTPUT`. `json` prints the full response. Any other value prints the request ID and `data`.
</ParamField>

<ParamField body="--body" type="string">
  Send this JSON as the whole request body instead of using the command's flags. You can't combine it with them.
</ParamField>

## Required permissions

`portal.*.create_portal`, plus read on the resource the portal will serve: `api.*.read_api` or `api.<apiId>.read_api` for a keyspace, `app.*.read_app` or `app.<appId>.read_app` for an app. Without the read permission, the call fails with 403 and "You do not have permission to point a portal at that resource." Unlike the other portal commands, a missing `portal.*.create_portal` returns 403, not 404. See [Root key permissions](/docs/platform/root-keys/permissions).

## Examples

```bash Keyspace portal theme={"system"}
unkey api portal create-portal --slug=acme-portal --display-name=Acme --keyspace-id=ks_1234abcd
```

```bash Branded app portal theme={"system"}
unkey api portal create-portal --slug=developer-portal --display-name='Developer Portal' --app-id=app_1234abcd --logo-url=https://cdn.example.com/logo.svg --primary-color=#6366f1
```

Or send the whole request as JSON:

```bash Raw body theme={"system"}
unkey api portal create-portal --body='{"slug":"acme-portal","displayName":"Acme","keyspaceId":"ks_1234abcd"}'
```

## Related

<Columns cols={2}>
  <Card title="Developer portal" href="/docs/api-management/portal/overview">
    What a portal is and how your users reach it.
  </Card>

  <Card title="create-session" href="/docs/api-management/cli/portal/create-session">
    Mint the session that lets one end user in.
  </Card>
</Columns>
