Skip to content

Ingest documents at scale

Load documents, or structured items and edges, into institutional memory with POST /api/v1/institutional/ingest/batch.

  • An Enterprise install. On Core the endpoint returns 403 enterprise_required.
  • The URL of the workspace’s memory-api, exported here as MEMORY_API.
  • A ServiceAccount bearer token in an Authorization: Bearer header when internalServiceAuth.enabled is set. See Memory API.
  • A workspace_id in each request body (the workspace name or UID) when the memory-api has not resolved its own Workspace UID. Otherwise omit it.
  1. Post up to 100 documents under one source name. Each document needs a url, which is the key of its node and chunks.

    Terminal window
    curl -fsS -X POST "$MEMORY_API/api/v1/institutional/ingest/batch" \
    -H 'Content-Type: application/json' \
    -d '{
    "source": "handbook",
    "documents": [{
    "title": "Returns policy",
    "url": "https://docs.example.com/returns",
    "site": "operations",
    "text": "# Return window\nCustomers may return unused items within 30 days.\n\n# Exclusions\nPersonalised items are excluded.",
    "author": "Operations",
    "modified_at": "2026-09-01T00:00:00Z",
    "content_hash": "sha256:replace-with-source-hash"
    }]
    }'
  2. Read the 202 response. It carries accepted, skipped, forgotten, rejected and embedding_backlog. A document or item that fails lands in rejected with its reason, and the rest of the batch still lands.

  3. Choose how the body is split. Send sections[] on a document when the source already knows its headings. Otherwise send text, and memory-api splits it on Markdown headings. Chunks are cut within sections using the ingestion strategy from the workspace’s MemoryPolicy. See MemoryPolicy ingestion.

Send items[] and edges[] instead of documents[] for code indexers and other sources that already know their structure. A request carries at most 5000 items.

{
"source": "repo-main",
"items": [{
"about": {"kind": "function", "key": "pkg.Save"},
"kind": "function",
"name": "Save",
"content": "Writes a memory.",
"metadata": {"path": "memory/store.go"}
}],
"edges": [{
"from": {"kind": "file", "key": "memory/store.go"},
"to": {"kind": "function", "key": "pkg.Save"},
"type": "defines"
}]
}

Items upsert by about. Edges resolve both endpoints by the same references, from this request first and then from items already stored. An edge whose endpoint is unknown is rejected without failing the batch.

  1. Set a content_hash on each document. A re-ingest with the same hash, source and chunking settings is skipped. Items are always written.

  2. Re-ingest a shortened document to remove the surplus chunks.

  3. Add a present manifest to forget items of one kind that left the source:

    "present": {"kind": "document", "keys": ["https://docs.example.com/returns"]}

    Entries of that kind from the same source whose key is not listed are forgotten, along with the chunks of forgotten documents.

  4. Remove everything one source wrote:

    Terminal window
    curl -fsS -X DELETE "$MEMORY_API/api/v1/institutional/sources/handbook"

    This soft-deletes every institutional entity whose source is handbook and returns the count as forgotten.

List the documents a source wrote:

Terminal window
curl -fsS "$MEMORY_API/api/v1/institutional/documents?source=handbook"

Each document reports chunk_count, section_count and embedded_count. Ingest does not wait for vectors, so embedded_count trails chunk_count until the backlog drains. Follow Operate memory embeddings to drain it.

The response body enterprise_required means the install is Core. A body saying the workspace “is not this memory-api’s workspace” means the workspace_id or workspace names another workspace: send this memory-api’s workspace name or UID, or omit it. Any other 403 comes from service authentication: send a valid ServiceAccount bearer token.

Check the error text. The causes are a missing source, more than 100 documents or 5000 items, or a missing workspace_id where one is required.

A document with no url is rejected under its title. Fix the field and resend that document.