diff --git a/apps/docs/concepts/filtering.mdx b/apps/docs/concepts/filtering.mdx
index da2b513c..6beaa1aa 100644
--- a/apps/docs/concepts/filtering.mdx
+++ b/apps/docs/concepts/filtering.mdx
@@ -22,7 +22,7 @@ Both can be used independently or together for precise filtering.
## Namespaces
-Namespaces create isolated memory spaces. Use them to separate memories by user, project, or any logical boundary. The namespace is part of the URL (`/ns/{namespace}/...`), so every SDK call takes it as a top-level key.
+Namespaces create isolated memory spaces. Use them to separate memories by user, project, or any logical boundary. The namespace is part of the URL (`/ns/{namespace}/...`), so namespace-scoped SDK calls take it as the first argument.
### Adding Memories to a Namespace
@@ -42,7 +42,7 @@ const results = await supermemory.search("user_123", {
```
-Each search is scoped to a single namespace. Passing `namespace: "user_123"` restricts results to memories stored in that namespace.
+Each search is scoped to a single namespace. Passing `"user_123"` as the namespace restricts results to memories stored in that namespace.
### Recommended patterns
@@ -336,7 +336,6 @@ const results = await supermemory.search("user_123", { // Scopes results to this
### Metadata key rules
- Allowed characters: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`
-- Max length: 64 characters
- No spaces or special characters
- Keys are literal: `customer.plan` is one key named `customer.plan`, not a nested path
diff --git a/apps/docs/concepts/rules.mdx b/apps/docs/concepts/rules.mdx
index dab3452a..4a55e898 100644
--- a/apps/docs/concepts/rules.mdx
+++ b/apps/docs/concepts/rules.mdx
@@ -30,7 +30,7 @@ Agents benefit most from having a _general_ idea of the topic alongside tools to
Two things about this table that trip people up.
-**"Remember" and "look up" are both supermemory, but different reads.** You [ingest documents](/ingestion/add-memories); the pipeline derives memories from them and maintains a profile per [namespace](/concepts/container-tags). `supermemory.search({ searchMode: "memories" })` recalls the derived facts. `supermemory.search({ searchMode: "chunks" })` recalls the source material itself. A support agent usually needs both: memories for "this customer runs self-hosted and already tried reinstalling", documents for the actual troubleshooting guide.
+**"Remember" and "look up" are both supermemory, but different reads.** You [ingest documents](/ingestion/add-memories); the pipeline derives memories from them and maintains a profile per [namespace](/concepts/container-tags). `supermemory.search(namespace, { query, searchMode: "memories" })` recalls the derived facts. `supermemory.search(namespace, { query, searchMode: "chunks" })` recalls the source material itself. A support agent usually needs both: memories for "this customer runs self-hosted and already tried reinstalling", documents for the actual troubleshooting guide.
**Supermemory is not your system of record.** There's no SQL over memories, no joins, no aggregates, no querying by primary key. Keep transactional data in your database, and ingest the narrative *around* it ("the customer disputed invoice #4821 and churned over it") so your AI understands what the rows mean.
@@ -56,10 +56,10 @@ client.add(
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/test/document?taskType=superrag" \
+curl -X POST "https://api.supermemory.ai/ns/test/document" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
- -d '{ "content": "testing" }'
+ -d '{ "content": "testing", "taskType": "superrag" }'
```
@@ -86,10 +86,10 @@ results = client.search(
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/test/search?searchMode=hybrid" \
+curl -X POST "https://api.supermemory.ai/ns/test/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
- -d '{ "query": "test" }'
+ -d '{ "query": "test", "searchMode": "hybrid" }'
```
@@ -252,11 +252,12 @@ results = client.search(
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/org-supermemory/search?searchMode=chunks" \
+curl -X POST "https://api.supermemory.ai/ns/org-supermemory/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "preferred language",
+ "searchMode": "chunks",
"filter": { "field": "team", "operator": "eq", "value": "Research" }
}'
```
diff --git a/apps/docs/concepts/super-rag.mdx b/apps/docs/concepts/super-rag.mdx
index 50c4568a..4e1d40e6 100644
--- a/apps/docs/concepts/super-rag.mdx
+++ b/apps/docs/concepts/super-rag.mdx
@@ -33,7 +33,7 @@ No chunking strategies to configure. No embedding models to choose. It just work
By default, every `supermemory.add()` call runs on the **memory** path (`taskType: "memory"`): Supermemory chunks and embeds the content for retrieval, *and* runs it through the memory pipeline — extracting facts, updating the profile, and linking it into the knowledge graph.
-If you're ingesting content that's purely reference material — documentation, a large PDF, a knowledge base article — and you don't need Supermemory to derive personal facts or update a profile from it, set `taskType: "superrag"` (a query parameter, so a top-level key in the SDK). It skips the memory pipeline entirely and only does the chunk → embed → index work needed to make the content searchable.
+If you're ingesting content that's purely reference material — documentation, a large PDF, a knowledge base article — and you don't need Supermemory to derive personal facts or update a profile from it, set `taskType: "superrag"` in the request body. It skips the memory pipeline entirely and only does the chunk → embed → index work needed to make the content searchable.
@@ -53,10 +53,10 @@ client.add(
```
```bash cURL
-curl -X POST "https://api.supermemory.ai/ns/docs_kb/document?taskType=superrag" \
+curl -X POST "https://api.supermemory.ai/ns/docs_kb/document" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
- -d '{ "content": "..." }'
+ -d '{ "content": "...", "taskType": "superrag" }'
```
@@ -100,21 +100,9 @@ PDFs and documents are chunked by **semantic sections** — headers, paragraphs,
### Code
-Code is chunked using [code-chunk](https://github.com/supermemoryai/code-chunk), our open-source library that understands AST (Abstract Syntax Tree) boundaries:
+When content is recognized as Markdown, fenced code blocks are kept whole when they fit in a chunk. Larger blocks are split and re-wrapped in the original fence, including its language tag. Overlap can contain part of a previous line, so chunks are not guaranteed to be independently valid code.
-- Functions and methods stay intact
-- Classes are chunked by method
-- Import statements grouped separately
-- Comments attached to their code blocks
-
-```typescript
-// A 500-line file becomes meaningful chunks:
-// - Imports + type definitions
-// - Each function as a separate chunk
-// - Class methods individually indexed
-```
-
-This means searching for "authentication middleware" finds the actual function, not a random slice of code.
+Raw source files and content not recognized as Markdown use plain-text chunking. A lone fenced block may not be enough for automatic Markdown detection.
### Web pages
diff --git a/apps/docs/quickstart.mdx b/apps/docs/quickstart.mdx
index 9d528c3a..d0b95173 100644
--- a/apps/docs/quickstart.mdx
+++ b/apps/docs/quickstart.mdx
@@ -97,13 +97,14 @@ print(conv.id, conv.status) # e.g. "queued"
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/user_4f8a/document?dreaming=instant" \
+curl -X POST "https://api.supermemory.ai/ns/user_4f8a/document" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "user: Just got back from Tokyo — the team offsite went great.\nassistant: Glad it went well! Anything stand out?\nuser: Sarah presented the Q3 roadmap at the offsite.\nassistant: Sounds like a big moment for her.\nuser: She is being promoted to VP of Product.\nassistant: Congrats to Sarah — that is huge.\nuser: I need a gift idea for my VP of Product.\nassistant: Happy to help brainstorm something personal.",
"id": "chat_offsite_2026",
- "metadata": { "type": "conversation" }
+ "metadata": { "type": "conversation" },
+ "dreaming": "instant"
}'
```
@@ -164,13 +165,14 @@ print(doc.id, doc.status)
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/user_4f8a/document?taskType=superrag" \
+curl -X POST "https://api.supermemory.ai/ns/user_4f8a/document" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "# Team notes — gifts & recognition\n\nWhen someone is promoted to VP or above, the company recommends a thoughtful gift in the $75–$150 range. Experiences tied to recent team milestones land better than generic swag.\n\nFor product leadership, books on platform strategy or a dinner near the last offsite city are common picks. Tokyo offsites often inspire travel-themed gifts.",
"id": "doc_gift_policy",
- "metadata": { "type": "document", "source": "handbook" }
+ "metadata": { "type": "document", "source": "handbook" },
+ "taskType": "superrag"
}'
```
@@ -253,10 +255,14 @@ for hit in rag.results:
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/user_4f8a/search?searchMode=chunks&limit=3" \
+curl -X POST "https://api.supermemory.ai/ns/user_4f8a/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
- -d '{ "query": "gift ideas for a VP promotion after a Tokyo offsite" }'
+ -d '{
+ "query": "gift ideas for a VP promotion after a Tokyo offsite",
+ "searchMode": "chunks",
+ "limit": 3
+ }'
```
@@ -300,12 +306,14 @@ print(memories.to_json())
```
```bash curl
-curl -X POST "https://api.supermemory.ai/ns/user_4f8a/search?searchMode=memories&limit=5" \
+curl -X POST "https://api.supermemory.ai/ns/user_4f8a/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What gift should I get, and why?",
- "include": { "related": true }
+ "searchMode": "memories",
+ "include": { "related": true },
+ "limit": 5
}'
```
diff --git a/apps/docs/recall/memory-review.mdx b/apps/docs/recall/memory-review.mdx
index 818cd066..d246e24a 100644
--- a/apps/docs/recall/memory-review.mdx
+++ b/apps/docs/recall/memory-review.mdx
@@ -7,8 +7,8 @@ icon: "/icons/hugeicons/check-list.svg"
Supermemory's graph derives new facts from patterns across your existing memories
(see [graph memory](/concepts/graph-memory)). Because nobody stated these facts
-directly, they are flagged as inferred (`isInference: true`) and **down-weighted in
-search until someone confirms them**.
+directly, they are flagged as inferred (`isInference: true`) until someone confirms
+them.
These two endpoints let you build a review flow on top of that queue: list the
inferred memories awaiting review, then approve, decline or undo a decision on each one.
@@ -20,19 +20,17 @@ These endpoints are scoped to a single [namespace](/concepts/container-tags)
path parameter.
-## How review affects ranking
+## What review changes
-While a memory is unreviewed and inferred it is down-weighted in search, so the
-engine's guesses rank below facts you stated explicitly. Reviewing it resolves that
-either way:
+Reviewing an inferred memory resolves it either way:
| Action | Result | Effect on search |
|--------|--------|------------------|
-| **Approve** | `isInference` cleared | Ranks like a stated fact — no longer down-weighted |
+| **Approve** | `isInference` cleared | Stays in search, no longer flagged as inferred |
| **Decline** | `isForgotten` set | Removed from search entirely — a rejected guess is forgotten |
-| **Undo** | back to unreviewed | Returns to the queue; inferred and down-weighted again |
+| **Undo** | back to unreviewed | Returns to the queue, flagged as inferred again |
-A reviewed memory is stamped with `reviewStatus` in its metadata so it drops out of the
+A reviewed memory gets an internal review stamp in its metadata so it drops out of the
review queue (declined memories also leave search, since they're forgotten). **Undo**
clears that stamp — and un-forgets a declined memory — bringing it back.
@@ -98,7 +96,7 @@ GET /v3/container-tags/{containerTag}/inferred
| `memories[].createdAt` | string | ISO 8601 timestamp |
| `memories[].updatedAt` | string | ISO 8601 timestamp |
| `memories[].metadata` | object \| null | Arbitrary metadata stored on the memory |
-| `total` | number | Count of unreviewed inferred memories returned |
+| `total` | number | Total unreviewed inferred memories in the queue; can exceed the number returned in `memories` |
The queue returns up to **50** memories, ordered by `parentCount` descending (most
@@ -166,8 +164,8 @@ The reject action is named **`decline`**. There is no `reject` value.
**Action semantics:**
-- **`approve`** — Promote the memory: clears `isInference`, so it ranks like a stated
- fact instead of a down-weighted guess. Stamps `reviewStatus: "approved"`.
+- **`approve`** — Promote the memory: clears `isInference`, so it's treated as a
+ confirmed fact. Stamps `reviewStatus: "approved"`.
- **`decline`** — Reject the suggestion: the memory is **forgotten**
(`isForgotten: true`) and stamped `reviewStatus: "declined"`, so it leaves both
search and the review queue.
@@ -198,6 +196,7 @@ The reject action is named **`decline`**. There is no `reject` value.
| Status | When |
|--------|------|
| `401` | Missing or invalid authentication |
+| `403` | Your key can't access this namespace, or lacks write access to it |
| `404` | The namespace or memory was not found in your organization |
| `409` | The memory isn't reviewable for this action — it's not an inferred memory, or there's no prior review to undo |
@@ -286,4 +285,4 @@ a request and the memory simply stays in the queue for a later session.
- [Graph Memory](/concepts/graph-memory) — How inferred (`derive`) memories are created
- [Memory Operations](/recall/memory-operations) — Forget memories
-- [Search](/recall/search) — How inferred memories are ranked in results
+- [Search](/recall/search) — Results flag inferred memories with `isInference`
diff --git a/apps/docs/recall/search.mdx b/apps/docs/recall/search.mdx
index 38d4d858..cc5817bc 100644
--- a/apps/docs/recall/search.mdx
+++ b/apps/docs/recall/search.mdx
@@ -12,7 +12,7 @@ Search through your memories and documents with a single API call. Each search r
-**TypeScript SDK:** one call, `supermemory.search(namespace, { query, searchMode })`. `searchMode` (`"memories"`, `"chunks"`, or `"hybrid"`) picks what comes back. There is no v5 Python SDK yet; the Python tab shows the legacy client.
+**SDKs:** one call, `supermemory.search(namespace, { query, searchMode })` in TypeScript or `client.search(namespace, query=..., search_mode=...)` in Python. `searchMode` (`"memories"`, `"chunks"`, or `"hybrid"`) picks what comes back.
## Quick start
@@ -54,10 +54,10 @@ Search through your memories and documents with a single API call. Each search r
```bash
- curl -X POST "https://api.supermemory.ai/ns/user_123/search?searchMode=hybrid&limit=5" \
+ curl -X POST "https://api.supermemory.ai/ns/user_123/search" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
- -d '{ "query": "machine learning" }'
+ -d '{ "query": "machine learning", "searchMode": "hybrid", "limit": 5 }'
```
@@ -72,6 +72,7 @@ Search through your memories and documents with a single API call. Each search r
"similarity": 0.91,
"metadata": { "topic": "interests" },
"isLatest": true,
+ "isInference": false,
"system": { "createdAt": "2024-01-15T10:30:00.000Z", "updatedAt": "2024-01-15T10:30:00.000Z" }
},
{
@@ -80,6 +81,7 @@ Search through your memories and documents with a single API call. Each search r
"similarity": 0.87,
"metadata": { "source": "onboarding_doc" },
"isLatest": true,
+ "isInference": false,
"system": { "createdAt": "2024-01-14T09:15:00.000Z", "updatedAt": "2024-01-14T09:15:00.000Z" }
}
],
@@ -95,7 +97,7 @@ In hybrid mode, results contain either a `memory` field (extracted facts) or a `
## Parameters
-`namespace` is the URL path. Every other option goes in the JSON body (the second argument in the SDKs).
+`namespace` is the URL path. Every other option goes in the JSON body: the second argument in TypeScript, or keyword arguments in Python. Search takes no query-string parameters; sending any returns `400`.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
@@ -104,10 +106,10 @@ In hybrid mode, results contain either a `memory` field (extracted facts) or a `
| `searchMode` | string | `"hybrid"` | `"hybrid"` (recommended), `"memories"`, or `"chunks"` |
| `limit` | number | 10 | Max results (max 100) |
| `threshold` | 0-1 | 0.3 | Similarity cutoff (higher = fewer, better results) |
-| `rerank` | string | `"none"` | `"none"`, `"order"` (re-score for relevance, +100ms), or `"aggregate"` |
-| `rewriteQuery` | boolean | false | Generate multiple rewrites, search all of them, and merge results. No extra cost, but adds latency |
+| `rerank` | string | `"none"` | `"none"`, `"order"` (re-score for relevance, +100ms), or `"aggregate"`. Successful reranking or aggregation can bill one extra [operation](/overview/billing#what-is-an-operation); setting the option alone does not guarantee it runs |
+| `rewriteQuery` | boolean | false | Generate multiple rewrites, search all of them, and merge results. Adds latency and can bill one extra [operation](/overview/billing#what-is-an-operation) when rewriting runs successfully |
| `filter` | object | — | Metadata filter expression. See [Filtering](#filtering) |
-| `include` | object | — | `{ documents, related, forgotten }` — opt in to extra context per result |
+| `include` | object | all `false` | `{ documents, related, forgotten }` — opt in to extra context per result |
Defaults changed from v4: `searchMode` was `memories` and is now `hybrid`; `threshold` was `0.6` and is now `0.3`. Set both explicitly if you are comparing against v4 results.
@@ -196,9 +198,9 @@ await supermemory.search("user_123", { query: "...", threshold: 0.8 });
### Attachments
-- `attach.documents` adds the most relevant source document to each result.
-- `attach.related` adds parent, child, and sibling memories (see [graph memory](/concepts/graph-memory)).
-- `attach.forgotten` allows forgotten memories in related context. By default, search excludes memories that have been forgotten or have passed their `forgetAfter` expiration.
+- `include.documents` adds the most recently updated source document to each result when one is available.
+- `include.related` adds parent, child, and sibling memories (see [graph memory](/concepts/graph-memory)).
+- `include.forgotten` lets forgotten and expired memories appear in results. By default, search excludes memories that have been forgotten or have passed their `forgetAfter` expiration.
```typescript
await supermemory.search("user_123", {
@@ -238,10 +240,11 @@ async function getContext(userId: string, message: string) {
memory?: string; // Present for memory results
chunk?: string; // Present for document chunk results
similarity: number; // 0-1
- metadata: object | null;
+ metadata: Record; // {} when none
isLatest: boolean;
- system: { createdAt: string; updatedAt: string };
- included?: { // Only when you pass attach
+ isInference: boolean; // false for chunks
+ system: { createdAt?: string; updatedAt: string };
+ included?: { // Only when you pass include
document?: object;
related?: { parents: object[]; children: object[]; siblings: object[] };
};
diff --git a/apps/docs/snippets/api-v5-filters.mdx b/apps/docs/snippets/api-v5-filters.mdx
index 9e7e7ab3..2a96cbd8 100644
--- a/apps/docs/snippets/api-v5-filters.mdx
+++ b/apps/docs/snippets/api-v5-filters.mdx
@@ -83,7 +83,7 @@ await supermemory.search("user_1", {
```
-`filter` is a typed object under `body`, not a JSON string. The same shape works in `supermemory.list` and `supermemory.profile`. Keys are literal: `customer.plan` is one field name, not a nested path.
+`filter` is a typed object in the request body (a field of the options object in the SDKs), not a JSON string. The same shape works in `supermemory.list` and `supermemory.profile`. Keys are literal: `customer.plan` is one field name, not a nested path.
### Deterministic conversion