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

Statements

A statement records what one connected source reported about a subject. The authenticated key supplies source identity; the request cannot impersonate another source. sourceKey is optional and identifies a stable row or field inside that source. Writing a statement does not promote it to curated Brain truth. Use POST /v1/brains/{handle}/statements to report one.

Terminal window
curl -X POST "$API/v1/brains/tenant:acme/statements" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: stmt-salesforce-arr" \
-d '{
"subject": "acme",
"predicate": "contract_value_usd",
"value": 120000,
"sourceKey": "salesforce-renewal"
}'
{
"data": {
"statementIds": ["stmt_91ab01"],
"outcome": {
"kind": "admitted",
"batchId": "batch_44a1e0",
"policyVersionId": "pol_nicia_open",
"acceptedSnapshot": "snap_6f1e4d6b",
"changeIds": ["brn_9c2a1f:12:0:0"]
},
"statements": [
{
"id": "stmt_91ab01",
"subject": "acme",
"predicate": "contract_value_usd",
"value": 120000,
"validFrom": "2026-08-14T09:20:00.000Z",
"sourceKey": "salesforce-renewal",
"assertedBy": { "kind": "service", "id": "key_7f3a1c" },
"status": "active"
}
]
}
}

The returned source is the server-bound producer identity. Credential rotation preserves it. assertedBy is projected from the accepted change; callers cannot set either field.

A statement without sourceKey is valid when the producer has no durable row key:

Terminal window
curl -X POST "$API/v1/brains/tenant:acme/statements" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: stmt-handbook-pto" \
-d '{
"subject": "acme",
"predicate": "pto_starts_on",
"value": "day-one",
}'

A statement can cite the document it was read from, exactly as a record write does: evidence names a document the Brain holds, a quote that must occur in its current version, and your own locator. The citation grounds the statement only, not the subject it is about. Add an anchor (§ <heading> or L12-L14) to rest the statement on a part of the document; the Brain resolves it, and a standing answer that depends on the statement is then monitored.

{
"subject": "sunfield",
"predicate": "migratory_route",
"value": "Pacific Flyway",
"evidence": [
{
"document": { "id": "environmental-report" },
"quote": "within the Pacific Flyway",
"locator": { "page": 14 }
}
]
}

A later report for the same source stream supersedes. Another stream or source disagreeing over an overlapping window does not: both statements stay, and the next /context names it. You do not call GET /findings to find out. That list is the operator inbox.

Terminal window
curl -X POST "$API/v1/brains/tenant:acme/statements" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: stmt-netsuite-arr" \
-d '{
"subject": "acme",
"predicate": "contract_value_usd",
"value": 145000,
"sourceKey": "netsuite-renewal"
}'
Terminal window
curl -X POST "$API/v1/brains/tenant:acme/context" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-d '{
"prompt": "What is the Acme contract value?",
"maxTokens": 2000,
"format": "items"
}'
{
"data": {
"text": "",
"citations": [],
"items": [
{
"kind": "record",
"id": "stmt-salesforce-arr",
"fields": { "contract_value_usd": 120000 },
"status": "contested"
},
{
"kind": "record",
"id": "stmt-netsuite-arr",
"fields": { "contract_value_usd": 145000 },
"status": "contested"
}
],
"staged": 0,
"warnings": [
{
"kind": "contested",
"subject": "acme",
"predicate": "contract_value_usd",
"count": 2,
"detail": "Two sources disagree about acme.contract_value_usd."
}
],
"receipt": "rcp_contested",
"truncated": false
}
}

warnings[] kind contested names the subject and predicate. Per-item status: "contested" marks the statements in this answer. There is no conflicts[] field on /context.

GET /findings is the inbox. POST /v1/brains/{handle}/findings/{findingId}/decide keeps one statement or writes a corrected value. The loser is retained, not deleted. The call needs review and an Idempotency-Key.

Terminal window
curl "$API/v1/brains/tenant:acme/findings?resolved=false" \
-H "authorization: Bearer $NICIA_KEY"
{
"data": {
"findings": [
{
"id": "fnd_91ab",
"subject": "acme",
"predicate": "contract_value_usd",
"statements": [
{
"id": "stmt_91ab01",
"subject": "acme",
"predicate": "contract_value_usd",
"value": 120000,
"validFrom": "2026-08-14T09:20:00.000Z",
"sourceKey": "salesforce-renewal",
"assertedBy": { "kind": "service", "id": "key_7f3a1c" },
"status": "conflicted"
},
{
"id": "stmt_91ab02",
"subject": "acme",
"predicate": "contract_value_usd",
"value": 145000,
"validFrom": "2026-08-14T09:21:00.000Z",
"sourceKey": "netsuite-renewal",
"assertedBy": { "kind": "service", "id": "key_7f3a1c" },
"status": "conflicted"
}
],
"detectedAt": "2026-08-14T09:21:01.000Z",
"classification": "contradiction",
"coverage": "complete",
"reasons": ["declared-single-value-conflict"],
"supportFingerprint": "sha256:finding-support",
"analysisAsOf": "2026-08-14T09:21:01.000Z"
}
],
"receipt": "rcp_findings"
}
}
Terminal window
curl -X POST "$API/v1/brains/tenant:acme/findings/fnd_91ab/decide" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: resolve-acme-arr" \
-d '{ "keep": "stmt_91ab02", "reviewedReceipt": "rcp_findings", "reviewedFingerprint": "sha256:finding-support" }'
{
"data": {
"outcome": {
"kind": "admitted",
"batchId": "batch_91ab03",
"policyVersionId": "pol_nicia_open",
"acceptedSnapshot": "snap_91ab03",
"changeIds": ["brn_9c2a1f:15:0:0"]
}
}
}

Or send "value": 145000 instead of keep to supersede both with a corrected number.

  • Context — how a contested fact shows up on the read.
  • Receipts — reconstructing a served read, and whether it is stale.
  • Review — Open vs Reviewed, and settling the queue.
  • Records — the subjects and sources statements point at.