> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openmem.blog/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API endpoints for memory CRUD operations

> Full reference for POST, GET, PATCH, DELETE, and list /memories — request bodies, path and query parameters, and response shapes.

The `/memories` endpoints cover the full lifecycle of a memory record: creating, reading, updating, deleting, and paginated listing. All five operations share the same `Memory` response schema and the same error envelope described in [Error codes and HTTP status mapping](/api/error-model).

***

## POST /memories

Add a new memory record. Returns the created `Memory` object with a provider-assigned `id`.

### Request body

<ParamField body="content" type="string" required>
  The text content of the memory. This is the only field that all providers are required to index and return.
</ParamField>

<ParamField body="user_id" type="string" required>
  The user this memory belongs to. All memory operations are scoped to a `user_id`.
</ParamField>

<ParamField body="scope" type="string">
  Slash-delimited hierarchical namespace, e.g. `coding/preferences` or `health/symptoms`. Used to filter and access-control memories. See [Scopes](/concepts/scopes) for full scope semantics.
</ParamField>

<ParamField body="tags" type="string[]">
  Free-form labels attached to this memory. You can filter by a single tag using `GET /memories?tag=<value>`.
</ParamField>

<ParamField body="source" type="object">
  Origin metadata for the memory.

  <Expandable title="source properties">
    <ParamField body="source.app" type="string">
      Name of the application that created the memory (e.g. `cursor`, `chatgpt`).
    </ParamField>

    <ParamField body="source.type" type="string">
      How the memory was created. One of `extracted`, `explicit`, or `imported`.
    </ParamField>

    <ParamField body="source.ref" type="string">
      An opaque pointer back to the source — a session ID, document ID, or similar.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="confidence" type="number">
  A float between `0` and `1` indicating how confident the system is in this memory. Defaults to `null` if omitted.
</ParamField>

<ParamField body="valid_from" type="string">
  ISO 8601 datetime from which this memory is considered valid.
</ParamField>

<ParamField body="valid_to" type="string">
  ISO 8601 datetime after which this memory is no longer valid. Pass `null` for no expiry.
</ParamField>

<ParamField body="supersedes" type="string[]">
  List of memory IDs that this record replaces. Useful when updating a fact while preserving history.
</ParamField>

### Response — 201 Created

<ResponseField name="id" type="string" required>
  Provider-assigned unique identifier for the memory (e.g. `mem_abc123`).
</ResponseField>

<ResponseField name="content" type="string" required>
  The stored text content.
</ResponseField>

<ResponseField name="user_id" type="string" required>
  The user this memory belongs to.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 datetime when the record was created.
</ResponseField>

<ResponseField name="scope" type="string">
  Scope if provided at creation time.
</ResponseField>

<ResponseField name="tags" type="string[]">
  Tags if provided at creation time.
</ResponseField>

<ResponseField name="source" type="object">
  Source metadata if provided at creation time.
</ResponseField>

<ResponseField name="confidence" type="number">
  Confidence score between 0 and 1.
</ResponseField>

<ResponseField name="valid_from" type="string">
  Validity start datetime.
</ResponseField>

<ResponseField name="valid_to" type="string">
  Validity end datetime, or `null`.
</ResponseField>

<ResponseField name="supersedes" type="string[]">
  IDs of memories this record supersedes.
</ResponseField>

<ResponseField name="embedding_model" type="string">
  The embedding model used to index the content, if reported by the provider.
</ResponseField>

<ResponseField name="updated_at" type="string">
  ISO 8601 datetime of the last update.
</ResponseField>

<ResponseField name="status" type="string">
  Ingestion lifecycle state. One of `queued`, `indexing`, `done`, or `failed`. Synchronous providers always return `done`. Absent or `null` means the provider does not track ingestion state.
</ResponseField>

### Example

```bash theme={null}
curl -s -X POST http://localhost:8080/memories \
  -H "Content-Type: application/json" \
  -d '{
    "content": "User prefers pnpm over npm",
    "user_id": "u1",
    "scope": "coding/preferences",
    "tags": ["tooling", "nodejs"],
    "source": { "app": "cursor", "type": "extracted" },
    "confidence": 0.92
  }'
```

```json theme={null}
{
  "id": "mem_abc123",
  "content": "User prefers pnpm over npm",
  "user_id": "u1",
  "scope": "coding/preferences",
  "tags": ["tooling", "nodejs"],
  "source": { "app": "cursor", "type": "extracted", "ref": null },
  "confidence": 0.92,
  "valid_from": null,
  "valid_to": null,
  "supersedes": null,
  "embedding_model": "text-embedding-3-small",
  "created_at": "2026-04-27T10:00:00Z",
  "updated_at": "2026-04-27T10:00:00Z",
  "status": "done"
}
```

