# Memory API

Read and write memory through the documented REST and MCP contracts with explicit scope boundaries.

- Canonical: https://docs.xmemo.dev/docs/api/memory
- Locale: en-US
- Content-Locale: en-US
- Canonical-Content-Digest: 446b069541121da293fcc920696cb4e6d4e9fd7cc186d28bbbc1c688a7b3ffcc
- Edition-Digest: d14c4b25c69701caf6fa67efada1e14cda08c16140c9eab97664fa5129388063
- Source-Revision: sha256:004c0ac7668443326dc253ae102d38bbd116e9cc540e7df7d066772f28b3a152

## Public memory endpoints and scopes

The examples below use the /v1 paths that are present in the committed OpenAPI contract. Authenticate with X-API-Key (or the server's accepted Bearer form); read operations need a read-capable token and writes need a write-capable token. The OpenAPI response schema is intentionally untyped for most memory endpoints, so the documented implementation keys are called out separately where the server currently returns them. GET /v1/memories currently returns an object with memories (array) and total (number), but those properties are not declared in OpenAPI.

- Create/capture: POST /v1/remember and POST /v1/memories (201).
- List: GET /v1/memories with limit, offset, and path (200).
- Search: GET /v1/memories/search; GET /v1/recall is the same search operation (200).
- Assemble context: POST /v1/recall/context (200).
- Update: PATCH /v1/memories/{memory_id}; delete: DELETE /v1/memories/{memory_id}.
- Forget: POST /v1/memories/{memory_id}/forget; restore: POST /v1/memories/{memory_id}/restore; complete reminder: POST /v1/reminders/{reminder_id}/complete.

## Create request schemas

POST /v1/remember accepts MemoryRememberRequest; POST /v1/memories accepts MemoryStoreRequest. Both require content (string) and path (string). Optional fields in the OpenAPI schemas include metadata (object), source (string or null), logic_path (string or null), embedding (number array or null), bucket (string, default public), memory_id, semantic_key, memory_type, version, status, superseded_by, embedding_provider, embedding_model, embedding_dimension, importance, confidence, expires_at, scope, team_id, and provenance. MemoryRememberRequest additionally declares dedupe (boolean, default true); MemoryStoreRequest defaults memory_type to semantic and importance/confidence to 0.5/1.0.

```http
POST /v1/remember
X-API-Key: <your-assigned-api-key>
Content-Type: application/json

{
  "content": "The actual text to remember.",
  "path": "projects/memory-os/decisions",
  "scope": "memory-os",
  "source": "codex",
  "metadata": { "kind": "decision" }
}
```

## Create response schemas

The OpenAPI 201 response content is an untyped JSON object for both create operations. The current remember implementation returns {id: string, status: "remembered"}; the store implementation returns the created memory identifier. Treat these as implementation behavior, not a stronger schema than the committed OpenAPI document declares.

```json
{
  "id": "<memory-id>",
  "status": "remembered"
}
```

## Search and recall

GET /v1/memories/search and GET /v1/recall share the Search Memories operation and return Cache-Control: no-store, private. Filters narrow retrieval and cannot widen what the token authorizes.

```http
GET /v1/memories/search?query=current%20MCP%20decision&limit=5&scope=memory-os&explain=true
X-API-Key: <your-assigned-api-key>
```

## Search request parameters and response

OpenAPI query parameters are query (string, required), limit (integer, default 5), threshold (number or null), path (string, default %), bucket (string, default %), scope (string or null), team_id (string or null), memory_type (string, default %), status (string, default active), explain (boolean, default false), prefer_working (boolean, default false), and candidate_count (integer or null). OpenAPI leaves the 200 response as an untyped JSON object; the implementation currently returns results (array) and coverage (number), and may add keyguard_decrypt_grant_ids when applicable.

- Response shape currently observed: { results: [...], coverage: number }.
- The spec does not declare a maximum for search limit or candidate_count; clients should use conservative values and handle validation errors.

## Context request and response schemas

POST /v1/recall/context accepts RecallContextRequest. query (string) is required; path and bucket default to %, memory_type defaults to auto, status to active, max_items to 8, max_tokens to 1500, prefer_working to true, include_knowledge to false, and scope, team_id, threshold, and limit are nullable. The OpenAPI 200 response is an untyped object; the normal authenticated-owner implementation returns a value-density-v2 context object with version, query, retrieval_plan, budget, items, context_text, and answer_status. The temporary-agent branch returns version 1.0 with the same core query/budget/items/context_text fields.

```http
POST /v1/recall/context
X-API-Key: <your-assigned-api-key>
Content-Type: application/json

{
  "query": "recent progress on memory-os",
  "scope": "memory-os",
  "memory_type": "auto",
  "status": "active",
  "max_items": 8,
  "max_tokens": 1500,
  "prefer_working": true
}
```

## Memory update and forget schemas

PATCH /v1/memories/{memory_id} accepts MemoryUpdateRequest: all fields are optional, and content, path, metadata, source, logic_path, embedding, bucket, semantic_key, memory_type, status, superseded_by, embedding_provider, embedding_model, embedding_dimension, importance, confidence, expires_at, scope, team_id, provenance, supersession_reason, merge_metadata (default true), merge_provenance (default true), and detect_conflicts (default true) are declared. DELETE /v1/memories/{memory_id} accepts query mode (default soft_delete) and reason; mode=hard_delete and mode=redact are irreversible, and memory:write is accepted by compatibility rules so write tokens can permanently delete records. POST /v1/memories/{memory_id}/forget accepts MemoryForgetRequest with mode (default soft_delete), reason, replacement_content, and metadata. POST /v1/memories/{memory_id}/restore restores soft-deleted records. The 200 responses for these lifecycle operations are typed in the public OpenAPI schema.

```http
POST /v1/memories/<memory-id>/forget
X-API-Key: <your-assigned-api-key>
Content-Type: application/json

{
  "mode": "soft_delete",
  "reason": "No longer needed"
}
```

## Pagination, errors, and rate limits

Only GET /v1/memories exposes list pagination in OpenAPI: limit defaults to 100 and offset to 0, with an optional path filter. Search uses limit rather than offset; context uses max_items/max_tokens rather than page cursors. The documented validation error is HTTPValidationError: {detail: [{loc: (string|integer)[], msg: string, type: string}]}. Runtime authorization failures use the shared error contract on the Authentication page. The runtime applies the 180-per-minute memory_write policy to writes/lifecycle mutations and the 300-per-minute memory_search policy to search, recall, context, and memory reads, inside a 60-second window when enabled; quotas are configurable and absent from OpenAPI.

```json
{
  "version": "value-density-v2",
  "query": "recent progress on memory-os",
  "retrieval_plan": {},
  "budget": {
    "max_items": 8,
    "max_tokens": 1500,
    "used_items": 3,
    "used_tokens": 412,
    "skipped_items": 0,
    "filtered_items": 0,
    "structured_skipped_items": 0,
    "budget_skipped_items": 0,
    "truncated_items": 0,
    "candidate_items": 3,
    "selection_strategy": "top-primary-plus-stable-value-density",
    "budget_tradeoff": false,
    "token_scope": "context_text"
  },
  "items": [],
  "context_text": "",
  "answer_status": "no_confirmed_answer"
}
```

