mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-20 05:54:01 +00:00
### TL;DR Documents the new `ids` parameter for the `forget-matching` endpoint, allowing exact memory deletion without semantic search. ### What changed? The `forget-matching` endpoint now accepts either a `query` (semantic search-based forgetting) or an explicit `ids` list (direct deletion by memory ID) — one or the other must be provided. The docs have been updated to reflect this: - The `query` parameter is now marked as `one of*` rather than required, and `ids` is introduced as an alternative with the same mutual-exclusivity constraint. - `threshold` is clarified as applying to `query` mode only. - Code examples for both JavaScript and cURL now show the recommended two-step pattern: run a `dryRun` with `query`, then apply using the `ids` returned from the preview — avoiding drift if the container changes between steps. - A new `<Tip>` block explains why passing `ids` on the apply step produces a more deterministic delete than re-running the `query`. ### How to test? 1. Call `forget-matching` with `dryRun: true` and a `query` to retrieve candidate `id`s. 2. Re-call with `dryRun: false` and the `ids` from step 1 to confirm only those exact memories are forgotten. 3. Verify that passing `ids` belonging to a different `containerTag` are ignored. 4. Confirm that providing both `query` and `ids`, or neither, returns an appropriate validation error. ### Why make this change? Re-running a `query` on the apply step can produce different results if the container was modified between the preview and the apply. Exposing `ids` as a first-class parameter lets callers pin the delete to exactly the set they reviewed, making bulk forgetting safer and more predictable.
349 lines
12 KiB
Text
349 lines
12 KiB
Text
---
|
||
title: "Memory Operations"
|
||
sidebarTitle: "CRUD & Forgetting"
|
||
description: "Advanced memory operations (v4 API)"
|
||
icon: "database"
|
||
---
|
||
|
||
<Info>
|
||
These v4 endpoints operate on extracted memories (not raw documents). SDK support coming soon — use fetch or cURL for now.
|
||
|
||
For document management (list, get, update, delete), see [Document Operations](/ingestion/document-operations).
|
||
For ingesting raw content (text, files, URLs) through the processing pipeline, see [Add Context](/ingestion/add-memories).
|
||
</Info>
|
||
|
||
## Create Memories
|
||
|
||
Create memories directly without going through the document ingestion workflow. Memories are embedded and immediately searchable.
|
||
|
||
This is useful for storing user preferences, traits, or any structured facts where you already know the exact memory content.
|
||
|
||
<Tabs>
|
||
<Tab title="fetch">
|
||
```typescript
|
||
const response = await fetch("https://api.supermemory.ai/v4/memories", {
|
||
method: "POST",
|
||
headers: {
|
||
"Authorization": `Bearer ${API_KEY}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
memories: [
|
||
{
|
||
content: "John prefers dark mode",
|
||
isStatic: false,
|
||
metadata: { source: "user_preference" }
|
||
},
|
||
{
|
||
content: "John is from Seattle",
|
||
isStatic: true
|
||
}
|
||
],
|
||
containerTag: "user_123"
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
// {
|
||
// documentId: "abc123",
|
||
// memories: [
|
||
// { id: "mem_1", memory: "John prefers dark mode", isStatic: false, createdAt: "2025-..." },
|
||
// { id: "mem_2", memory: "John is from Seattle", isStatic: true, createdAt: "2025-..." }
|
||
// ]
|
||
// }
|
||
```
|
||
</Tab>
|
||
<Tab title="cURL">
|
||
```bash
|
||
curl -X POST "https://api.supermemory.ai/v4/memories" \
|
||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"memories": [
|
||
{
|
||
"content": "John prefers dark mode",
|
||
"isStatic": false,
|
||
"metadata": { "source": "user_preference" }
|
||
},
|
||
{
|
||
"content": "John is from Seattle",
|
||
"isStatic": true
|
||
}
|
||
],
|
||
"containerTag": "user_123"
|
||
}'
|
||
```
|
||
</Tab>
|
||
</Tabs>
|
||
|
||
### Parameters
|
||
|
||
| Parameter | Type | Required | Description |
|
||
|-----------|------|----------|-------------|
|
||
| `memories` | array | yes | Array of memory objects (1–100 items) |
|
||
| `memories[].content` | string | yes | The memory text (max 10,000 chars). Should be entity-centric, e.g. "John prefers dark mode" |
|
||
| `memories[].isStatic` | boolean | no | `true` for permanent identity traits (name, hometown). Defaults to `false` |
|
||
| `memories[].metadata` | object | no | Key-value metadata (strings, numbers, booleans) |
|
||
| `containerTag` | string | yes | Space / container tag these memories belong to |
|
||
|
||
### Response
|
||
|
||
```json
|
||
{
|
||
"documentId": "abc123",
|
||
"memories": [
|
||
{
|
||
"id": "mem_1",
|
||
"memory": "John prefers dark mode",
|
||
"isStatic": false,
|
||
"createdAt": "2025-01-15T10:30:00.000Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `documentId` | string \| null | ID of the lightweight source document created for traceability |
|
||
| `memories` | array | The created memory entries |
|
||
| `memories[].id` | string | Unique memory ID |
|
||
| `memories[].memory` | string | The memory content |
|
||
| `memories[].isStatic` | boolean | Whether this is a permanent trait |
|
||
| `memories[].createdAt` | string | ISO 8601 timestamp |
|
||
|
||
<Tip>
|
||
**When to use this vs [Add Context](/ingestion/add-memories)?**
|
||
|
||
Use **Create Memories** when you already know the exact facts to store (user preferences, traits, structured data). Use **Add Context** when you have raw content (conversations, documents, URLs) that Supermemory should process and extract memories from.
|
||
</Tip>
|
||
|
||
---
|
||
|
||
## Forget Memory
|
||
|
||
Soft-delete a single memory — excluded from search results but preserved in the database. Identify it by `id` or by exact `content`, scoped to its `containerTag`.
|
||
|
||
<Tabs>
|
||
<Tab title="fetch">
|
||
```typescript
|
||
await fetch("https://api.supermemory.ai/v4/memories", {
|
||
method: "DELETE",
|
||
headers: {
|
||
"Authorization": `Bearer ${API_KEY}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
// Identify by ID or by exact content
|
||
id: "mem_abc123",
|
||
// content: "John prefers dark mode",
|
||
containerTag: "user_123",
|
||
reason: "outdated information"
|
||
})
|
||
});
|
||
```
|
||
</Tab>
|
||
<Tab title="cURL">
|
||
```bash
|
||
curl -X DELETE "https://api.supermemory.ai/v4/memories" \
|
||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"id": "mem_abc123",
|
||
"containerTag": "user_123",
|
||
"reason": "outdated information"
|
||
}'
|
||
```
|
||
</Tab>
|
||
</Tabs>
|
||
|
||
### Parameters
|
||
|
||
| Parameter | Type | Required | Description |
|
||
|-----------|------|----------|-------------|
|
||
| `id` | string | * | Memory ID to forget |
|
||
| `content` | string | * | Exact content match to forget (alternative to ID) |
|
||
| `containerTag` | string | yes | Container tag / space the memory belongs to |
|
||
| `reason` | string | no | Optional reason recorded as `forgetReason` |
|
||
|
||
\* Either `id` or `content` must be provided.
|
||
|
||
The memory will no longer appear in search results but remains in the database (`isForgotten=true`).
|
||
|
||
---
|
||
|
||
## Forget Matching
|
||
|
||
Forget in bulk in one call, two ways. Give a **`query`** (a prompt or topic) and the service semantically searches the container, an LLM decides which memories are genuinely about your target, and those are soft-deleted — use this for "forget everything about X". Or give an explicit **`ids`** list to forget exactly those memories with no search. Provide one or the other.
|
||
|
||
<Warning>
|
||
This is a bulk, destructive operation. Always **`dryRun` first** to review what would be forgotten, then re-run with `dryRun: false`. The match is semantic, so a too-broad query can select more than you intend — `threshold` and `maxForget` bound the blast radius.
|
||
</Warning>
|
||
|
||
<Tabs>
|
||
<Tab title="fetch">
|
||
```typescript
|
||
// 1) Preview
|
||
const preview = await fetch("https://api.supermemory.ai/v4/memories/forget-matching", {
|
||
method: "POST",
|
||
headers: {
|
||
"Authorization": `Bearer ${API_KEY}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
query: "forget everything about Project Titan",
|
||
containerTag: "user_123",
|
||
dryRun: true
|
||
})
|
||
}).then((r) => r.json());
|
||
// preview.candidates → [{ id, memory, score }, ...]
|
||
|
||
// 2) Apply — pass the ids from the preview to forget exactly that set
|
||
const result = await fetch("https://api.supermemory.ai/v4/memories/forget-matching", {
|
||
method: "POST",
|
||
headers: {
|
||
"Authorization": `Bearer ${API_KEY}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
ids: preview.candidates.map((c) => c.id),
|
||
containerTag: "user_123",
|
||
dryRun: false,
|
||
reason: "project cancelled"
|
||
})
|
||
}).then((r) => r.json());
|
||
// result.forgotten → [{ id, memory, score }, ...]
|
||
// result.forgetBatchId → tagged on every forgotten memory for traceability
|
||
```
|
||
</Tab>
|
||
<Tab title="cURL">
|
||
```bash
|
||
# Preview
|
||
curl -X POST "https://api.supermemory.ai/v4/memories/forget-matching" \
|
||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"query": "forget everything about Project Titan",
|
||
"containerTag": "user_123",
|
||
"dryRun": true
|
||
}'
|
||
|
||
# Apply — pass the ids from the preview to forget exactly that set
|
||
curl -X POST "https://api.supermemory.ai/v4/memories/forget-matching" \
|
||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"ids": ["abc123", "def456", "ghi789"],
|
||
"containerTag": "user_123",
|
||
"dryRun": false,
|
||
"reason": "project cancelled"
|
||
}'
|
||
```
|
||
</Tab>
|
||
</Tabs>
|
||
|
||
### Parameters
|
||
|
||
| Parameter | Type | Required | Description |
|
||
|-----------|------|----------|-------------|
|
||
| `query` | string | one of* | What to forget — a natural-language instruction ("forget everything about Project Titan") or a bare topic ("Project Titan") |
|
||
| `ids` | string[] | one of* | Exact memory ids to forget instead of a `query` — no semantic search. Ids are validated against `containerTag`, so unknown or out-of-scope ids are ignored |
|
||
| `containerTag` | string | yes | Container tag / space to scope the operation to |
|
||
| `dryRun` | boolean | no | When `true`, returns what *would* be forgotten without changing anything. Defaults to `false` |
|
||
| `threshold` | number | no | Similarity floor (0–1) for candidate memories (`query` mode only). Lower casts a wider net. Defaults to `0.5` |
|
||
| `maxForget` | number | no | Safety cap for **query mode** — the most matches one call may forget (1–500). Defaults to `100`. Ignored in id mode, which forgets exactly the ids you pass (bounded only by the 500-item array limit) |
|
||
| `reason` | string | no | Reason recorded as `forgetReason` on each forgotten memory |
|
||
|
||
\* Provide either `query` or `ids`.
|
||
|
||
### Response
|
||
|
||
```json
|
||
{
|
||
"dryRun": false,
|
||
"count": 3,
|
||
"forgetBatchId": "VcuQoGRz4hA4ak5Xu6DRUN",
|
||
"summary": "Forgot 3 memories about \"Project Titan\".",
|
||
"forgotten": [
|
||
{ "id": "mem_1", "memory": "Project Titan ships in Q3", "score": 0.82 }
|
||
]
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `dryRun` | boolean | Whether this was a preview or a real forget |
|
||
| `count` | number | Number of memories selected (dryRun) or forgotten (apply) |
|
||
| `forgetBatchId` | string \| null | ID tagged on every memory forgotten in this call; `null` on dryRun |
|
||
| `summary` | string | One-line summary of the operation (e.g. `Forgot 3 memories about "Project Titan".`) |
|
||
| `candidates` | array | On `dryRun`: the memories that **would** be forgotten (`{ id, memory, score }`) |
|
||
| `forgotten` | array | On apply: the memories that **were** forgotten (`{ id, memory, score }`) |
|
||
|
||
<Note>
|
||
Identity is server-owned: the LLM only ever references opaque handles for the memories a search returned, so it can never forget a memory outside the results it reviewed, and every operation is scoped to the `containerTag` you pass.
|
||
</Note>
|
||
|
||
<Tip>
|
||
**Exact, bound deletes.** Applying with a `query` re-runs the semantic match, so the result can drift from the preview if the container changed in between. To forget *precisely* what you reviewed, take the `id`s from a `dryRun` preview and send them back as `ids` on the apply — the delete is then bound to exactly that set. (`ids` with `dryRun: true` returns the validated set as `candidates` without deleting, so you can confirm first.)
|
||
</Tip>
|
||
|
||
---
|
||
|
||
## Update Memory (Versioned)
|
||
|
||
Update a memory by creating a new version. The original is preserved with `isLatest=false`.
|
||
|
||
<Tabs>
|
||
<Tab title="fetch">
|
||
```typescript
|
||
await fetch("https://api.supermemory.ai/v4/memories", {
|
||
method: "PATCH",
|
||
headers: {
|
||
"Authorization": `Bearer ${API_KEY}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
// Identify by ID or content
|
||
id: "mem_abc123",
|
||
// content: "Original content to match",
|
||
|
||
newContent: "Updated content goes here",
|
||
metadata: {
|
||
tags: ["updated"]
|
||
}
|
||
})
|
||
});
|
||
```
|
||
</Tab>
|
||
<Tab title="cURL">
|
||
```bash
|
||
curl -X PATCH "https://api.supermemory.ai/v4/memories" \
|
||
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"id": "mem_abc123",
|
||
"newContent": "Updated content goes here",
|
||
"metadata": {"tags": ["updated"]}
|
||
}'
|
||
```
|
||
</Tab>
|
||
</Tabs>
|
||
|
||
### Parameters
|
||
|
||
| Parameter | Type | Required | Description |
|
||
|-----------|------|----------|-------------|
|
||
| `id` | string | * | Memory ID to update |
|
||
| `content` | string | * | Original content to match (alternative to ID) |
|
||
| `newContent` | string | yes | New content for the memory |
|
||
| `metadata` | object | no | Updated metadata |
|
||
|
||
\* Either `id` or `content` must be provided.
|
||
|
||
---
|
||
|
||
## Next Steps
|
||
|
||
- [Review Inferred Memories](/recall/memory-review) — Approve or decline low-confidence memories
|
||
- [Document Operations](/ingestion/document-operations) — Manage documents (SDK supported)
|
||
- [Search](/recall/search) — Query your memories
|
||
- [Ingesting Content](/ingestion/add-memories) — Add new content
|