# POST /v1/keys

> Create a test or live key.

In [Account API](https://vestra.ai/developers/reference/api/account.md): Your company's account: who is calling, its keys, its caps, what it spent and the models it may use.

Send `Authorization: Bearer vk_test_...` on every call.

Create a test or live key. The full key is shown once.

Your API key, scope `admin` or `all`. On the card: [`keys`](https://vestra.ai/developers/keys.md). Every call here is a checked sample.

## Request

Body, if you send one:

- `name` (`string`): A name for the key, to tell it apart later, up to 100 characters. Limits: 1 to 100 characters. Example: `production`.
- `scopes` (`("all" | "runtime" | "setup" | "admin")[]`): What it may call: `all` alone, or 1 to 3 of `runtime`, `setup` and `admin`. Absent: `all`. A key only gives the scopes it has. Limits: 1 to 3 items. Example: `["runtime"]`.
- `expires_at` (`string (date and time)`): When the key stops working, an ISO 8601 date and time in the future. Absent: never.

## Answers 201

- `id` (`string`): The key's id. Example: `key_8f2k`.
- `object` (`"api_key"`): Always `api_key`.
- `mode` (`"live" | "test"`): `live` or `test`: what the key reaches. A test key sees only test users, test deployments and test money.
- `name` (`string | null`): The name you gave it; null when it has none.
- `prefix` (`string`): The start of the secret, to tell keys apart: `vk_live_` or `vk_test_` and a few characters. Example: `vk_test_8f2k`.
- `last4` (`string`): The last four characters of the secret.
- `scopes` (`("all" | "runtime" | "setup" | "admin")[]`): What the key may call: `all`, or any of `runtime` (conversations, work, routines, connected apps, files, memory, usage), `setup` (deployments, tests, secrets) and `admin` (users and keys).
- `status` (`"active" | "expiring" | "expired" | "revoked"`): `active`: works, with no end. `expiring`: works until `expires_at` (a rolled key in its grace period, or one made to expire). `expired` or `revoked`: refused.
- `created_at` (`string`): When it was made, as an ISO 8601 date and time in UTC.
- `last_used_at` (`string | null`): When it last made a call; null when it never has.
- `expires_at` (`string | null`): When it stops working; null when it never does.
- `revoked_at` (`string | null`): When it was revoked; null while it is not.
- `secret` (`string`): The whole key. It is shown this once: store it now, as Vestra keeps only its hash. Example: `vk_test_...`.

## Code

**TypeScript**

```ts
const key = await vestra.keys.create();
```

**Python**

```python
key = vestra.keys.create()
```

**CLI**

```bash
vestra keys create
```

**HTTP**

```bash
# Check your key. See your company, this key, and whether it is test or live.
curl "$VESTRA_BASE_URL/v1/me" \
  -H "Authorization: Bearer $VESTRA_API_KEY"

# Create a key for CI. This one can only set things up. Its secret is shown only once.
curl "$VESTRA_BASE_URL/v1/keys" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci", "scopes": ["setup"] }'

# Roll a key. You get a new secret, and the old one keeps working for an hour.
curl "$VESTRA_BASE_URL/v1/keys/key_3vd/roll" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "grace_seconds": 3600 }'

# Revoke a key. It stops working at once.
curl -X DELETE "$VESTRA_BASE_URL/v1/keys/key_3vd" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**: No sample in your language for this route, so here it is over HTTP.
