---
title: API keys
description: Programmatic API key management. Requires admin or owner role on the calling key.
section: API Reference
order: 9
---
Use these endpoints to issue, list, update, and revoke API keys for
your organization. The full key string (`pk_live_…`) is returned **only
once** on creation — store it immediately.

```python
from pictograph import Client
client = Client()
```

## list

```python
keys = client.api_keys.list()                              # active org
keys = client.api_keys.list(organization_id="org-uuid")    # explicit org
for k in keys:
    print(k.name, k.role, k.key_prefix, k.last_used_at)
```

Returns `list[ApiKey]` — metadata only (no full key strings).

## create

```python
created = client.api_keys.create(
    organization_id="org-uuid",
    name="ci-pipeline",
    role="member",                # viewer / member / admin / owner
    expires_at=None,              # ISO datetime or None for no expiry
)
print("Save this — it is shown once:", created.full_key)
```

Returns `CreatedApiKey` — `id`, `name`, `role`, `key_prefix`,
`full_key` (the only call that returns it).

| Arg | Type | Default | Notes |
|---|---|---|---|
| `organization_id` | `str` | required | |
| `name` | `str` | required | Human label, not unique |
| `role` | `ApiKeyRole` | required | `"viewer"` / `"member"` / `"admin"` / `"owner"` |
| `expires_at` | `datetime \| str \| None` | `None` | ISO 8601 or `None` for no expiry |

## get

```python
key = client.api_keys.get("key-uuid")
print(key.role, key.created_at, key.last_used_at)
```

## update

Patch the key's name, role, or expiry. The full key string is **not**
rotated by update — issue a new key + delete the old one to rotate.

```python
client.api_keys.update("key-uuid", name="renamed", role="admin")
client.api_keys.update("key-uuid", expires_at="2027-01-01T00:00:00Z")
```

## delete

Revokes the key immediately. In-flight requests using the key fail
with `401 AuthError` after revocation propagates (≤ 1 second).

```python
client.api_keys.delete("key-uuid")
```

## Role hierarchy

Keys can only manage keys of equal or lower role. An `admin` key cannot
create an `owner` key. Owner-tier ops require an `owner` key.

| Caller role | Can create |
|---|---|
| `viewer` | nothing — these endpoints all require `admin`+ |
| `member` | nothing |
| `admin` | `viewer`, `member`, `admin` |
| `owner` | `viewer`, `member`, `admin`, `owner` |

## Web app vs SDK

- **Web app** (`app.pictograph.io → Settings → API Keys`) — visual UI,
  the most common path for one-off keys.
- **SDK / CLI** — for programmatic key issuance (CI provisioning,
  multi-org tools, automated rotation).

The SDK enforces the same role hierarchy as the web UI.

## Common errors

| Status | Exception | Cause |
|---|---|---|
| 403 | `ForbiddenError` | Caller's role too low for the requested action |
| 404 | `NotFoundError` | `key_id` doesn't exist or belongs to another org |
| 422 | `ValidationError` | Invalid role string, malformed `expires_at` |