--- title: "Ingest" sidebarTitle: "Ingest" description: "Add documents, files, batches, and conversations into the processing pipeline." icon: "download" --- Ingest is how content enters Supermemory. Every ingest call returns an id immediately; extraction, chunking, and embedding happen asynchronously in the background. ## Add a document `POST /v3/documents` Accepts plaintext, a URL, or structured content. The content type is detected from the URL's response format. ```bash cURL curl -X POST "https://api.supermemory.ai/v3/documents" \ --header "Authorization: Bearer $SUPERMEMORY_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "content": "This is a detailed article about machine learning concepts...", "containerTag": "user_123", "customId": "mem_abc123", "metadata": { "category": "technology" } }' ``` ```typescript Typescript const response = await fetch("https://api.supermemory.ai/v3/documents", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SUPERMEMORY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ content: "This is a detailed article about machine learning concepts...", containerTag: "user_123", customId: "mem_abc123", metadata: { category: "technology" }, }), }); ``` ```python Python import os, requests response = requests.post( "https://api.supermemory.ai/v3/documents", headers={ "Authorization": f"Bearer {os.environ['SUPERMEMORY_API_KEY']}", "Content-Type": "application/json", }, json={ "content": "This is a detailed article about machine learning concepts...", "containerTag": "user_123", "customId": "mem_abc123", "metadata": {"category": "technology"}, }, ) ``` ### Parameters | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `content` | string | one of | Plaintext, or a URL to a website, PDF, image, or video | | `containerTag` | string | no | Tag to containerize this memory by — a user id, project id, or any grouping identifier | | `customId` | string | no | Your own id for this memory; makes re-sends upsert instead of duplicate | | `metadata` | object | no | Flat key-value pairs (strings, numbers, booleans). Keys are case sensitive; nested objects are not supported | | `entityContext` | string | no | Context that guides how memories are extracted for this container (max 1500 chars) | `customId` is the idempotency handle. Use a stable value (conversation id, document id) so re-sending the same content updates the existing document rather than creating a second one. ### Response ```json { "id": "acxV5LHMEsG2hMSNb4umbn", "status": "queued" } ``` Poll [`GET /v3/documents/{id}`](/v5/api-reference/content-management#get-a-document) until `status` reaches `done` before relying on search or profiles. ## Upload a file `POST /v3/documents/file` Send binary content as `multipart/form-data`. Use this for local files that are not reachable by URL. ```bash curl -X POST "https://api.supermemory.ai/v3/documents/file" \ --header "Authorization: Bearer $SUPERMEMORY_API_KEY" \ --form "file=@./report.pdf" \ --form "containerTag=user_123" ``` The uploaded file can be read back later through the presigned URL on the document — see [Content management](/v5/api-reference/content-management#get-a-file-url). ## Batch ingest `POST /v3/documents/batch` Add many documents in one request. ```bash cURL curl -X POST "https://api.supermemory.ai/v3/documents/batch" \ --header "Authorization: Bearer $SUPERMEMORY_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "documents": [ { "content": "Batch doc 1" }, { "content": "Batch doc 2", "containerTags": ["user_123"] } ], "containerTag": "user_123" }' ``` ```typescript Typescript const response = await fetch("https://api.supermemory.ai/v3/documents/batch", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SUPERMEMORY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ documents: [ { content: "Batch doc 1" }, { content: "Batch doc 2", containerTags: ["user_123"] }, ], containerTag: "user_123", }), }); ``` ### Parameters | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `documents` | array | yes | 1–600 document objects | | `documents[].content` | string | yes | The document content or URL | | `documents[].containerTags` | string[] | no | Per-document tags for this document | | `documents[].metadata` | object | no | Per-document metadata | | `documents[].entityContext` | string | no | Per-document extraction context (max 1500 chars) | | `containerTag` | string | no | Default container for documents that do not set their own | | `metadata` | object | no | Default metadata for the batch | | `entityContext` | string | no | Default extraction context for the batch | ### Response Per-document results, so a partial failure does not fail the whole batch: ```json { "results": [ { "id": "doc_1", "status": "queued" }, { "id": "doc_2", "status": "failed", "error": "Unsupported content type" } ], "success": 1, "failed": 1 } ``` Check `failed` and the per-result `error` field. A batch request returns `200` even when individual documents fail. ## Add a conversation `POST /v4/conversations` Ingest a chat session as structured, turn-aware messages rather than a single text blob. The service diffs against the previous state of the same conversation and appends what is new. ```bash cURL curl -X POST "https://api.supermemory.ai/v4/conversations" \ --header "Authorization: Bearer $SUPERMEMORY_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "conversationId": "conv-123", "messages": [ { "role": "user", "content": "Hello!" }, { "role": "assistant", "content": "Hi there!" } ], "containerTags": ["user_123"] }' ``` ```typescript Typescript await fetch("https://api.supermemory.ai/v4/conversations", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SUPERMEMORY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ conversationId: "conv-123", messages: [ { role: "user", content: "Hello!" }, { role: "assistant", content: "Hi there!" }, ], containerTags: ["user_123"], }), }); ``` ### Parameters | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `conversationId` | string | yes | Stable id for the conversation; used for diffing across sends | | `messages` | array | yes | Structured turns | | `messages[].role` | string | yes | `user`, `assistant`, `system`, or `tool` | | `messages[].content` | string \| array | yes | Text, or an array of content parts for multi-modal turns | | `messages[].name` | string | no | Participant name | | `messages[].tool_calls` | array | no | Tool calls made in this turn | | `messages[].tool_call_id` | string | no | Id linking a tool result back to its call | | `containerTags` | string[] | no | Tags this conversation belongs to | | `metadata` | object | no | Metadata attached to the ingested conversation | Keep `conversationId` stable for the lifetime of a chat. Re-sending the growing transcript with the same id lets the service store only the new turns instead of duplicating the whole history. ## Next steps - [Content management](/v5/api-reference/content-management) — poll status and manage what you ingested - [Search](/v5/api-reference/search) — recall the indexed content - [Add memories](/ingestion/add-memories) — narrative ingest guide