1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
---
title: "Ingesting context to supermemory"
sidebarTitle: "Add context"
description: "Add text, files, and URLs to Supermemory"
icon: "plus"
---
Send any raw content to Supermemory — conversations, documents, files, URLs. We extract the memories automatically.
<Tip>
**Use `customId`** to identify your content (conversation ID, document ID, etc.). This enables updates and prevents duplicates.
</Tip>
## Quick Start
<Tabs>
<Tab title="TypeScript">
```typescript
import Supermemory from 'supermemory';
const client = new Supermemory();
// Add text content
await client.add({
content: "Machine learning enables computers to learn from data",
containerTag: "user_123",
metadata: { category: "ai" }
});
// Add a URL (auto-extracted)
await client.add({
content: "https://youtube.com/watch?v=dQw4w9WgXcQ",
containerTag: "user_123"
});
```
</Tab>
<Tab title="Python">
```python
from supermemory import Supermemory
client = Supermemory()
# Add text content
client.add(
content="Machine learning enables computers to learn from data",
container_tag="user_123",
metadata={"category": "ai"}
)
# Add a URL (auto-extracted)
client.add(
content="https://youtube.com/watch?v=dQw4w9WgXcQ",
container_tag="user_123"
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Machine learning enables computers to learn from data",
"containerTag": "user_123",
"metadata": {"category": "ai"}
}'
```
</Tab>
</Tabs>
**Response:**
```json
{ "id": "abc123", "status": "queued" }
```
---
## Updating Content
Use `customId` to update existing documents or conversations. When you send content with the same `customId`, Supermemory intelligently processes only what's new.
### Two ways to update:
**Option 1: Send only the new content**
```typescript
// First request
await client.add({
content: "user: Hi, I'm Sarah.\nassistant: Nice to meet you!",
customId: "conv_123",
containerTag: "user_sarah"
});
// Later: send only new messages
await client.add({
content: "user: What's the weather?\nassistant: It's sunny today.",
customId: "conv_123", // Same ID — Supermemory links them
containerTag: "user_sarah"
});
```
**Option 2: Send the full updated content**
```typescript
// Supermemory detects the diff and only processes new parts
await client.add({
content: "user: Hi, I'm Sarah.\nassistant: Nice to meet you!\nuser: What's the weather?\nassistant: It's sunny today.",
customId: "conv_123",
containerTag: "user_sarah"
});
```
Both work — choose what fits your architecture.
### Replace entire document
To completely replace a document's content (not append), use `memories.update()`:
```typescript
// Replace the entire document content
await client.documents.update("doc_id_123", {
content: "Completely new content replacing everything",
metadata: { version: 2 }
});
```
This triggers full reprocessing of the document.
### Formatting conversations
Format your conversations however you want. Supermemory handles any string format:
```typescript
// Simple string
content: "user: Hello\nassistant: Hi there!"
// JSON stringify
content: JSON.stringify(messages)
// Template literal
content: messages.map(m => `${m.role}: ${m.content}`).join('\n')
// Any format — just make it a string
content: formatConversation(messages)
```
---
## Upload Files
Upload PDFs, images, and documents directly.
<Tabs>
<Tab title="TypeScript">
```typescript
import fs from 'fs';
await client.documents.uploadFile({
file: fs.createReadStream('document.pdf'),
containerTags: 'user_123'
});
```
</Tab>
<Tab title="Python">
```python
with open('document.pdf', 'rb') as file:
client.documents.upload_file(
file=file,
container_tags='user_123'
)
```
</Tab>
<Tab title="cURL">
```bash
curl -X POST "https://api.supermemory.ai/v3/documents/file" \
-H "Authorization: Bearer $SUPERMEMORY_API_KEY" \
-F "[email protected]" \
-F "containerTags=user_123"
```
</Tab>
</Tabs>
### Supported File Types
| Type | Formats | Processing |
|------|---------|------------|
| Documents | PDF, DOC, DOCX, TXT, MD | Text extraction, OCR for scans |
| Images | JPG, PNG, GIF, WebP | OCR text extraction |
| Spreadsheets | CSV, Google Sheets | Structured data extraction |
| Videos | YouTube URLs, MP4 | Auto-transcription |
**Limits:** 50MB max file size
---
## Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| `content` | string | **Required.** Any raw content — text, conversations, URLs, HTML |
| `customId` | string | **Recommended.** Your ID for the content (conversation ID, doc ID). Enables updates and deduplication |
| `containerTag` | string | Group by user/project. Required for user profiles |
| `metadata` | object | Key-value pairs for filtering (strings, numbers, booleans) |
<AccordionGroup>
<Accordion title="Parameter Details & Examples">
**Content Types:**
```typescript
// Any text — conversations, notes, documents
{ content: "Meeting notes from today's standup" }
{ content: JSON.stringify(messages) }
// URLs (auto-detected and extracted)
{ content: "https://example.com/article" }
{ content: "https://youtube.com/watch?v=abc123" }
// Markdown, HTML, or any format
{ content: "# Project Docs\n\n## Features\n- Real-time sync" }
```
**Container Tags:**
```typescript
// By user
{ containerTag: "user_123" }
// By project
{ containerTag: "project_alpha" }
// Hierarchical
{ containerTag: "org_456_team_backend" }
```
**Custom IDs (Recommended):**
```typescript
// Use IDs from your system
{ customId: "conv_abc123" } // Conversation ID
{ customId: "doc_456" } // Document ID
{ customId: "thread_789" } // Thread ID
{ customId: "meeting_2024_01_15" } // Meeting ID
// Updates: same customId = same document
// Supermemory only processes new/changed content
await client.add({
content: "Updated content...",
customId: "doc_456" // Links to existing document
});
```
**Metadata:**
```typescript
{
metadata: {
source: "slack",
author: "john",
priority: 1,
reviewed: true
}
}
```
- No nested objects or arrays
- Values: string, number, or boolean only
</Accordion>
</AccordionGroup>
---
## Processing Pipeline
When you add content, Supermemory:
1. **Validates** your request
2. **Stores** the document and queues for processing
3. **Extracts** content (OCR, transcription, web scraping)
4. **Chunks** into searchable memories
5. **Embeds** for vector search
6. **Indexes** for retrieval
Track progress with `GET /v3/documents/{id}`:
```typescript
const doc = await client.documents.get("abc123");
console.log(doc.status); // "queued" | "processing" | "done"
```
<AccordionGroup>
<Accordion title="Batch Upload">
Process multiple documents with rate limiting:
```typescript
async function batchUpload(documents: Array<{id: string, content: string}>) {
const results = [];
for (const doc of documents) {
try {
const result = await client.add({
content: doc.content,
customId: doc.id,
containerTag: "batch_import"
});
results.push({ id: doc.id, success: true, docId: result.id });
} catch (error) {
results.push({ id: doc.id, success: false, error });
}
// Rate limit: 1 second between requests
await new Promise(r => setTimeout(r, 1000));
}
return results;
}
```
**Tips:**
- Batch size: 3-5 documents at once
- Delay: 1-2 seconds between requests
- Use `customId` to track and deduplicate
</Accordion>
<Accordion title="Error Handling">
| Status | Error | Cause |
|--------|-------|-------|
| 400 | BadRequestError | Missing required fields, invalid parameters |
| 401 | AuthenticationError | Invalid or missing API key |
| 403 | PermissionDeniedError | Insufficient permissions |
| 429 | RateLimitError | Too many requests or quota exceeded |
| 500 | InternalServerError | Processing failure |
```typescript
import { BadRequestError, RateLimitError } from 'supermemory';
try {
await client.add({ content: "..." });
} catch (error) {
if (error instanceof RateLimitError) {
// Wait and retry
await new Promise(r => setTimeout(r, 60000));
} else if (error instanceof BadRequestError) {
// Fix request parameters
console.error("Invalid request:", error.message);
}
}
```
</Accordion>
<Accordion title="Delete Content">
**Single delete:**
```typescript
await client.documents.delete("doc_id_123");
```
**Bulk delete by IDs:**
```typescript
await client.documents.deleteBulk({
ids: ["doc_1", "doc_2", "doc_3"]
});
```
**Bulk delete by container tag:**
```typescript
// Delete all content for a user
await client.documents.deleteBulk({
containerTags: ["user_123"]
});
```
Deletes are permanent — no recovery.
</Accordion>
</AccordionGroup>
---
## Next Steps
- [Search Memories](/search) — Query your content
- [User Profiles](/user-profiles) — Get user context
- [Organizing & Filtering](/concepts/filtering) — Container tags and metadata
|