---
name: isodora-keys
description: >
  Authenticate to Isodora's public API and MCP. Use when the user needs an API
  key, sees 401/403, asks about Settings → API keys, My keys vs Organization
  keys, isk_u_ prefixes, scopes, expiry, org kill switch, region mismatch, rate
  limits, or "my key doesn't work". Always required before isodora-api or
  isodora-mcp calls succeed.
metadata:
  author: isodora
  version: "1.0.0"
  parent: isodora
---

# Isodora keys

Every call to `/api/v1/**` or `/api/mcp` needs:

```http
Authorization: Bearer isk_u_…
```

Create and manage keys in the **customer portal → Settings → API keys**
(`/{locale}/settings/api-keys`).

---

## Get a key (customer path)

1. Sign in to the regional portal (`app.isodora.se` or `app.isodora.app`).
2. Open **Settings → API keys**.
3. Tab **My keys** → **New API key**.
4. Choose name, scope (**Read** or **Read & write**), expiry (30 / 90 / 365 days), optional org allow-list.
5. Copy the plaintext **once**. Store in a secret manager or env var — never commit it.

Auditors always get read-only keys regardless of UI choice.

### UI tabs

| Tab | Purpose |
|---|---|
| **My keys** | Create/revoke your personal keys (`isk_u_*`) — this is what agents use |
| **Organization keys** | `customer_admin` oversight: list members' keys, revoke, org-wide kill switch |
| **Usage** | Request volume / credits consumed by keys |

There is **no separate organization bearer prefix**. Organization keys tab manages the same `isk_u_*` credentials.

### Platform keys (`isk_p_*`)

Operator / partner keys for provisioning and platform tools. Not the default customer skill path. If the user only has `isk_p_*`, say so and prefer personal keys for compliance reads/writes as the user.

---

## Environment

```bash
# EU
export ISODORA_BASE_URL=https://app.isodora.se
export ISODORA_API_KEY=isk_u_…   # never commit

# US
export ISODORA_BASE_URL=https://app.isodora.app
export ISODORA_API_KEY=isk_u_…
```

Region is baked into the database where the key was created. Cross-region calls fail.

---

## Smoke test

```bash
curl -sS -H "Authorization: Bearer $ISODORA_API_KEY" \
  "$ISODORA_BASE_URL/api/v1/me"
```

Expect HTTP 200 and JSON `{ "data": …, "meta": …, "request_id": "…" }`.

MCP equivalent: call tool `whoami` after configuring the server (see `isodora-mcp`).

---

## Scopes

| Key scope | REST | MCP |
|---|---|---|
| `read` | GET endpoints | Read tools only |
| `read_write` | GET + PATCH status / import | Read + `update_*` / `import_project_document` |

Effective permission = **live user permission ∩ key scope**. Offboard the user → key dies. Org kill switch off → all member keys fail.

---

## Support runbook — "my key doesn't work"

Work through in order (full detail: [references/support-runbook.md](references/support-runbook.md)):

1. **Region** — EU key on `.se`, US on `.app`
2. **Expiry / revocation** — badges on My keys
3. **Owner eligibility** — seat still active (`customer_admin` / `customer_user` / `consultant` / `auditor`)
4. **Org kill switch** — Organization keys tab
5. **Subscription** — org `active` or `trial`
6. **Rate limit** — 429 + `Retry-After`
7. **Credits / caps** — 429 with `details.code` like `credits_depleted`, `daily_cap_reached`, `import_quota`
8. Ask for `request_id` from the error envelope

---

## Security rules for agents

- Never print full keys in chat, logs, or git.
- Prefer env vars / MCP `headers` with secret refs.
- Example configs use `isk_u_…` placeholders only.
- MFA may be required to *create* a key; *using* a key bypasses MFA by design — kill switch is the mitigation.
