Skip to content
Beta. This surface may change before GA; breaking changes are dated in the changelog.

Sources

A source is one producer’s stream of documents: one customer’s content, one repository’s docs folder, one CRM export. You send a source its documents as snapshots — the whole current set, or an explicitly partial one — and the Brain compares each snapshot with what the source said before and what the Brain has accepted, before anything is served.

Use a source when the content you send has an owner that revises it as a set. Keep using POST /documents when you only ever add or rewrite documents one at a time.

A source is the key that sends it plus a name you choose. The name is part of the URL; the key comes from the credential:

Terminal window
curl -X POST "$API/v1/brains/tenant:acme/sources/acme-content/snapshots" \
-H "authorization: Bearer $NICIA_KEY" \
-H "idempotency-key: acme-content-2026-09-23"

A name is lowercase letters, digits and hyphens, starts with a letter or digit, and is at most 64 characters. Three things follow from the key being part of the identity:

  • Nobody can report as your source. Another key naming acme-content is a different source, with its own documents.
  • Rotating a key keeps its source. A rotated key is the same key with a new secret.
  • Only the owning key touches a snapshot. Adding to, sealing, reading, applying and cancelling a snapshot are for the key that opened it; any other key gets 404.

A document belongs to exactly one source, addressed by the source and the id you gave it there. The same text sent under two sources is two documents, and retiring a document from one source never touches the other.

Any key with read can list every source in the Brain, whoever owns it, with each one’s newest snapshot. It answers names, owners and counts — no content:

Terminal window
curl "$API/v1/brains/tenant:acme/sources" \
-H "authorization: Bearer $NICIA_KEY"
{
"data": {
"sources": [
{
"name": "acme-content",
"owner": { "keyId": "key_7f3a1c" },
"latestSnapshot": {
"id": "01a0cdbb-66e1-75be-a056-c758c4b3ee4c",
"source": "acme-content",
"status": "applied",
"completeness": "complete",
"documents": 2,
"bytes": 58,
"openedAt": "2026-09-23T10:06:45.984Z",
"sealedAt": "2026-09-23T10:06:46.025Z",
"plannedAt": "2026-09-23T10:06:46.068Z",
"closedAt": "2026-09-23T10:07:12.310Z",
"expiresAt": "2026-09-30T10:06:46.068Z",
"appliedPlanRevision": 1,
"appliedAt": "2026-09-23T10:06:46.099Z"
}
}
]
}
}

GET /v1/brains/{handle}/sources/{name} reads one: your key’s source with that name. A source exists once a snapshot has been opened for it.

A receipt names a document of a source by the source and your id for it: the item carries document: { "source": "acme-content", "id": "pricing" } and uses pricing as its source.

/context citations and /search results do not do that yet. They name a source’s document by the Brain’s own id for it — a source-document:… string — which GET /v1/brains/{handle}/documents/{documentId} accepts, and which the document listing uses too.

POST /documents is unchanged, and it is not a source. A document written there is served at once, is never compared with anything, and is never retired because a later write left it out. Documents you send through a source and documents you send through POST /documents are separate: sending the same id both ways makes two documents.

  • Snapshots — sending a source its documents.
  • Receipts — what a read was served, and the text it pinned.