mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-11 03:37:56 +00:00
Rewrites 339 TypeScript calls across 50 pages from the rc.5 `method({ namespace, body })` form to the shipped `method(namespace, { ... })` form, and aligns field names with the live v5 spec: `attach` to `include`, `authUrl` to `authorization`, `lastSync` to `latestRun`, `deletedCount` to `count`, and the paginated `namespaces.list()`.
Renames container tags to namespaces across concepts, connectors, integrations and snippets. The namespace pages keep container tag in the description, search keywords and a rename note so old searches still land, and the v3 reference page points at v5.
The migration guide's SDK table now covers both 5.0.0 SDKs, and the SDK integration page uses the real client options (`baseUrl`, `timeoutInSeconds`, `maxRetries`) and error classes.
364 lines
12 KiB
Text
364 lines
12 KiB
Text
---
|
|
title: 'Supermemory SDK'
|
|
sidebarTitle: "Supermemory SDK"
|
|
description: 'Official Python and JavaScript SDKs for Supermemory'
|
|
icon: "/images/supermemory.svg"
|
|
---
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Python SDK" icon="/icons/hugeicons/python.svg" href="https://pypi.org/project/supermemory/">
|
|
pip install supermemory
|
|
</Card>
|
|
<Card title="JavaScript SDK" icon="/icons/hugeicons/java-script.svg" href="https://www.npmjs.com/package/supermemory">
|
|
npm install supermemory
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
<Tip>
|
|
Both SDKs also work against [self-hosted Supermemory](/self-hosting/overview) running `supermemory-server` v0.0.9 or later. Pass `baseUrl: "http://localhost:6767"` (TypeScript) or `base_url="http://localhost:6767"` (Python) when creating the client.
|
|
</Tip>
|
|
|
|
<Tabs>
|
|
<Tab title="TypeScript">
|
|
## Install the TypeScript SDK
|
|
|
|
```bash
|
|
npm i supermemory
|
|
```
|
|
|
|
## Start a TypeScript client
|
|
|
|
```typescript
|
|
import { Supermemory } from "supermemory";
|
|
|
|
const supermemory = new Supermemory({ apiKey: process.env.SUPERMEMORY_API_KEY });
|
|
```
|
|
|
|
One rule for every call: URL values first as positional arguments (`namespace`, then `id` where there is one), then a single object with everything else. A namespace scopes memories to one user, workspace, or tenant, and you pass it on every call.
|
|
|
|
## Add
|
|
|
|
```typescript
|
|
const { id, status } = await supermemory.add("user_123", {
|
|
content: "Meeting notes from Q1 planning",
|
|
id: "meeting-q1", // optional, your own id; the response echoes it
|
|
metadata: { category: "engineering", priority: "high" },
|
|
dreaming: "instant",
|
|
});
|
|
```
|
|
|
|
`dreaming` defaults to `"dynamic"`, which batches memory extraction. A fresh namespace can show zero memories and an empty profile for minutes. Pass `dreaming: "instant"` in quick-start flows and anywhere the next step is a memory search or a profile read.
|
|
|
|
## Search
|
|
|
|
```typescript
|
|
const { results, searchTime } = await supermemory.search("user_123", {
|
|
query: "planning notes",
|
|
limit: 10,
|
|
});
|
|
|
|
for (const result of results) {
|
|
console.log(result.memory ?? result.chunk, result.similarity);
|
|
}
|
|
```
|
|
|
|
`searchMode` is `"hybrid"` (default), `"memories"`, or `"chunks"`. Filter on metadata with a typed expression:
|
|
|
|
```typescript
|
|
const { results } = await supermemory.search("user_123", {
|
|
query: "design document",
|
|
filter: { field: "category", operator: "eq", value: "engineering" },
|
|
searchMode: "chunks",
|
|
});
|
|
```
|
|
|
|
Two defaults changed from the legacy SDK: `threshold` is now `0.3` (was `0.6`) and `searchMode` is now `hybrid` (was `memories`). Set both explicitly if you compare results against old code.
|
|
|
|
## Profile
|
|
|
|
```typescript
|
|
const { profile } = await supermemory.profile("user_123");
|
|
console.log(profile.static);
|
|
console.log(profile.dynamic);
|
|
console.log(profile.buckets);
|
|
```
|
|
|
|
Buckets group profile facts under names you define:
|
|
|
|
```typescript
|
|
await supermemory.profiles.setBuckets("user_123", {
|
|
buckets: { work: "Job, team, and current projects" },
|
|
});
|
|
|
|
const buckets = await supermemory.profiles.getBuckets("user_123");
|
|
|
|
await supermemory.profiles.deleteBuckets("user_123", {
|
|
buckets: ["work"],
|
|
});
|
|
```
|
|
|
|
## List
|
|
|
|
```typescript
|
|
const { documents, pagination } = await supermemory.list("user_123", "documents", {
|
|
page: 1,
|
|
limit: 20,
|
|
sort: "createdAt",
|
|
order: "desc",
|
|
});
|
|
|
|
console.log(documents[0]?.system.status, pagination.totalPages);
|
|
```
|
|
|
|
`type` is required: `"documents"`, `"chunks"`, or `"memories"`. The response always has `documents`, `chunks`, `memories`, and `pagination`, and only the requested array is filled. Pass `{ filter }` to narrow the list.
|
|
|
|
## Documents
|
|
|
|
```typescript
|
|
const doc = await supermemory.documents.get("user_123", "meeting-q1", {
|
|
include: ["chunks", "memories"],
|
|
});
|
|
console.log(doc.title, doc.summary, doc.system.status);
|
|
|
|
await supermemory.documents.update("user_123", "meeting-q1", {
|
|
metadata: { priority: "low" },
|
|
});
|
|
|
|
await supermemory.documents.batchAdd("user_123", {
|
|
documents: [{ content: "First note" }, { content: "Second note" }],
|
|
});
|
|
|
|
await supermemory.documents.uploadFile("user_123", { // file is a File or Blob
|
|
file,
|
|
metadata: JSON.stringify({ source: "upload" }),
|
|
});
|
|
|
|
const { count, errors } = await supermemory.documents.delete("user_123", {
|
|
ids: ["meeting-q1"],
|
|
});
|
|
```
|
|
|
|
`uploadFile` is multipart, so `metadata` is a JSON string there. `delete` can return partial failures, so check `errors` as well as `count`.
|
|
|
|
## Memories
|
|
|
|
```typescript
|
|
const preview = await supermemory.memories.forgetMatching("user_123", {
|
|
query: "old office address",
|
|
dryRun: true,
|
|
});
|
|
|
|
const { count } = await supermemory.memories.forget("user_123", {
|
|
ids: preview.matches.map((match) => match.id),
|
|
});
|
|
```
|
|
|
|
`dryRun` is required on `forgetMatching`. Preview with `dryRun: true`, review `matches`, then forget by id. There is no direct memory create or update: ingest or update the source document instead.
|
|
|
|
## Namespaces
|
|
|
|
```typescript
|
|
const { namespaces, pagination } = await supermemory.namespaces.list({ limit: 50 });
|
|
|
|
const ns = await supermemory.namespaces.get("user_123");
|
|
console.log(ns.supportingContext, namespaces[0]?.documentCount, pagination.totalPages);
|
|
|
|
await supermemory.namespaces.update("user_123", {
|
|
supportingContext: "A paying customer on the Pro plan",
|
|
});
|
|
|
|
await supermemory.namespaces.delete("user_123", { // optional, moves content instead of deleting it
|
|
moveTo: "archive",
|
|
});
|
|
```
|
|
|
|
## Organization
|
|
|
|
```typescript
|
|
const { organizationalContext, namespaceCount } = await supermemory.organization.get();
|
|
|
|
await supermemory.organization.update({
|
|
organizationalContext: "Acme sells billing software to dental clinics",
|
|
});
|
|
```
|
|
|
|
## Connectors
|
|
|
|
```typescript
|
|
const { id, authorization } = await supermemory.connectors.create("user_123", {
|
|
provider: "notion",
|
|
redirectUrl: "https://app.example.com/connected",
|
|
});
|
|
// send the user to authorization.url before authorization.expiresAt
|
|
|
|
const connectors = await supermemory.connectors.list("user_123");
|
|
const everyConnector = await supermemory.connectors.listAll();
|
|
|
|
const connector = await supermemory.connectors.get("user_123", id, {
|
|
include: ["syncs", "picker"],
|
|
});
|
|
console.log(connector.latestRun?.system.status, connector.documentCount);
|
|
|
|
await supermemory.connectors.update("user_123", id, {
|
|
documentLimit: 500,
|
|
});
|
|
|
|
await supermemory.connectors.sync("user_123", id);
|
|
|
|
await supermemory.connectors.delete("user_123", id, { deleteDocuments: true });
|
|
```
|
|
|
|
OAuth providers (`notion`, `google-drive`, `onedrive`, `gmail`, `github`) return an `authorization` link. Config providers start syncing right away and return `authorization: null`:
|
|
|
|
```typescript
|
|
await supermemory.connectors.create("user_123", {
|
|
provider: "web-crawler",
|
|
config: { startUrl: "https://docs.example.com", crawlDepth: 2 },
|
|
});
|
|
```
|
|
|
|
`sync` returns `{ id, status: "queued" }` and responds with 409 if a sync is already running.
|
|
|
|
### Error handling
|
|
|
|
Every HTTP error throws a `SupermemoryError` with `statusCode`, `body`, and `rawResponse`. Common statuses have their own subclasses, all exported from the package root: `BadRequestError` (400), `UnauthorizedError` (401), `PaymentRequiredError` (402), `ForbiddenError` (403), `NotFoundError` (404), `ConflictError` (409), `InternalServerError` (500), and `ServiceUnavailableError` (503). A timeout throws `SupermemoryTimeoutError`; a network failure is a `SupermemoryError` without a `statusCode`.
|
|
|
|
```typescript
|
|
import { Supermemory, NotFoundError, SupermemoryError } from "supermemory";
|
|
|
|
try {
|
|
await supermemory.documents.get("user_123", "missing");
|
|
} catch (error) {
|
|
if (error instanceof NotFoundError) {
|
|
console.log("gone");
|
|
} else if (error instanceof SupermemoryError) {
|
|
console.error(error.statusCode, error.body);
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Timeouts and retries
|
|
|
|
The client retries connection errors, 408, 429, and 5xx responses twice with backoff. Tune it on the client or per call; the per-call options object is always the optional last argument.
|
|
|
|
```typescript
|
|
const supermemory = new Supermemory({
|
|
apiKey: process.env.SUPERMEMORY_API_KEY,
|
|
timeoutInSeconds: 30, // default 60
|
|
maxRetries: 0, // default 2
|
|
});
|
|
|
|
await supermemory.search("user_123", { query: "planning notes" }, {
|
|
timeoutInSeconds: 5,
|
|
maxRetries: 3,
|
|
abortSignal: controller.signal,
|
|
});
|
|
```
|
|
|
|
</Tab>
|
|
|
|
<Tab title="Python">
|
|
## Install the Python SDK
|
|
|
|
```bash
|
|
pip install supermemory
|
|
```
|
|
|
|
## Start a Python client
|
|
|
|
```python
|
|
import os
|
|
from supermemory import Supermemory
|
|
|
|
client = Supermemory(
|
|
api_key=os.environ.get("SUPERMEMORY_API_KEY"), # Default, can be omitted
|
|
)
|
|
|
|
# Add a document
|
|
result = client.add(
|
|
"user_123",
|
|
content="Meeting notes from Q1 planning",
|
|
id="meeting-q1", # optional, your own id; the response echoes it
|
|
metadata={"category": "engineering", "priority": "high"},
|
|
dreaming="instant",
|
|
)
|
|
print(result.id, result.status)
|
|
|
|
# Search (hybrid by default: memories plus document chunks)
|
|
response = client.search("user_123", query="planning notes", limit=10)
|
|
for hit in response.results:
|
|
print(hit.memory or hit.chunk, hit.similarity)
|
|
|
|
# Get user profile
|
|
profile = client.profile("user_123").profile
|
|
print(profile.static)
|
|
print(profile.dynamic)
|
|
print(profile.buckets)
|
|
```
|
|
|
|
## Run common Python operations
|
|
|
|
```python
|
|
import json
|
|
|
|
# Search document chunks with a filter
|
|
results = client.search(
|
|
"user_123",
|
|
query="design document",
|
|
search_mode="chunks",
|
|
filter={"field": "category", "operator": "eq", "value": "engineering"},
|
|
)
|
|
|
|
# Profile buckets
|
|
client.profiles.set_buckets("user_123", buckets={"work": "Job, team, and current projects"})
|
|
buckets = client.profiles.get_buckets("user_123")
|
|
client.profiles.delete_buckets("user_123", buckets=["work"])
|
|
|
|
# List documents
|
|
page = client.list("user_123", "documents", page=1, limit=20, sort="createdAt", order="desc")
|
|
print(page.pagination.total_pages)
|
|
|
|
# Get, update, batch add, upload
|
|
doc = client.documents.get("user_123", "meeting-q1", include=["chunks", "memories"])
|
|
client.documents.update("user_123", "meeting-q1", metadata={"priority": "low"})
|
|
client.documents.batch_add(
|
|
"user_123",
|
|
documents=[{"content": "First note"}, {"content": "Second note"}],
|
|
)
|
|
with open("notes.pdf", "rb") as f:
|
|
client.documents.upload_file("user_123", file=f, metadata=json.dumps({"source": "upload"}))
|
|
|
|
# Delete documents
|
|
result = client.documents.delete("user_123", ids=["meeting-q1"])
|
|
|
|
# Forget memories: preview, then apply
|
|
preview = client.memories.forget_matching("user_123", query="old office address", dry_run=True)
|
|
client.memories.forget("user_123", ids=[m.id for m in preview.matches])
|
|
|
|
# Namespaces and organization
|
|
page = client.namespaces.list() # page.namespaces, page.pagination
|
|
ns = client.namespaces.get("user_123")
|
|
client.namespaces.update("user_123", supporting_context="A paying customer on the Pro plan")
|
|
client.namespaces.delete("user_123", move_to="archive") # optional, moves content instead of deleting it
|
|
client.organization.update(organizational_context="Acme sells billing software to dental clinics")
|
|
|
|
# Connectors
|
|
setup = client.connectors.create(
|
|
"user_123",
|
|
request={"provider": "notion", "redirectUrl": "https://app.example.com/connected"},
|
|
)
|
|
# send the user to setup.authorization.url before setup.authorization.expires_at
|
|
connector = client.connectors.get("user_123", setup.id, include=["syncs", "picker"])
|
|
client.connectors.sync("user_123", setup.id)
|
|
client.connectors.delete("user_123", setup.id, delete_documents=True)
|
|
```
|
|
|
|
## Handle Python SDK errors
|
|
|
|
Failed requests raise `supermemory.APIStatusError` (`.status_code`, `.body`) or a subclass such as `NotFoundError` or `RateLimitError`. Network failures raise `supermemory.APIConnectionError`. Set `max_retries=` and `timeout=` on the client, or per call. `AsyncSupermemory` has the same methods, awaited.
|
|
|
|
Requires Python 3.10+.
|
|
</Tab>
|
|
</Tabs>
|