You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: api-reference/openapi.json
+53-4Lines changed: 53 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -3419,6 +3419,7 @@
3419
3419
"post": {
3420
3420
"operationId": "createApiKey",
3421
3421
"summary": "Create a personal API key",
3422
+
"description": "Mints a new personal API key. The full secret is returned in the `key` field — capture it now, it is not retrievable again. Scopes use the capability-based vocabulary (ADR-049); the default scope set is `[\"gateway\", \"api:read\", \"api:write\"]`. Admin scopes (`admin:org`, `admin:platform`) are opt-in and rejected at mint time if the requester does not hold the corresponding role.",
3422
3423
"tags": [
3423
3424
"Billing"
3424
3425
],
@@ -3436,7 +3437,20 @@
3436
3437
"name": {
3437
3438
"type": "string",
3438
3439
"maxLength": 100,
3439
-
"default": "Default"
3440
+
"default": "Default",
3441
+
"description": "Friendly name for the key (e.g., \"ci-prod\", \"local-dev\"). Capped at 100 characters; longer names are truncated server-side."
3442
+
},
3443
+
"scopes": {
3444
+
"type": "array",
3445
+
"items": {
3446
+
"$ref": "#/components/schemas/ApiKeyScope"
3447
+
},
3448
+
"default": [
3449
+
"gateway",
3450
+
"api:read",
3451
+
"api:write"
3452
+
],
3453
+
"description": "Capability set for this key. If omitted, the API substitutes the default. Admin scopes (`admin:org`, `admin:platform`) are gated by the requester's current role and return HTTP 403 at mint time if the requester is not eligible."
3440
3454
}
3441
3455
}
3442
3456
}
@@ -3454,8 +3468,14 @@
3454
3468
}
3455
3469
}
3456
3470
},
3471
+
"400": {
3472
+
"description": "Validation error — typically an unknown scope name. The error message lists the valid scopes."
3473
+
},
3457
3474
"401": {
3458
3475
"$ref": "#/components/responses/Unauthorized"
3476
+
},
3477
+
"403": {
3478
+
"description": "Mint-time ceiling violation — `admin:platform` requested by a non-staff user, or `admin:org` requested by a user who is not owner/admin of any organization. The error body identifies which scope was rejected."
3459
3479
}
3460
3480
}
3461
3481
},
@@ -4893,7 +4913,20 @@
4893
4913
"properties": {
4894
4914
"name": {
4895
4915
"type": "string",
4896
-
"maxLength": 100
4916
+
"maxLength": 100,
4917
+
"description": "Friendly name for the key (e.g., \"ci-prod\")."
4918
+
},
4919
+
"scopes": {
4920
+
"type": "array",
4921
+
"items": {
4922
+
"$ref": "#/components/schemas/ApiKeyScope"
4923
+
},
4924
+
"default": [
4925
+
"gateway",
4926
+
"api:read",
4927
+
"api:write"
4928
+
],
4929
+
"description": "Capability set for this org key (ADR-049). If omitted, the API substitutes the default. The caller is already verified as owner/admin of this org by the route's RBAC gate, so `admin:org` is implicit-eligible here; `admin:platform` still requires Mnemom-staff role."
4897
4930
}
4898
4931
}
4899
4932
}
@@ -4917,6 +4950,9 @@
4917
4950
"401": {
4918
4951
"$ref": "#/components/responses/Unauthorized"
4919
4952
},
4953
+
"403": {
4954
+
"description": "Mint-time ceiling violation — typically `admin:platform` requested by a non-staff user."
4955
+
},
4920
4956
"404": {
4921
4957
"$ref": "#/components/responses/NotFound"
4922
4958
}
@@ -20570,6 +20606,18 @@
20570
20606
}
20571
20607
}
20572
20608
},
20609
+
"ApiKeyScope": {
20610
+
"type": "string",
20611
+
"enum": [
20612
+
"gateway",
20613
+
"api:read",
20614
+
"api:write",
20615
+
"admin:org",
20616
+
"admin:platform",
20617
+
"api"
20618
+
],
20619
+
"description": "Capability-based scope (ADR-049). `gateway` permits gateway-worker traffic; `api:read` and `api:write` permit identity-scoped GET and write endpoints respectively; `admin:org` permits org-admin operations on orgs the bearer owns/admins (per-request membership re-check); `admin:platform` permits `/v1/admin/*` Mnemom-staff operations (per-request staff-role re-check). The legacy `api` scope is accepted for backward compatibility and aliased to `api:read` + `api:write` at the auth gate; new keys should use the canonical vocabulary."
20620
+
},
20573
20621
"ApiKey": {
20574
20622
"type": "object",
20575
20623
"properties": {
@@ -20595,8 +20643,9 @@
20595
20643
"scopes": {
20596
20644
"type": "array",
20597
20645
"items": {
20598
-
"type": "string"
20599
-
}
20646
+
"$ref": "#/components/schemas/ApiKeyScope"
20647
+
},
20648
+
"description": "Capabilities granted to this key. Default for new keys is `[\"gateway\", \"api:read\", \"api:write\"]`. Admin scopes (`admin:org`, `admin:platform`) are opt-in and gated by the requester's role at mint time. See [API Keys → Scope vocabulary](https://docs.mnemom.ai/guides/api-keys#scope-vocabulary)."
Copy file name to clipboardExpand all lines: guides/api-keys.mdx
+75-11Lines changed: 75 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,11 @@
1
1
---
2
2
title: "API Keys"
3
-
description: "Personal vs. organization keys, when to use which, and how to rotate."
3
+
description: "Personal vs. organization keys, capability scopes, and how to rotate them safely."
4
4
sidebarTitle: "API Keys"
5
5
icon: "key"
6
6
---
7
7
8
-
Mnemom has **two API key surfaces**with different ownership, billing, and lifecycle. This guide covers when to use each and how to rotate them safely.
8
+
Mnemom has **two API key surfaces**— personal keys and organization keys — sharing one capability-based scope vocabulary. This guide covers when to use each surface, how scopes work, and how to rotate them safely.
9
9
10
10
If you came here from the [Org Admin guide](/guides/org-admin), this is the deep dive on key management.
11
11
@@ -16,19 +16,53 @@ If you came here from the [Org Admin guide](/guides/org-admin), this is the deep
|**Who can create**| Any authenticated user | Owner or admin of the org |
18
18
|**Billed to**| The user's billing account | The org's billing account |
19
-
|**Acts as**| The user's identity + permissions | The user's identity, scoped to the org |
19
+
|**Acts as**| The user's identity | The user's identity, scoped to the org |
20
20
|**Visible in**| Settings → Personal → API keys | Settings → Organization → API keys |
21
21
|**Survives departure?**| No — when the user leaves, key revokes | Yes — admin must explicitly revoke |
22
22
|**Revoke**| The user (or admin via support) | Owner, admin, or original creator |
23
23
24
24
Both surfaces produce keys with the `mnm_` prefix; they're identical at the wire level. The difference is **billing attribution** and **lifecycle ownership**.
25
25
26
-
## When to use which
26
+
## Scope vocabulary
27
+
28
+
Mnemom keys use a **capability-based** scope vocabulary. Each scope names what the key is *allowed to do*. The default is least-privilege; admin scopes are opt-in and gated by your role at mint time and re-checked on every request.
29
+
30
+
| Scope | Grants | Mintable by |
31
+
|---|---|---|
32
+
|`gateway`| Send traffic through the Mnemom gateway worker (proxy LLM requests, capture traces). | Any authenticated user |
33
+
|`api:read`|`GET` endpoints scoped to the bearer's identity (your agents, traces, cards, policies). | Any authenticated user |
34
+
|`api:write`|`POST` / `PUT` / `PATCH` / `DELETE` endpoints scoped to the bearer's identity (mutate your agents, cards, policies). | Any authenticated user |
35
+
|`admin:org`|`/v1/orgs/{org_id}/...` admin operations on orgs you own or admin (members, settings, billing, org-level keys). Re-checked per request against your current org membership. | Owner or admin of at least one org |
36
+
|`admin:platform`| Mnemom-staff platform operations across tenants. Re-checked per request against your current staff role. | Mnemom-staff users only |
37
+
38
+
**Default for new keys:**`["gateway", "api:read", "api:write"]`. Admin scopes are not added unless you explicitly request them.
39
+
40
+
### Scope semantics — what to know
41
+
42
+
-**Capabilities are independent.**`admin:platform` does NOT imply `api:read`. A key with only `admin:platform` cannot call `/v1/agents`. If your automation needs to call non-admin endpoints alongside admin ones, request both.
43
+
-**Mint-time ceiling is enforced server-side.** Requesting a scope you're not eligible for returns HTTP 403 at creation time. Examples:
← 403 admin:platform scope requires Mnemom-staff role on your account
48
+
```
49
+
-**Request-time role is re-checked** for admin scopes. If a staff member is demoted after minting an `admin:platform` key, that key's admin power stops working immediately on the next request — without rotation. The key still authenticates for non-admin endpoints if those scopes are also present.
50
+
-**Demotion is silent.** Mnemom does not auto-revoke admin-scoped keys when a user's role changes. Use `DELETE /v1/api-keys/{key_id}` (or rotate) when offboarding admin-role users.
51
+
52
+
### Picking scopes for common patterns
53
+
54
+
-**Local development on your laptop:**`gateway`, `api:read`, `api:write` (the default).
55
+
-**CI runner that publishes traces but doesn't mutate state:**`gateway`, `api:read`.
56
+
-**Read-only analytics ingest into Snowflake/BQ:**`api:read`.
57
+
-**Service account that manages org members from a script:**`admin:org` (plus `api:read` if it needs to read non-admin endpoints).
58
+
-**Mnemom-internal automation (deploy gates, on-call tooling):**`admin:platform` (plus `api:read`/`api:write` if it touches non-admin endpoints too).
59
+
60
+
## When to use which surface
27
61
28
62
**Personal key, every time** — *unless* one of the things below applies.
29
63
30
64
-**Local development.** A developer on the team using Mnemom from their laptop. Personal key.
31
-
-**Per-engineer CI accounts.** Each engineer has their own CI runner credentialed against their personal account. Personal key. (You probably want option 2 below for actual CI.)
65
+
-**Per-engineer CI accounts.** Each engineer has their own CI runner credentialed against their personal account. Personal key.
32
66
-**Single-purpose script you're running yourself.** Personal key.
33
67
34
68
**Organization key when:**
@@ -47,7 +81,10 @@ If a member leaves the org, their **personal keys remain valid** (they're still
47
81
curl -X POST https://api.mnemom.ai/v1/api-keys \
48
82
-H "Authorization: Bearer $MNEMOM_JWT" \
49
83
-H "Content-Type: application/json" \
50
-
-d '{"name": "local dev"}'
84
+
-d '{
85
+
"name": "local dev",
86
+
"scopes": ["gateway", "api:read", "api:write"]
87
+
}'
51
88
```
52
89
53
90
### Organization
@@ -56,7 +93,10 @@ curl -X POST https://api.mnemom.ai/v1/api-keys \
56
93
curl -X POST https://api.mnemom.ai/v1/orgs/$ORG_ID/api-keys \
57
94
-H "Authorization: Bearer $MNEMOM_JWT" \
58
95
-H "Content-Type: application/json" \
59
-
-d '{"name": "ci-prod"}'
96
+
-d '{
97
+
"name": "ci-prod",
98
+
"scopes": ["gateway", "api:read", "api:write"]
99
+
}'
60
100
```
61
101
62
102
In both cases the response carries the **full secret** in the `key` field. You see it once. Mnemom stores only its SHA-256 hash; we cannot recover the secret if you lose it.
@@ -67,11 +107,33 @@ In both cases the response carries the **full secret** in the `key` field. You s
67
107
"key": "mnm_8f3e7c2b91a4d6f8...",
68
108
"key_prefix": "mnm_8f3e",
69
109
"name": "ci-prod",
70
-
"scopes": ["gateway", "api"],
110
+
"scopes": ["gateway", "api:read", "api:write"],
71
111
"created_at": "2026-04-25T12:34:56Z"
72
112
}
73
113
```
74
114
115
+
If you omit `scopes` from the request body, the API substitutes the default set (`["gateway", "api:read", "api:write"]`).
116
+
117
+
## Using a key
118
+
119
+
```bash
120
+
curl https://api.mnemom.ai/v1/agents \
121
+
-H "X-Mnemom-Api-Key: mnm_8f3e7c2b91a4d6f8..."
122
+
```
123
+
124
+
The `X-Mnemom-Api-Key` header is the canonical auth path for `mnm_*` keys. (Some legacy SDKs send the key as `Authorization: Bearer mnm_...` — that path is deprecated; migrate to `X-Mnemom-Api-Key`.)
125
+
126
+
## Legacy keys (`["gateway", "api"]`)
127
+
128
+
Keys minted before May 2026 carry the legacy two-scope set `["gateway", "api"]`. They continue to work — the auth gate aliases them to `["gateway", "api:read", "api:write"]` at request time, so existing integrations need no changes.
129
+
130
+
The dashboard renders these keys with a "legacy" badge. To upgrade a legacy key to the canonical vocabulary:
131
+
132
+
1. Rotate the key (`POST /v1/api-keys/{key_id}/rotate`) — the rotation preserves the legacy scope set on the new key.
133
+
2. Revoke the rotated key and create a fresh one (`POST /v1/api-keys`) without specifying `scopes`. The new key inherits the post-ADR-049 default `["gateway", "api:read", "api:write"]`.
134
+
135
+
(You don't have to upgrade — legacy keys remain valid indefinitely. But if you want the dashboard to stop annotating them, this is the migration path.)
136
+
75
137
## Rotation
76
138
77
139
Two endpoints, identical contract:
@@ -123,8 +185,10 @@ For org keys, the same shape applies under `/v1/orgs/{org_id}/api-keys/{key_id}`
123
185
124
186
## Key hygiene checklist
125
187
126
-
-**Rotate annually**, or whenever a member with access leaves the org. The audit log shows last_used_at per key — rotate dormant keys aggressively.
127
-
-**Name your keys**. `"name": "ci-prod"` is much more useful than `"Default"` six months later when you're triaging an alert.
188
+
-**Rotate annually**, or whenever a member with access leaves the org. The audit log shows `last_used_at` per key — rotate dormant keys aggressively.
189
+
-**Name your keys.**`"name": "ci-prod"` is much more useful than `"Default"` six months later when you're triaging an alert.
190
+
-**Use the smallest scope set that works.** Default to `gateway` + `api:read`/`api:write` and only add admin scopes when the integration genuinely needs them. Smaller blast radius if leaked.
191
+
-**Prefer `api:read` for analytics integrations.** Read-only keys are safer and the audit trail is cleaner.
128
192
-**Never commit secrets.** The `mnm_` prefix is a string git secret-scanners recognize; we recommend GitHub Secret Scanning + push protection to catch accidents.
129
-
-**Use scopes.** Keys default to `["gateway", "api"]`; if you only need one, request just one. Smaller blast radius if leaked.
130
193
-**Include a renewal reminder** in your deploy / IaC if the key has a TTL constraint from your security policy. Mnemom keys themselves don't expire by default.
194
+
-**Treat admin-scope keys with extra care.** Use them only for the specific automation that needs them; rotate them on any suspected leak; audit which keys carry `admin:org` or `admin:platform` quarterly.
Copy file name to clipboardExpand all lines: guides/authentication.mdx
+22-6Lines changed: 22 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -86,19 +86,33 @@ Server-side, sessions are revalidated on every protected request against the `au
86
86
87
87
## API keys
88
88
89
-
API keys authenticate server-to-server calls against `api.mnemom.ai`. They are scoped to an organization and inherit the role of the creator.
89
+
API keys authenticate server-to-server calls against `api.mnemom.ai` and `gateway.mnemom.ai`. They use a **capability-based scope vocabulary** (ADR-049): each scope names what the key is allowed to do, defaults are least-privilege, and admin scopes are opt-in and gated by your role.
90
+
91
+
The full deep dive on key management — including the side-by-side comparison of personal vs. organization keys, the per-scope reference table, and rotation/revocation flows — lives at [API Keys](/guides/api-keys). This section is the auth-flow summary.
|`api:read`|`GET` endpoints scoped to your identity. | Anyone |
99
+
|`api:write`|`POST`/`PUT`/`PATCH`/`DELETE` endpoints scoped to your identity. | Anyone |
100
+
|`admin:org`| Org-admin operations on orgs you own/admin. | Org owner / org admin |
101
+
|`admin:platform`| Mnemom-staff platform operations. | Mnemom staff only |
102
+
103
+
**Default for new keys:**`["gateway", "api:read", "api:write"]`. Admin scopes are explicit opt-in; the API enforces a mint-time ceiling against your current role and re-checks on every request.
90
104
91
105
### Creating an API key
92
106
93
107
<Steps>
94
108
95
109
### Sign in and open API keys
96
110
97
-
**Settings → API Keys** (user-scoped) or **Org Settings → API Keys** (org-scoped).
111
+
**Settings → API Keys** (personal) or **Org Settings → API Keys** (organization).
98
112
99
-
### Create the key
113
+
### Pick capabilities
100
114
101
-
Click **Create API key**, name it, and pick a scope (Owner, Admin, Member — must not exceed the creator's role). AAL2 step-up is required.
115
+
The dialog has a Capabilities section (default scopes) and an Admin permissions section (opt-in, role-gated). Quick-pick presets ("Default", "Read-only", "Gateway-only") cover most cases. AAL2 step-up is required.
API keys are rate-limited per plan tier (see [API reference overview](/api-reference/overview)).
117
131
132
+
### Legacy keys
133
+
134
+
Keys minted before May 2026 carry the legacy two-scope set `["gateway", "api"]`. The auth gate aliases them to `["gateway", "api:read", "api:write"]` at request time, so existing integrations continue to work unchanged. The dashboard renders them with a "legacy" annotation; rotation upgrades them to the canonical vocabulary. See [API Keys → Legacy keys](/guides/api-keys#legacy-keys-gateway-api) for the migration path.
135
+
118
136
### Rotating an API key
119
137
120
138
Rotation is **create-new-then-revoke-old**, not an in-place swap. This gives you a window to roll callers over before the old key dies.
@@ -126,8 +144,6 @@ Rotation is **create-new-then-revoke-old**, not an in-place swap. This gives you
126
144
127
145
Revocation is immediate. Any in-flight request using the revoked key receives HTTP 401 on its next call.
128
146
129
-
{/* TODO: Alex — confirm whether we surface a "last used at" timestamp in the dashboard today, and whether there's an automated rotation reminder (e.g., suggest rotation after 90 days). */}
130
-
131
147
### Rotating a provider API key bound to an agent
132
148
133
149
If you are rotating an **agent's provider key** (Anthropic / OpenAI / Gemini) — not a Mnemom API key — see [Rotating your agent's API key](/guides/agent-key-rotation). The flow preserves the agent's ID, traces, and reputation.
0 commit comments