# API keys

> Create a key in the panel, keep it on your server, and roll or revoke it without downtime.

Keys are created and managed in **Panel › Developers › Keys**, signed in to Refabric. Manage keys
while signed in to the panel.

## Properties

| Property | Meaning |
|---|---|
| prefix | every key starts with `rf_live_` so scanners and humans recognise it |
| `secret` | the key itself — shown **once**, when it is created or rolled; we keep a hash, so the secret is shown once |
| owner | the user who created it; the key acts as that user |
| `name` | your label, e.g. `"prod-backend"` |
| `display` | the masked key (`rf_live_abcd…wxyz`) — enough to recognise it, nothing to use |
| `scopes` | what the key may do (below) |
| `expires_at` | optional; when the key stops working. Without it, the key does not expire |
| `last_used_at` | when the key was last accepted |
| `revoked_at` | when the key stopped (or, after a roll, stops) working |
| `rolled_to` | after a roll, the id of the key that replaced it |

## Create a key

1. Open **Panel › Developers › Keys** and choose **Create key**. Give it a name that says where it
   runs. A new key gets every scope.
2. **Copy the key now. You won't see it again.**
3. Set it where your server reads it:
   - macOS / Linux: `export REFABRIC_API_KEY="<key>"`
   - Windows (PowerShell): `$env:REFABRIC_API_KEY = "<key>"`
   - `.env` (keep the file out of your repository): `REFABRIC_API_KEY=<key>`
4. Test it with a read that does not spend credits:

```bash
curl -s "$REFABRIC_API/account/balance" -H "Authorization: Key $REFABRIC_API_KEY"
```

A `200` with your balance means the key works. `401 invalid_api_key` means the key is wrong,
revoked or expired ([Authentication](https://docs.refabric.com/api-reference/platform/authentication)).

## Scopes

A scope is one thing a key may do. A new key gets every scope.

<!-- scopes — written by hand, checked against the live scope list (x-refabric-scopes) at docs build; the build fails if they differ -->
| Scope | Allows |
|---|---|
| `tasks:read` | Estimate a task's cost, and narrow the task list to your surface (reading tasks needs no key). |
| `tasks:run` | Run tasks (this spends credits). |
| `jobs:read` | Read the status and results of your jobs. |
| `jobs:cancel` | Cancel your running jobs. |
| `files:read` | Read your files, uploads and the library. |
| `files:write` | Upload and delete files. |
| `account:read` | Read your credit balance and usage. |
<!-- /generated:scopes -->

Reference reads (`/v1/concepts`, `/v1/vocab`, `/v1/errors`, `/v1/recipes`), `/v1/meta` and
`/v1/pricing` accept any valid key. A key without the scope an operation needs is answered
`403 scope_missing`.

## Roll and revoke

**Roll** (rotate without downtime): in **Panel › Developers › Keys**, choose **Roll** on the key and
pick a grace period — how long the OLD key keeps working (at most
`limits.api_keys.roll_grace_max_seconds` of `GET /v1/meta`; the default is none). The answer is
the NEW key, with its `secret` shown once. The old key's `rolled_to` names the new one and its
`revoked_at` is the moment it stops. Deploy the new key, then let the old one lapse, or revoke it
to end the grace period early.

**Revoke**: choose **Revoke** on the key. Revocation is immediate: the key fails on its next
request. Jobs it already started keep running, and their webhooks are still delivered.

A key's expiry is set when it is created.

## Recommendations

- One key per system and environment; name it after where it runs.
- Set `expires_at` for keys given to contractors or used in experiments.
- Roll keys on a schedule and whenever someone with access leaves.
- Never use a key from a browser: a key sent from a web page is refused with
  `403 api_key_not_allowed_here`, on every endpoint.
- If a key leaks, follow [Security → leaked key](https://docs.refabric.com/api-reference/platform/security#if-a-key-leaks).
