Migrate with an agent
Paste this into Claude Code, Cursor, or Codex. It fetches this guide as markdown and rewrites every legacy call.Migrate by hand
The API base URL and bearer keys do not change. Where parameters live:GET options go in the query string. POST, PATCH, and PUT options go in the JSON body, or as form fields on file uploads; the one exception is list pagination (page, limit, sort, order), which stays in the query string. DELETE options such as moveTo go in the query string, while bulk deletes send their ids in the JSON body. Routes reject options sent in the wrong place with 400. v5 application routes are unversioned; /v5/reference is the interactive v5 reference, not an API path prefix.
Recommended migration process
1
Inventory every legacy call
Search for
/v3/, /v4/, containerTag, containerTags, customId, entityContext, filterByMetadata, filters, and legacy SDK methods such as client.search.execute, client.profile, and client.connections.*.2
Resolve one namespace per request
Move the legacy
containerTag into /ns/{namespace}. Never infer scope from a document or memory ID, and never send multiple namespaces to one v5 request.3
Translate requests by domain
Apply ingestion, updates, content management, search, profiles, forgetting, namespaces, organization, and filter changes independently.
4
Update response readers
Migrate envelopes, includes, pagination, profile buckets, system fields, and partial-error handling before switching traffic.
5
Verify legacy and v5 side by side
Follow the verification and rollout guide. Compare identity and behavior—not raw JSON ordering—and set changed defaults explicitly during rollout.
6
Cut over one domain at a time
Switch traffic, monitor failures and semantic drift, then remove legacy compatibility code only after that domain passes verification.
Upgrade the SDK
The v5 TypeScript SDK ships as the samesupermemory package. Install it, then replace the legacy client:
namespace, path IDs, and query parameters are top-level keys; the JSON body goes under body. Legacy containerTag never appears in a body again. There is no v5 Python SDK yet.
Endpoint map
Connectors
Connector routes also move under the namespace. LegacycontainerTags arrays become one namespace per connector.
authorization is null for config providers (web-crawler, s3, granola), which start syncing immediately. connectors.sync returns { id, status: "queued" } and 409 when a sync is already running.
SDKs, tools and the CLI
Check which client you call the API through before you translate requests. Both official SDKs speak v5; the integration packages do not yet.TypeScript SDK changes
The v5 SDK scopes every content call to onenamespace, passed first. URL values (namespace, then id where there is one) are positional; everything else goes in one object:
If your code passes a
containerTags array, pick one namespace. A v5 document lives in exactly one namespace, so there is no multi-tag write to translate. Code that read across several tags runs one call per namespace and merges the results.
Some v4 methods are gone from the v5 SDK. Most have a v5 way to do the same thing:
Gone with no replacement:
settings.reset, settings.suggestBuckets, documents.fileUrl, and the reason field on forget.
The full method map is in the SDK’s migration guide.
Document ingestion
v5 moves document scope into the URL and keeps repeated caller IDs attached to one evolving document.Rename common fields
Add or append one document
id and status. Its status is the document’s processing state after the request: queued when new work was queued, otherwise the document’s current state (for example done for an unchanged duplicate, or failed for a metadata-only update to a failed document). Possible values: unknown, queued, extracting, chunking, embedding, indexing, done, failed. Repeating the v5 request with id: "conv_1" adds or diffs the new content into that document; it does not silently replace the canonical source.
Batch ingestion
POST /ns/user_1/document/batch. The array accepts 1–600 document objects. taskType and dreaming sit at the top level of the body, next to documents, and apply to every item; document content, ID, context, metadata, grouping, and date stay per item.
results lists accepted documents first, in request order, then failed ones; match each result by id, or by url for a failed item with no ID. Inspect count (accepted), failed, and every item in results; each item’s status is the document’s processing state (unknown, queued, extracting, chunking, embedding, indexing, done, or failed), or error when that item failed, and a batch can contain successful and failed items together.
File ingestion
ReplacePOST /v3/documents/file with POST /ns/{namespace}/document/file. Continue using multipart/form-data:
The API acknowledges the file after durable acceptance, with
status set as for a JSON add. Extraction, indexing, and memory formation continue asynchronously; poll the document rather than assuming the first response means processing is complete.
Processing choices
taskType: "memory"extracts long-term memories;taskType: "superrag"indexes source context without memory generation.dreaming: "dynamic"(default) groups related documents into coherent memory units.dreaming: "instant"processes each document independently and bills one extra operation per document.- Memories appear quickly only with
dreaming: "instant". Underdynamic, a fresh namespace can show zero memories and an empty profile for several minutes. Useinstantfor quickstarts and parity tests.
400.
With the SDK
taskType and dreaming sit next to content in the same object. uploadFile is multipart, so metadata is a JSON string there, not an object.
Verification
- Ingest text, a public URL, and a file, then wait for each document to finish processing.
- Repeat a caller-defined ID and confirm append/diff behavior instead of replacement.
- Submit a mixed-success batch and verify each result matches its document by ID, with per-item errors.
- Confirm metadata and grouping remain filterable after processing.
Document updates
v5 makes the difference between adding new information and replacing the canonical source explicit.Choose the correct write
Update text or URL content
content, supportingContext, metadata, group, or date, plus optional taskType and dreaming (which alone do not count as a change). Supplying content makes it the new canonical source; facts supported only by the previous source can disappear after reprocessing.
Replace a file-backed document
file and replaces the canonical source plus user-controlled metadata, grouping, context, and date. Omitted supporting fields are cleared. Use it when the submitted request is the complete new representation of the file-backed document.
Partially update a file-backed document
file to replace the source while retaining omitted supporting fields, or omit file for metadata-, group-, context-, or date-only changes. metadata and group are JSON-encoded strings; supportingContext and date are plain strings.
With the SDK
replaceWithFile is the POST full replacement and requires file. updateFile is the PATCH partial update; file is optional and metadata merges key by key.
IDs and scope
The pathid may be the Supermemory document ID or your caller-defined ID. It is resolved only inside {namespace}; an ID from another namespace is not a cross-namespace update mechanism.
Processing and conflicts
Content or file replacement is accepted before downstream processing completes. A document still processing, a namespace conflict, or a conflicting internal file path can return409; retry only after the conflicting operation reaches a terminal state.
Verification
- Patch metadata alone and confirm document content and derived facts remain intact.
- Patch content and confirm the new source is canonical after processing.
- Replace a file with POST and confirm omitted user metadata is cleared.
- Patch a file-backed document and confirm omitted fields remain unchanged.
- Attempt the same ID in another namespace and confirm the update is rejected or not found.
Content management
v5 retrieves, lists, and removes content within one explicit namespace.Retrieve a document and its derived context
include as a comma-separated list to return chunks, memories, or both. Keys you omit are absent; requested keys with no results are empty arrays. Lifecycle fields move under system:
system.status is one of unknown, queued, extracting, chunking, embedding, indexing, done, or failed.
Retrieve a memory and its history
v5
id, memory, metadata, isStatic, isInference, isLatest, isForgotten, version, and system.createdAt/updatedAt. A memory from another namespace returns 404; a forgotten memory, or one past its forget_after, is still returned with isForgotten: true.
include=relatedaddsincluded.related.parents(earlier versions),children(newer versions), andsiblings(memories connected byextendsorderives). Each list walks outward from the memory until it holdsrelatedLimititems (default10, maximum100). Forgotten memories and memories in other namespaces are left out.include=documentsaddsincluded.document, the most recently updated source document. With both values, every related memory also carries its owndocument.
List documents, chunks, or memories
type to documents, chunks, or memories. Pagination and sorting move to the query string as plain integers and values; the body takes an optional filter and, for memories, include. Defaults are page=1, limit=10 (maximum 100), sort=createdAt, and order=desc.
Memory lists hide forgotten memories and memories past their forget_after. Send "include": {"forgotten": true} to list them too; they come back with isForgotten: true. Document memories (include=memories on GET /ns/{namespace}/document/{id}) report the same flag.
Every response contains documents, chunks, memories, and pagination. Only the selected resource array is populated. Replace legacy memories assumptions in document-list callers with documents.
Delete documents
count and per-ID errors; HTTP success can include partial failures.
With the SDK
system.status on each item returned by supermemory.list(namespace, "documents"). Chunks come from supermemory.list(namespace, "chunks") or documents.get with include: ["chunks"].
Forget memories
Both return
{ count, matches, errors }. For drift-free semantic deletion, preview with dryRun: true, review the IDs, then submit them to the exact-ID endpoint.
See memory forgetting for the complete dry-run, approval, response, and audit workflow.
Verification
- Assert requested empty includes are
[], while omitted includes are absent. - Paginate each resource type until
currentPage >= totalPages; unselected arrays stay empty. - Verify chunk rows contain their parent
documentId. - Exercise partial document-delete failures and semantic dry runs.
- Verify IDs cannot read, list, or delete content outside their namespace.
Search
v5 searches one namespace, defaults to hybrid recall, and takes every option in one typed JSON body. Search has no query-string parameters.Request mapping
With the SDK
query, searchMode, limit, threshold, filter, include, rerank, and rewriteQuery all go in one object (the JSON body over HTTP). Omitting searchMode gives hybrid.
Changed defaults
Set mode and threshold explicitly while comparing versions. After parity testing, remove them only if you want the broader v5 hybrid defaults.
Search modes
Legacy
include.chunks has no v5 equivalent. Choose chunks or hybrid instead.
Included context and ranking
include is an object of booleans in the body, e.g. "include": {"documents": true, "related": true}. Each flag defaults to false.
include.documentsadds the most relevant source document to each result.include.relatedadds parent, child, and sibling memories. Related memories come only from the same namespace and must match the request’sfilter, so they never surface content the search itself would exclude.include.forgottenlets forgotten and expired memories appear in results, including as primary results.rerankacceptsnone,order, oraggregate;rewriteQuerycontrols retrieval-oriented query rewriting.
Response mapping
Each primary result contains either
memory, chunk, or both only if the contract allows it. Branch on field presence rather than assuming one result shape.
Verification
- Compare IDs using explicit v4-equivalent defaults, then test v5 hybrid behavior separately.
- Cover all three modes, thresholds at
0and1, each rerank option, and query rewriting. - Cover every include alone and in combination, including empty results.
- Verify filters, namespace isolation, result limits, and invalid body/query placement.
Profiles and buckets
v5 returns a maintained profile directly and gives profile bucket definitions their own namespace-scoped resource.Remove search behavior from profile calls
q, threshold, and include. If the caller needs query-ranked results, issue a separate v5 search request. Move containerTag to the path and rename filters to singular filter.
Read the v5 profile shape
static and dynamic are always returned and cannot be disabled. Omit buckets in the request to return every effective custom bucket; pass up to 50 names to narrow only the bucket section.
Read bucket definitions
Add or edit namespace buckets
Delete namespace buckets
With the SDK
supermemory.profile takes no query. body is optional and accepts only filter and buckets. Read profile.static, profile.dynamic, and profile.buckets[name] as arrays of { id, memory }.
Verification
- Confirm every profile response contains
static,dynamic, andbuckets. - Compare omitted buckets with one-name and multi-name narrowing.
- Add, edit, and delete a namespace bucket without replacing omitted buckets.
- Attempt to mutate an inherited organization bucket and expect the documented error.
Memory forgetting
v5 scopes forgetting to one namespace and returns the same result envelope for exact and semantic requests.Choose exact or semantic forgetting
Forget exact IDs
matches and missing or ineligible IDs in errors, so HTTP success does not imply every requested ID changed.
Preview a semantic request
dryRun: true performs selection without changing memory state. dryRun: false forgets the memories selected when that request executes.
Avoid selection drift
dryRun: false can select a different set if memories changed after preview.
Read the normalized response
count always equals matches.length. Both dry-run and applied semantic requests use this shape; the payload alone does not replace your record of which mode was sent.
With the SDK
dryRun is required on forgetMatching. Both calls return { count, matches, errors }.
Removed memory-write routes
Direct v4 memory creation and version updates (client.memories.add, client.memories.updateMemory) have no v5 replacement. Ingest source material through document routes and update the canonical document when facts change.
Verification
- Exercise all-success, partial-success, duplicate, unknown, and cross-namespace ID sets.
- Confirm dry runs leave matched memories recallable.
- Apply reviewed IDs exactly and confirm normal recall excludes them.
- Persist the request mode alongside audit logs for semantic operations.
Namespaces
v5 renames the public isolation boundary from container tag to namespace. Existing values remain valid identifiers; no stored data rename is required.Endpoint mapping
GET /ns is an alias for GET /namespaces. Prefer /namespaces in new integrations.
List namespaces
The list is paginated:GET /namespaces?page=1&limit=10 returns {namespaces, pagination}, newest first, with limit up to 100. Each entry now exposes id, namespace, documentCount, memoryCount, nullable description, and system.createdAt/updatedAt. Update readers that still expect containerTag, flat timestamps, or unbounded internal settings.
Read and update settings
namespace, supportingContext, and lifecycle timestamps. Profile buckets have their own /profile/buckets resource and are not namespace settings.
Send supportingContext: null to remove existing context. Omitting the field entirely is invalid because PATCH requires at least one supported setting.
Permanently delete a namespace
moveTo, deletion is synchronous and returns 200 with status: "deleted", deletedDocumentsCount, and deletedMemoriesCount. Branch on status (deleted or queued) to tell the two outcomes apart. This removes the namespace and its content.
Move then remove a namespace
moveTo is a query parameter. This returns 202 with status: "queued" and operationId. The destination must differ from the source. Do not treat acceptance as completed migration.
Legacy merge can accept multiple sources; v5 moves one source per request. Run multi-source migrations sequentially and record each operation independently.
With the SDK
Replace calls to/v3/container-tags/* with supermemory.namespaces:
namespaces.list() returns { namespaces, pagination }, where each namespace is { id, namespace, documentCount, memoryCount, description, system }. A delete without moveTo returns { status: "deleted", namespace, deletedDocumentsCount, deletedMemoriesCount }; with moveTo it returns { status: "queued", operationId, namespace, moveTo }.
Verification
- Confirm existing container-tag values resolve unchanged as namespace paths.
- Compare namespace counts with namespace-scoped document and memory lists.
- Verify a permanent delete returns final counts while a move returns
202. - Verify restricted callers cannot read or mutate namespaces outside their scope.
- Verify only organization-authorized callers can change settings or lifecycle.
Organization settings
v5 exposes only the organization-wide context needed to guide memory formation. Internal controls and profile bucket mutation are no longer part of this settings resource.Endpoint mapping
Read organization settings
namespaceCount is informational and cannot be changed through PATCH.
Update organization context
null to remove it. Empty strings are rejected.
Organization updates require an organization administrator. Do not silently fall back to namespace context when the caller receives 403.
With the SDK
Removed public operations
- Organization profile-bucket mutation is not exposed through organization settings.
- Bucket suggestion is not part of v5.
- Organization data reset is not part of v5.
- Namespace-owned profile buckets are managed through
/ns/{namespace}/profile/buckets.
Verification
- Compare the v5 context with the legacy
filterPromptbefore cutover. - Set, replace, and clear organizational context.
- Confirm
namespaceCountagrees withpagination.totalItemsfromGET /namespacesfor the same credentials. - Verify non-admin callers receive
403on PATCH. - Confirm removed fields are not required by downstream configuration code.
Typed filters
v5 uses one optional singularfilter field for search, profiles, and list operations.
Shape
_, ., and -. Expressions allow up to five nested levels and 200 operands per logical group.
Operator mapping
Before and after
With the SDK
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.
Deterministic conversion
- Rename outer
filterstofilter. - Recursively replace
AND/ORobjects with{ operator, operands }. - Rename
keytofield. - Convert legacy flags into one explicit operator.
- Keep numeric values as JSON numbers rather than numeric strings.
- Remove legacy
filterType,negate,numericOperator, andignoreCasekeys.
Verification
- Compare result IDs for equality, inequality, contains, numeric, array, nested AND, and nested OR fixtures.
- Add negative tests: legacy shapes, empty operands, incompatible value types, and unknown keys must return
400. - Confirm omitted
filterpreserves unfiltered behavior.
Verification and rollout
Treat migration as a behavioral comparison, not a raw response snapshot update.Build deterministic fixtures
Use an isolated namespace with stable IDs and fixed source content. Include plaintext, URL, file, batch, metadata, grouping, profile facts, related memories, forgotten memories, and empty-result cases. Record each legacy request, v5 request, expected semantic result, and intentional difference. Never compare generated IDs, signed URLs, timing, or JSON object order unless the contract guarantees them.Compare writes
- Repeated POST appends or diffs; PATCH replaces canonical content.
- Batch outcomes list accepted documents first, then failures, and surface partial failures; match by ID, not position.
- Metadata-only updates leave source content unchanged.
- Accepted writes are polled until processing reaches a terminal state.
Compare reads and recall
- Document includes are absent when omitted and empty arrays when requested without results.
- Unified list responses populate only the selected resource array.
metadatais always an object,{}when empty; it is nevernull.- Search parity uses explicit v4-equivalent mode and threshold before testing v5 defaults.
- Profiles always contain static, dynamic, and bucket sections.
Exercise boundaries
Classify differences
Cut over by domain
- Ship v5 request construction behind a per-domain flag.
- Dual-read or shadow-call where side effects allow it.
- Switch ingestion, content management, search, profiles, then settings independently.
- Monitor validation failures, authorization failures, latency, empty-result rate, and processing failures.
- Retain the legacy path until the observation window passes.
Completion checklist
- No application API call accidentally uses a
/v5prefix. - Connector calls use
/ns/{namespace}/connectorsorsupermemory.connectors.*, not/v3/connections. - No legacy field aliases or response readers remain.
- Every changed default is either accepted intentionally or passed explicitly.
- Rollback restores the previous caller without requiring data repair.
Operations without a direct replacement
- Direct memory creation and version updates: ingest or replace a source document instead.
- Organization bucket suggestion and organization reset: not part of the v5 public surface.
- Connector resource listing and hosted pickers from
/v3/connections: usesupermemory.connectors.getwithinclude: ["syncs", "picker"]instead. Connector create, list, get, update, delete, and sync all have v5 routes under/ns/{namespace}/connectors.
/reference always points to the latest public version.