# AfterPack API keys

Minting, scoping, using, and revoking the key that turns a local build into a Pro Cloud build.

Source: https://www.afterpack.dev/docs/dashboard/api-keys

An API key turns a local build into a **Pro Cloud** build. Without one, [`npx afterpack@latest`](https://www.afterpack.dev/docs/cli#usage) and every [plugin](https://www.afterpack.dev/docs/frameworks) run locally with [Free](https://www.afterpack.dev/docs/tiers) protection and report nothing. With one, the build's files go to AfterPack's cloud engine, metered against your workspace and recorded in the dashboard.

## Where keys live

Keys live under a **project**, on its *Keys* page: a key is bound to one project, and its builds inherit that project, grouping [builds](https://www.afterpack.dev/docs/dashboard/builds), [protection maps](https://www.afterpack.dev/docs/protection-map), and [usage](https://www.afterpack.dev/docs/dashboard/usage) under it. In every other sense a key is a workspace-wide credential: it draws on the workspace's allowance and is gated by [workspace role](https://www.afterpack.dev/docs/dashboard/workspaces).

## Creating one

Only workspace owners and admins can mint a key, and only from the dashboard. A key cannot mint another key. The create dialog asks for:

- **Name** (required, up to 100 characters): what it is for, for example *CI pipeline*. It is the only thing distinguishing rows later, so name it after what will hold it.
- **Expires on** (optional, under *advanced*): a date, anchored to end-of-day local time. A past date returns an error.
- **Allowed IPs** (optional, under *advanced*): a comma-separated list, for example `10.0.0.0/8, 203.0.113.7`.

> **The key is shown exactly once**
>
> The raw key is returned once and never stored; only a hash and a short non-secret prefix are kept. Copy it before closing the dialog. If you lose it, revoke it and mint another. It cannot be shown again.

Keys look like `ap_v1_` followed by 40 random base62 characters, and the list shows only the stored prefix (`ap_v1_` plus six characters) with a `*`. A key attributes builds to its project but does not restrict which project a build can target. [`scope.allowedProjects`](https://www.afterpack.dev/docs/cloud-api) returns an error.

## Using one

The engine resolves [`key`](https://www.afterpack.dev/docs/config#key) from `--key=` first, then the environment, then `afterpack.json`. Set [`AFTERPACK_key`](https://www.afterpack.dev/docs/config#key) as a secret in [CI](https://www.afterpack.dev/docs/builds), or put it in `afterpack.json` for a local trial:

```json
{ "key": "ap_v1_..." }
```

No key in either place means the build runs locally: the default, and the entire [Free tier](https://www.afterpack.dev/docs/deployment-modes) path.

> **A key belongs in CI, not in the repo**
>
> `afterpack.json` suits a local trial run, but committing it publishes a credential that spends your workspace's allowance. Use [`AFTERPACK_key`](https://www.afterpack.dev/docs/config#key) for anything shared. See [Build & CI](https://www.afterpack.dev/docs/builds).

## The key list

| Column | What it is |
| --- | --- |
| **Name** | What you called it. |
| **Key** | The stored display prefix, `ap_v1_xxxxxx*`. |
| **Created** | When it was minted. |
| **Expires** | The expiry date, or *Never*. |
| **Last used** | When a build last authenticated with it, useful for finding a key nothing uses anymore. |
| **Status** | *Active* or *Revoked*. |

## Rotating

There is no in-place rotate. Rotation is always **create new, then revoke old**, and since a key never expires on its own unless you set one at creation, the two can overlap for as long as the rollout takes:

1. Create the new key.
2. Deploy it wherever the old one was used (CI secrets, deploy configs).
3. Confirm builds are authenticating with it via the **Last used** column.
4. Revoke the old one.

## Revoking

Revoking is immediate and cannot be undone: the key stops working on the next request. The row stays visible, marked *Revoked*, instead of disappearing, so you can see what it was used for. A key's creator can revoke it, and so can any admin or owner in its workspace, so a key minted by someone who has since left is still revocable. Revoking is a dashboard action: an API key cannot revoke a key, its own included. A key revoked mid-build fails the CLI's next request with it.

> **If a key leaks, revoke it**
>
> Revocation is effective globally within seconds and is the complete fix: AfterPack never stores the raw key after creation, only an opaque id, the non-secret prefix, and a salted hash, so there is no cache or log to scrub afterward. If you cannot reach the dashboard, email **security@afterpack.dev**.

## Limits a keyed build runs under

| | Limit |
| --- | --- |
| Requests per key, per minute | 10 on Free, 100 on a paid plan |
| Requests per IP, per minute | 100 |
| Bytes per file | 50 MB |
| Files per batch | 200 |
| Bytes per batch | 500 MB |

A build that exceeds a limit [fails](https://www.afterpack.dev/docs/diagnostics#exit-codes) rather than falling back to unobfuscated output. See [Cloud API](https://www.afterpack.dev/docs/cloud-api) for the wire protocol and error codes.

## When builds don't appear

Almost always one of these:

1. **No key resolved**: the build ran locally. Check that [`AFTERPACK_key`](https://www.afterpack.dev/docs/config#key) is set where the build runs.
2. **The key is revoked or expired**: the list says which.
3. **You are looking at the wrong project**: the build is attributed to the key's project, which may differ from the one you have open.

## Next

- [Builds](https://www.afterpack.dev/docs/dashboard/builds): what a keyed build produces.
- [Usage & billing](https://www.afterpack.dev/docs/dashboard/usage): what it costs.
- [Cloud API](https://www.afterpack.dev/docs/cloud-api): the protocol the key authenticates.
- [Workspaces & projects](https://www.afterpack.dev/docs/dashboard/workspaces): the roles that gate this page.