***

## GET /memories/\{id}

Retrieve a single memory by its ID.

### Path parameters

<ParamField path="id" type="string" required>
  The memory ID returned when the record was created (e.g. `mem_abc123`).
</ParamField>

### Response — 200 OK

Returns the `Memory` object. Returns `404` with a `not_found` error code if the ID does not exist.

### Example

```bash theme={null}
curl -s http://localhost:8080/memories/mem_abc123
```

```json theme={null}
{
  "id": "mem_abc123",
  "content": "User prefers pnpm over npm",
  "user_id": "u1",
  "scope": "coding/preferences",
  "tags": ["tooling", "nodejs"],
  "created_at": "2026-04-27T10:00:00Z",
  "updated_at": "2026-04-27T10:00:00Z",
  "status": "done"
}
```

***

## PATCH /memories/\{id}

Update one or more fields of an existing memory. All fields in the request body are optional — only the fields you include are modified.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the memory to update.
</ParamField>

### Request body

<ParamField body="content" type="string">
  New text content for the memory.
</ParamField>

<ParamField body="scope" type="string">
  Updated scope path.
</ParamField>

<ParamField body="tags" type="string[]">
  Replacement tag list. The entire list is replaced, not merged.
</ParamField>

<ParamField body="confidence" type="number">
  Updated confidence score between 0 and 1.
</ParamField>

<ParamField body="valid_to" type="string">
  Updated expiry datetime, or `null` to remove the expiry.
</ParamField>

<ParamField body="supersedes" type="string[]">
  Updated list of memory IDs that this record replaces.
</ParamField>

### Response — 200 OK

Returns the full updated `Memory` object. Returns `404` if the ID does not exist.

### Example

```bash theme={null}
curl -s -X PATCH http://localhost:8080/memories/mem_abc123 \
  -H "Content-Type: application/json" \
  -d '{
    "content": "User prefers bun for new projects",
    "supersedes": ["mem_abc123"]
  }'
```

***

## DELETE /memories/\{id}

Permanently delete a memory. This action cannot be undone.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the memory to delete.
</ParamField>

### Response — 204 No Content

Returns an empty body on success. Returns `404` if the ID does not exist.

<Warning>
  Deletion is permanent. If you want to preserve history while marking a memory as replaced, use `PATCH /memories/{id}` with the `supersedes` field instead.
</Warning>

### Example

```bash theme={null}
curl -s -X DELETE http://localhost:8080/memories/mem_abc123
# (empty body, HTTP 204)
```

***

## GET /memories

Return a paginated list of memories for a user, with optional filtering by scope, tag, and time range.

### Query parameters

<ParamField query="user_id" type="string" required>
  Return only memories belonging to this user.
</ParamField>

<ParamField query="scope" type="string">
  Glob pattern to filter by scope, e.g. `coding/*` returns all memories under the `coding/` hierarchy.
</ParamField>

<ParamField query="tag" type="string">
  Return only memories that have this tag. To filter by multiple tags, call the endpoint multiple times and intersect client-side, or use `GET /memories/search`.
</ParamField>

<ParamField query="since" type="string">
  ISO 8601 datetime. Return only memories created at or after this time.
</ParamField>

<ParamField query="until" type="string">
  ISO 8601 datetime. Return only memories created before or at this time.
</ParamField>

<ParamField query="limit" type="integer" default="50">
  Maximum number of results per page. Maximum is 500.
</ParamField>

<ParamField query="cursor" type="string">
  Opaque pagination cursor from the previous response's `next_cursor` field. Omit to start from the beginning.
</ParamField>

### Response — 200 OK

<ResponseField name="items" type="Memory[]" required>
  The list of memory records for this page.
</ResponseField>

<ResponseField name="next_cursor" type="string">
  Opaque string to pass as `cursor` in the next request. `null` when there are no more results.
</ResponseField>

### Pagination example

```bash theme={null}
# First page
curl -s "http://localhost:8080/memories?user_id=u1&limit=2"
```

```json theme={null}
{
  "items": [
    { "id": "mem_abc123", "content": "User prefers pnpm over npm", "..." },
    { "id": "mem_def456", "content": "User prefers dark mode", "..." }
  ],
  "next_cursor": "eyJvZmZzZXQiOjJ9"
}
```

```bash theme={null}
# Second page — pass the cursor from the previous response
curl -s "http://localhost:8080/memories?user_id=u1&limit=2&cursor=eyJvZmZzZXQiOjJ9"
```

```json theme={null}
{
  "items": [
    { "id": "mem_ghi789", "content": "User is based in Berlin", "..." }
  ],
  "next_cursor": null
}
```

<Note>
  Treat `next_cursor` as an opaque value. Its internal structure is provider-defined and may change across releases.
</Note>
