# API keys API

> List, create and revoke ak_live_ API keys. Secrets are shown once and stored only as a SHA-256 hash.

Source: https://akaphone-docs.pages.dev/api/keys/

API keys authenticate the MCP server, scripts and CI. You can manage them in the dashboard under **API keys**, or with these endpoints. A key has the full rights of your account, including managing other keys, so treat it like a password.

## The key object

```json
{
  "id": "key_01m5vqsywgc25cftvdhxzj",
  "name": "github-actions",
  "prefix": "ak_live_urQu",
  "last_used_at": "2026-10-26T09:14:02.000Z",
  "created_at": "2026-10-20T15:44:31.000Z"
}
```

| Field | Type | Description |
|---|---|---|
| `id` | string | `key_…`. Use it to revoke the key. |
| `name` | string or null | Your label. |
| `prefix` | string | The first 12 characters of the secret, to recognise it. |
| `last_used_at` | string or null | Last use, updated at most once a minute. |
| `created_at` | string | When it was created. |

## List keys

`GET /v1/keys`

Returns your active (not revoked) keys, newest first.

```bash title="curl"
curl https://akaphone.abhgnx-417.workers.dev/v1/keys \
  -H "Authorization: Bearer $AKAPHONE_API_KEY"
```
```typescript title="TypeScript"
const { keys } = await fetch("https://akaphone.abhgnx-417.workers.dev/v1/keys", {
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}` },
}).then((r) => r.json());
```
```python title="Python"
import os, requests

keys = requests.get(
    "https://akaphone.abhgnx-417.workers.dev/v1/keys",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
).json()["keys"]
```

**Response** `200 OK`

```json
{
  "keys": [
    { "id": "key_01m5vqsywgc25cftvdhxzj", "name": "github-actions", "prefix": "ak_live_urQu", "last_used_at": "2026-10-26T09:14:02.000Z", "created_at": "2026-10-20T15:44:31.000Z" }
  ]
}
```

## Create a key

`POST /v1/keys`

| Body field | Type | Description |
|---|---|---|
| `name` | string | Optional, up to 64 characters. |

```bash title="curl"
curl -X POST https://akaphone.abhgnx-417.workers.dev/v1/keys \
  -H "Authorization: Bearer $AKAPHONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "github-actions"}'
```
```typescript title="TypeScript"
const { key, secret } = await fetch("https://akaphone.abhgnx-417.workers.dev/v1/keys", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "github-actions" }),
}).then((r) => r.json());
```
```python title="Python"
created = requests.post(
    "https://akaphone.abhgnx-417.workers.dev/v1/keys",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
    json={"name": "github-actions"},
).json()
secret = created["secret"]
```

**Response** `201 Created`

```json
{
  "key": { "id": "key_01m5vqsywgc25cftvdhxzj", "name": "github-actions", "prefix": "ak_live_urQu", "last_used_at": null, "created_at": "2026-10-26T09:30:00.000Z" },
  "secret": "ak_live_urQuj41lKvo2VYp2kBoFqRGw5ig661RoAtM5uTvyrhB"
}
```

`secret` is returned **only in this response**. AkaPhone keeps a SHA-256 hash, so it cannot show the secret again.

| Error | When |
|---|---|
| `409 conflict` | You already have 25 active keys (*At most 25 active API keys*). Revoke one first. |

## Revoke a key

`DELETE /v1/keys/:id`

Revokes the key immediately. Requests using it get `401 unauthorized` from then on. You can revoke the key you are calling with.

```bash title="curl"
curl -X DELETE https://akaphone.abhgnx-417.workers.dev/v1/keys/key_01m5vqsywgc25cftvdhxzj \
  -H "Authorization: Bearer $AKAPHONE_API_KEY"
```
```typescript title="TypeScript"
await fetch("https://akaphone.abhgnx-417.workers.dev/v1/keys/key_01m5vqsywgc25cftvdhxzj", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.AKAPHONE_API_KEY}` },
});
```
```python title="Python"
requests.delete(
    "https://akaphone.abhgnx-417.workers.dev/v1/keys/key_01m5vqsywgc25cftvdhxzj",
    headers={"Authorization": f"Bearer {os.environ['AKAPHONE_API_KEY']}"},
)
```

**Response** `204 No Content`. `404 not_found` if the key does not exist or is already revoked.

## Good practice

- One key per machine, pipeline or teammate, named after it. Revoking one does not disturb the others.
- Store keys in a secrets manager or your CI's secret store, never in source code or front-end bundles.
- If a key leaks, revoke it first and create the replacement second.
