Skip to main content
POST
When context is of type=knowledge:
  1. Documents: Use the documents field for binary uploads that HydraDB should parse: PDFs, Office and iWork files, spreadsheets, images and plain text. See Supported file formats for the full list.
  2. App Sources: Use app_knowledge for pre-extracted JSON content (Slack threads, Notion pages, emails, tickets). Read more about ingesting knowledge from your apps.
When context is of type=memory: Use memories for per-user content, scoped with collection. Set infer: true to let HydraDB extract preferences from raw signals, or infer: false to store the text verbatim. Read more about ingesting memories.

Upload in-memory text as a .txt file

If you already have text in memory, create a file-like object and upload it through documents as a text/plain .txt file.

Important form fields

  1. id must not contain a comma (,): The comma is reserved as the id separator on Ingestion Status (GET /context/status?ids=a,b), so an id containing a comma cannot be looked up unambiguously. This applies to every id you supply: document_metadata, app_knowledge, and memories items. Ingesting an item whose id contains a comma is rejected with a 400.
  2. 202 Accepted means queued, not indexed: Ingestion is asynchronous. A successful response only confirms your sources were accepted, not that they are ready to query. Before querying, poll GET /context/status with the returned IDs until each source reaches graph_creation (searchable), completed, or errored. Alternatively, register a webhook for indexing.status_changed events (see Webhooks).

Supported file formats

Anything in this table can be uploaded through documents and HydraDB will read it. What HydraDB extracts differs by type: A scanned page with nothing readable on it, or a photo that happens to contain no text, will index as an empty document rather than fail.

Formats we cannot read

These are rejected the moment you upload them, before anything is queued. You get the answer in the upload response rather than minutes later.
.heic is the format iPhones use for photos by default, so it is the one people hit most often without realizing. On iOS you can change this under Settings > Camera > Formats > Most Compatible, which makes the camera save JPEGs instead. Or export the photo as JPEG or PDF before uploading.

How we decide the format

The file extension is what counts. report.pdf is treated as a PDF because of the .pdf, not because of what is inside it. If the filename has no extension at all, the Content-Type you send with that part is used instead, so a file with no extension in its name, sent as application/pdf, is accepted.
Renaming a file does not convert it. A .heic photo renamed to photo.pdf passes this check, because the check reads the name, then fails later during parsing and comes back as errored on GET /context/status. Upload files under their real extension.

Size limit

Each file in documents can be up to 50 MB. A larger file is rejected with 413 and a message naming the file, and no part of the request is processed. Split large documents, or upload them separately.

When a file is not supported

A rejected file does not stop the rest of your upload. Each file is checked on its own, so a batch of ten with one bad file still indexes the other nine. The request returns 202 as usual. The rejected file comes back with status: "failed" and error_code: "E1002", and every other file is queued normally:
results, success_count and failed_count sit inside data, not at the top level, like every other v2 response. The outer success: true means the request was accepted; data.success is what tells you whether every file in it was queued.
Do not poll GET /context/status for a file rejected with E1002. The file never entered the pipeline, so it has no status record, and looking it up returns FILE_NOT_FOUND rather than the format error you were given. The upload response is the only place E1002 appears. Read error_code on each item in data.results and act on it there.

Common use-cases and their configurations

Document metadata

Per-document metadata (id, metadata, additional_metadata, relations, infer, evidence_kind, evidence_subject) can be passed alongside each uploaded document to control indexing, filtering, and display. The key list is closed: an item carrying any other key is rejected with a 400 naming it, rather than being silently dropped. See the field reference below.
Size limits are measured on the compact JSON of the whole object, in UTF-8 bytes, and apply the same way to app_knowledge and memories items.
Those seven, plus the legacy aliases source_id and file_id (for id) and document_metadata (for additional_metadata), are the only keys accepted. Anything else (including title, type, url and timestamp) is rejected with a 400 naming the unsupported key, rather than being silently dropped.In particular, a document’s title is derived, not settable. It defaults to the uploaded filename and is returned as source_title on query results and title on /context/list. It cannot be overridden at ingest, and PATCH /context/{id}/metadata only merges additional_metadata and database_metadata. Use additional_metadata for your own display fields, or ingest through app_knowledge, whose items carry an explicit title.
graph_payload is a map of source id to graph that replaces LLM graph extraction for each keyed source. For type=knowledge, the key is a document_metadata id or an app_knowledge item id; for type=memory, the key is a memory id. Keyed sources are still chunked and embedded, so they stay searchable. See Bring Your Own Graph for the full guide.
Caps per graph: at most 5,000 entities, 10,000 relations, and 500 relations per entity; over-cap returns 400. Graphs survive re-ingest: a re-upload or connector re-sync re-applies the stored graph.

Notes

  • Multipart, not JSON: This endpoint uses multipart/form-data. Stringify all JSON arrays (document_metadata, app_knowledge, memories) before placing them in the form field. A body that is neither a form nor JSON returns 415.
  • Declare hot schema fields upfront: put frequently filtered fields in metadata and declare them when you create the database; use additional_metadata for free-form fields. You can add fields later with Update Metadata Schema, but dense and sparse lanes can only be declared at creation.
  • Memory vs knowledge: Use type: "memory" for memory ingestion, listing, and deletion. Use type: "all" on POST /query when results should combine both. The multipart field name for memories is always memories.
  • Collection defaulting: Omitting collection writes to the default collection, created on first write. List available collections with List Collections.
Related Resources

Authorizations

Authorization
string
header
required

API key sent as a Bearer token: "Bearer prefix.secret"

Body

multipart/form-data

Content type: 'knowledge' or 'memory' | Database (canonical name for the tenant scope) | Collection (canonical name for the sub-tenant scope) | Deprecated alias for database | Deprecated alias for collection | Upsert existing content (true/false/1/0) | Knowledge files to ingest (repeatable; type=knowledge) | Per-document metadata as a JSON array (type=knowledge). Per item: metadata <= 16 KiB, additional_metadata <= 1 KiB. | App-knowledge items as a JSON array (type=knowledge). Per item: metadata <= 16 KiB, additional_metadata <= 1 KiB, optional acl principal list (PRO-1684). | Memory items as a JSON array (type=memory). Per item: metadata <= 16 KiB, additional_metadata <= 1 KiB. | Optional bring-your-own-graph payload as JSON

database
string
required
app_knowledge
string

JSON-stringified array of app sources (type=knowledge). Typed items use kind, provider, external_id, and fields. Metadata limits: 16 KiB metadata and 1 KiB additional_metadata. Optional acl restricts retrieval when the query supplies principals; an empty item ACL restricts it to nobody.

collection
string
document_metadata
string

JSON-stringified array, one item per uploaded file in the same order. Items accept id, metadata, additional_metadata, relations, infer, evidence_kind, and evidence_subject. Metadata limits: 16 KiB schema fields and 1 KiB free-form fields, measured as compact JSON in UTF-8 bytes.

documents
file
graph_payload
string
memories
string

JSON-stringified array of memory items (type=memory). Each item has text or user_assistant_pairs, and optional infer (default false), id, user_name, metadata, and additional_metadata. Nested metadata values are objects, not JSON strings. Limits: 16 KiB metadata and 1 KiB additional_metadata.

sub_tenant_id
string
deprecated
tenant_id
string
deprecated
type
enum<string>
default:knowledge
Available options:
knowledge,
memory
upsert
string
default:true

Response

Accepted

data
object
Example:
error
object | null

Null on success; an object with code and message on failure.

Example:

null

meta
object
Example:
success
boolean

Whether the request succeeded.

Example:

true