> ## 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 keys create-key

> Create an API key in a keyspace from the command line.

<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 key. The plaintext comes back once in this response. You can't fetch it again unless you pass `--recoverable`. Calls `POST /v2/keys.createKey`. See [Creating keys](/docs/api-management/keys/creating-keys).

## Usage

```bash theme={"system"}
unkey api keys create-key --api-id=<api id> [flags]
```

## Flags

<ParamField body="--api-id" type="string" required>
  Id of the API (keyspace) the key belongs to.
</ParamField>

<ParamField body="--byte-length" type="integer">
  Length of the random part of the key in bytes. The API accepts 16 to 255. If you leave the flag off, it uses the keyspace's default byte length, or 16 if the keyspace doesn't set one.
</ParamField>

<ParamField body="--credits" type="string">
  JSON object with `remaining` and an optional `refill` of `interval` (`daily` or `monthly`), `amount`, and `refillDay`. `refillDay` is a day of the month from 1 to 31. It's required for `monthly`, and a monthly refill without it fails with `400`. It's ignored for `daily`.
</ParamField>

<ParamField body="--enabled" type="boolean" default="true">
  Whether the key can be used. Create it disabled to turn it on later.
</ParamField>

<ParamField body="--expires" type="integer">
  Unix timestamp in milliseconds after which the key stops verifying.
</ParamField>

<ParamField body="--external-id" type="string">
  Your identifier for the user or tenant, up to 255 characters. Links the key to the identity with this external id, and creates the identity if needed.
</ParamField>

<ParamField body="--meta" type="string">
  JSON object stored on the key and returned by every verification. At most 100 top-level properties.
</ParamField>

<ParamField body="--name" type="string">
  Name shown in the dashboard, up to 255 characters.
</ParamField>

<ParamField body="--permissions" type="string[]">
  Comma-separated permission slugs to grant directly, at most 1000 of them. A slug that doesn't exist yet is created.
</ParamField>

<ParamField body="--prefix" type="string">
  Prefix added to the start of the key so users can tell keys apart, for example `prod`. Up to 16 characters of letters, digits, and underscores. If you leave it off, the keyspace's default prefix is used, if it has one.
</ParamField>

<ParamField body="--ratelimits" type="string">
  JSON array of rate limits, each with `name`, `limit`, `duration` in milliseconds, and `autoApply`.
</ParamField>

<ParamField body="--recoverable" type="boolean" default="false">
  Store the plaintext encrypted so `get-key --decrypt` can return it later. Needs `encrypt_key`. Fails with `412` unless the keyspace has key encryption turned on, which only we can do, through a support request.
</ParamField>

<ParamField body="--roles" type="string[]">
  Comma-separated role names to assign, at most 100 of them. Unlike permissions, each role must already exist. An unknown name fails the whole call.
</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

`api.*.create_key` or `api.<apiId>.create_key`. `--recoverable` also needs `api.*.encrypt_key` or `api.<apiId>.encrypt_key`. Without the permission you get a 404, not a 403, so the response doesn't reveal whether the API exists. See [Root key permissions](/docs/platform/root-keys/permissions).

## Examples

```bash Plain key theme={"system"}
unkey api keys create-key --api-id=api_1234abcd --prefix=prod --name='Payment Service Key'
```

```bash Key for a user with roles theme={"system"}
unkey api keys create-key --api-id=api_1234abcd --external-id=user_1234abcd --roles=api_admin,billing_reader
```

```bash Key with credits and a rate limit theme={"system"}
unkey api keys create-key --api-id=api_1234abcd \
  --credits='{"remaining":1000,"refill":{"interval":"monthly","amount":1000,"refillDay":1}}' \
  --ratelimits='[{"name":"requests","limit":100,"duration":60000,"autoApply":true}]'
```

Or send the whole request as JSON:

```bash Raw body theme={"system"}
unkey api keys create-key --body='{"apiId":"api_1234abcd","prefix":"prod","name":"Payment Service Key","externalId":"user_1234abcd","meta":{"plan":"pro"}}'
```
