---
title: "Mint a short-lived, gateway-only API key bound to an agent"
method: POST
path: "/agents/{agent_id}/session-keys"
tags: ["Code"]
---

# Mint a short-lived, gateway-only API key bound to an agent

`POST /agents/{agent_id}/session-keys`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/agents/{agent_id}/session-keys`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`
  - API key in cookie `mnemom_session`

Owner-authenticated only (a user JWT/cookie/OAuth session, or an API key carrying `api:write`), at org role owner/admin on the agent's governing org (`org_id` resolves like `GET /v1/code/entitlement`; an unknown agent and an agent in another org are the SAME 404 `agent_not_found`). Mints a key scoped to EXACTLY `['gateway']`, bound to `agent_id` and, when given, `session_id` (the gateway conversation id), with a fixed 24h expiry matching the goal contract's sliding 24h TTL. `mnemom agent` mints one of these per launched session instead of handing the launched session the owner's own key (MNE-8245), so a session can never call owner-only mnemom-api routes. A session key, or any other gateway-only key, is refused here with 403 `session_credential_forbidden` — a session can never mint itself a broader key. The minted key's `user_id` is the caller, so it revokes through the existing `DELETE /v1/api-keys/{key_id}`.

## Path parameters

- `agent_id` string, required

## Query parameters

- `org_id` string

## Request body

- object
  - `session_id` string: The gateway conversation/session id to bind the key to, if known at mint time.

## Response `201`

The minted key. `key` is the cleartext secret — returned once, never again.

- object
  - `key_id` string, required
  - `key` string, required: The cleartext key — shown once.
  - `key_prefix` string, required
  - `scopes` string[], required: Always exactly `['gateway']`.
  - `kind` 'session', required
  - `agent_id` string, required
  - `session_id` string, nullable, required
  - `expires_at` string, date-time, required
  - `created_at` string, date-time, required

## Other responses

- `400`: `agent_id` is missing (`agent_id_required`), or `session_id` is not a non-empty string.
- `401`: Authentication required
- `403`: The caller lacks org role owner/admin on the agent's org (`forbidden`), an API key lacks `api:write` (`insufficient_scope`), or the caller presented a session key or other gateway-only key (`session_credential_forbidden`).
- `404`: No org for the caller (`not_found`), or the agent does not exist / is not in the resolved org (`agent_not_found` — deliberately the same answer for both).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: The agent lookup failed (retryable).

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
