Save an original#
POST /messages · requires a stable Idempotency-Key.
{
"external_id": "message-1",
"thread_id": "customer-17",
"author_id": null,
"role": "human",
"occurred_at": null,
"text": "Please call after 6 pm.",
"expected_version_id": null
}IDs use 1–128 ASCII letters, digits or ._:-. Roles are literal human, assistant, tool or system. An unknown author or event clock is explicit null. A supplied event clock must have a time-zone offset. Text is complete, nonempty UTF-8, up to 4,096 bytes; it is never silently clipped.
A new message has expected_version_id: null. A correction uses the same external_id, the complete new message and its current expected_version_id, with a new stable idempotency key. Currentness conflicts refuse the write. The receipt identifies the saved record and version, request and payload hashes, outcome and custody status.
Recall a thread#
POST /recall · read-only; no idempotency header required.
{"thread_id":"customer-17","limit":20,"max_context_bytes":24000}limit defaults to 20 and accepts 1–60. max_context_bytes defaults to 24,000 and accepts 512–32,000. Extra fields are refused. Selection uses the exact literal thread ID under current producer authority.
| Response field | Meaning |
|---|---|
context_status | prepared: at least one complete message fits; empty: no eligible current messages; budget_limited: messages exist but none fits. |
prepared | Rendered unit, selected exact originals and source spans; otherwise null. |
selected_count, has_more | How many messages were prepared and whether selection omitted eligible evidence. |
omission_reasons | message_limit and/or context_byte_budget. Whole messages are omitted; bodies are never clipped. |
context_bytes | UTF-8 size of rendered text including evidence headers and separators. Not tokens or the whole response size. |
selection_order | latest_saved: ingestion time then immutable version ID descending. This does not establish event chronology. |
| Publication | publication_status: held, semantic_ready: false, accepted_memory: false, conversation_complete: null. |
Spans carry codepoint and UTF-8 offsets into exact original text and the rendered context, plus immutable version and content hashes. Fetch a current original with GET /versions/{version_id}; changed, withdrawn, unavailable or unauthorized evidence is refused.
Withdraw a message#
POST /withdrawals · requires a stable Idempotency-Key.
{"external_id":"message-1","expected_version_id":"CURRENT-VERSION-UUID"}The expected version must be current. A successful receipt has outcome: deleted. Subsequent recall excludes that source message. Earlier custody versions remain immutable; this route is not a privacy-erasure API and does not authorize restoring a withdrawn record.
Additional private reads#
GET /receipts/{receipt_id}— inspect a saved producer receipt.POST /contextwith{"version_ids":["CURRENT-VERSION-UUID"]}— prepare an explicit ordered selection of 1–60 distinct current versions from one thread.GET /catalog— inspect the bounded literal metadata schema.POST /query— run the existing typed metadata plan over an explicit current version selection. This is not SQL or semantic search. Start with{"version_ids":["CURRENT-VERSION-UUID"],"plan":{}}and inspect the catalog before choosing predicates.
Errors and retries#
Errors use type, code, message and request_id. Retain the request ID in private support logs; do not log authorization headers or source bodies.
| Status | Typical next step |
|---|---|
| 400 / 413 / 415 | Check the closed request, size and JSON content type. |
| 401 / 403 | Check the credential, its scope, Brain ID and connection ID. Contact Brain if access has expired. |
| 404 | The requested current evidence is unavailable; do not substitute an old snapshot. |
| 409 | Inspect the code: stale revision, changed thread membership or idempotency/integrity conflict. Preserve the refused request for diagnosis. |
| 429 | Respect Retry-After. A write still requires explicit outcome handling and the original idempotency identity. |
| 503 / timeout / malformed response | Stop the dependent flow. A post-dispatch write may have committed; inspect its outcome or explicitly replay the identical request with the same key. |
No SDK write retries automatically. Reusing a key with a different payload is a conflict. See SDK replay behavior and availability limits.