---
title: API keys
description: Scripto CLI keys — the scripto_ Bearer prefix, long-lived by default, named and revocable, with a surfaced last-used timestamp and an optional expiry.
---

The CLI authenticates with a **`scripto_` API key**, sent as `Authorization: Bearer scripto_…`. Better Auth's apiKey plugin owns these keys; a key's owner is its `referenceId` (your user id).

## Key policy

| Property | Behaviour |
|---|---|
| **Prefix** | Every CLI key starts with `scripto_`. |
| **Lifetime** | **Long-lived by default** — no forced expiry. An agent can't easily re-authenticate mid-run, so keys persist. |
| **Named** | Every key has a human-readable name (defaults to `scripto-cli` for OTP-minted keys). |
| **Revocable** | Any key can be revoked from web **Settings → API keys** or via `DELETE /api/keys/[id]`. |
| **Last-used surfaced** | A last-used timestamp is shown so a stale key is visible and killable. |
| **Optional expiry** | Minting offers an optional expiry for users who want one. |

<Note>

The security weight for the public surface is carried by the OAuth path's short-lived access tokens and a rate limit on the open mint endpoint — not by forcing CLI key rotation. A CLI key being long-lived is a deliberate ergonomic choice for agents.

</Note>

## How a key is minted

<Steps>

<Step title="Over OTP (no browser)">

`scripto auth login-complete --email … --code …` verifies the code and mints a key bound to your user. The raw key is returned **once** and stored in your active profile.

</Step>

<Step title="From web Settings">

Create a named key in **Settings → API keys**, copy it once, and store it with `scripto config set --api-key scripto_...`.

</Step>

</Steps>

## The raw value is shown once

A key's raw secret is returned **only at creation** — by `login-complete`, or by `POST /api/keys`. It is never retrievable again. Listing keys (`GET /api/keys`) returns metadata only (id, name, prefix, start, timestamps), never the secret.

## Where keys live locally

The CLI stores keys as profiles in `~/.config/scripto/config.json` (mode `0600`). One key per profile; the active profile is used unless you pass `--profile` or `--api-key`. See [Configuration](/cli/configuration).

## Revoking

```bash
# Web: Settings → API keys → revoke.
# HTTP:
curl -sS -X DELETE https://scripto.codika.io/api/keys/<keyId> \
  -H "Authorization: Bearer $SCRIPTO_API_KEY"
```

Revocation is immediate; a revoked key fails the next request with `unauthenticated`.

## Next

- **[Configuration](/cli/configuration)** — profiles, env vars, the resolution chain.
- **[Authentication](/api-reference/authentication)** — the Bearer header on the HTTP API.
- **[Key endpoints](/api-reference/list-keys)** — list, create, revoke.
