REST (generated)
Every path in the engine's public OpenAPI (client routes), regenerated at docs build. Do not edit.
Source: https://valorbrain-api.valor.digital/openapi.json (public client routes, generated from routes[]). Public base: https://valorbrain-api.valor.digital.
The engine publishes its client routes; admin and operations routes are not part of the public contract.
37 operations across 9 tags.
Agents
POST /api/v1/agents/signup
Register a new agent (public) — Public endpoint — no auth required. Creates a shadow tenant and returns an API key.
- Auth: none
- Body: object(
agent_caller* (string),user_agent(string) ) - operationId:
agentSignup
post:
operationId: agentSignup
summary: Register a new agent (public)
description: 'Public endpoint — no auth required. Creates a shadow tenant and returns
an API key.
'
tags:
- Agents
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- agent_caller
properties:
agent_caller:
type: string
maxLength: 100
user_agent:
type: string
responses:
'200':
description: Agent registered with API key
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
tenant_id:
type: string
api_key:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'501':
description: Postgres backend requiredPOST /api/v1/agents/mcp-token
Reissue the signup MCP token with the agent key — Authenticated by the workspace's own vb_agent_ key only (any other credential gets 401 agent_key_required). Mints a new vbm_ with the signup ceiling — scopes read write, toolset agent, the key's own expiry — and revokes the previous signup MCP token in the same transaction. Rate-limited per tenant (3 per minute by default).
- Auth: none
- operationId:
agentMcpTokenReissue
post:
operationId: agentMcpTokenReissue
summary: Reissue the signup MCP token with the agent key
description: 'Authenticated by the workspace''s own `vb_agent_` key only (any other
credential gets 401 `agent_key_required`). Mints a new `vbm_` with the signup
ceiling — scopes `read write`, toolset `agent`, the key''s own expiry — and revokes
the previous signup MCP token in the same transaction. Rate-limited per tenant
(3 per minute by default).
'
tags:
- Agents
security: []
responses:
'201':
description: New MCP token (raw value shown once)
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
tenant_id:
type: string
mcp_token:
type: string
scopes:
type: array
items:
type: string
toolset:
type: string
expires_at:
type: string
nullable: true
revoked_previous:
type: integer
'401':
description: Not the workspace's `vb_agent_` key (`agent_key_required`), or
an invalid key
'429':
description: Too many reissues for this workspacePOST /api/v1/agents/identify
Identify an agent by API key — Requires a Bearer API key (401 when absent).
- Auth: none
- Body: object(
agent_caller* (string) ) - operationId:
agentIdentify
post:
operationId: agentIdentify
summary: Identify an agent by API key
description: Requires a Bearer API key (401 when absent).
tags:
- Agents
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- agent_caller
properties:
agent_caller:
type: string
responses:
'200':
description: Agent identity
content:
application/json:
schema:
type: object
properties:
agent_name:
type: string
tenant_id:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'POST /api/v1/agents/claim
Request ownership claim for an agent — Requires a Bearer API key (401 when absent).
- Auth: none
- Body: object(
email* (string) ) - operationId:
agentClaim
post:
operationId: agentClaim
summary: Request ownership claim for an agent
description: Requires a Bearer API key (401 when absent).
tags:
- Agents
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
responses:
'200':
description: Claim request initiated
content:
application/json:
schema:
type: object
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'POST /api/v1/agents/claim/verify
Verify an agent ownership claim — Requires a Bearer API key (401 when absent). The SaaS calls it instead with the internal secret and the claim_token from the signup's claim_url. On success the workspace is named for its human and keeps its plan (it changes only when the operator sets VALORBRAIN_AGENT_PLAN_AFTER_CLAIM); login_url is where the human creates the app login (or adds the workspace to the account that e-mail already has).
- Auth: none
- Body: object(
email* (string),otp* (string) ) - operationId:
agentClaimVerify
post:
operationId: agentClaimVerify
summary: Verify an agent ownership claim
description: Requires a Bearer API key (401 when absent). The SaaS calls it instead
with the internal secret and the `claim_token` from the signup's `claim_url`.
On success the workspace is named for its human and keeps its plan (it changes
only when the operator sets `VALORBRAIN_AGENT_PLAN_AFTER_CLAIM`); `login_url`
is where the human creates the app login (or adds the workspace to the account
that e-mail already has).
tags:
- Agents
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- otp
properties:
email:
type: string
format: email
otp:
type: string
responses:
'200':
description: Claim verified
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
tenant_id:
type: string
email:
type: string
tenant_name:
type: string
login_url:
type: string
nullable: true
description: Null on an engine without a SaaS configured.
message:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'Discovery
GET /.well-known/valorbrain-credentials.json
Canonical credential matrix — Every credential the platform accepts — prefix, issuer, surfaces that accept and refuse it, identity, lifecycle and rate limits. Generated from src/credential-matrix.ts; sha256 changes whenever the matrix does.
- Auth: none
- operationId:
credentialMatrix
get:
operationId: credentialMatrix
summary: Canonical credential matrix
description: 'Every credential the platform accepts — prefix, issuer, surfaces that
accept and refuse it, identity, lifecycle and rate limits. Generated from src/credential-matrix.ts;
`sha256` changes whenever the matrix does.
'
tags:
- Discovery
security: []
responses:
'200':
description: The matrix
content:
application/json:
schema:
type: object
required:
- version
- sha256
- credentials
properties:
version:
type: integer
sha256:
type: string
credentials:
type: array
items:
type: objectDocuments
POST /documents
Ingest a document — Create or update a document in a collection. Supports quality gate evaluation, schema packs, auto-linking, and temporal metadata. The tenant comes from the credential (X-Tenant-ID only with the platform token). New content on a path whose document was forgotten (forget, memory_forget) is a new document — 201, action "created", revived: true, new id, the writer's, nothing inherited; the forgotten row stays forgotten under <path>#forgotten-<id>-<random> (FB-0217). Two writes bringing the same forgotten path back at once: one creates, the other gets a 409 and writes nothing. #forgotten- is reserved for those rows: a path carrying it is a 400. The same content after the forget answers "unchanged" with active: false and archived_reason. A document archived for another reason stays archived. created, updated and unchanged answers carry active, plus archived_reason when the document is out of reach.
- Auth: bearer
- Params:
None - Body: object(
collection* (string),path* (string),title(string),content* (string),content_type(string),confidence(number),quality_score(number),metadata(object( )),user_id(string),run_id(string),event_at(string),event_type(string) ) - operationId:
ingestDocument
post:
operationId: ingestDocument
summary: Ingest a document
description: 'Create or update a document in a collection. Supports quality gate
evaluation, schema packs, auto-linking, and temporal metadata. The tenant comes
from the credential (X-Tenant-ID only with the platform token). New content on
a path whose document was forgotten (forget, memory_forget) is a new document
— 201, action "created", `revived: true`, new id, the writer''s, nothing inherited;
the forgotten row stays forgotten under `<path>#forgotten-<id>-<random>` (FB-0217).
Two writes bringing the same forgotten path back at once: one creates, the other
gets a 409 and writes nothing. `#forgotten-` is reserved for those rows: a path
carrying it is a 400. The same content after the forget answers "unchanged" with
`active: false` and `archived_reason`. A document archived for another reason
stays archived. created, updated and unchanged answers carry `active`, plus `archived_reason`
when the document is out of reach.
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- collection
- path
- content
properties:
collection:
type: string
description: Collection name
path:
type: string
description: Unique document path within the collection
title:
type: string
content:
type: string
maxLength: 1000000
description: Document body (max 1MB)
content_type:
type: string
default: note
confidence:
type: number
minimum: 0
maximum: 1
default: 0.5
quality_score:
type: number
minimum: 0
maximum: 1
default: 0.5
metadata:
type: object
additionalProperties: true
description: 'Free-form; stored in source_metadata. The keys the server
owns are dropped (FB-0233): revisions, ingest_via, ingest_at, author_unverified,
claimed_user_id, claimed_user_id_reason, author_kind, author_credential,
inferred_event_at.'
user_id:
type: string
run_id:
type: string
event_at:
type: string
format: date-time
event_type:
type: string
responses:
'200':
description: 'Document updated, or nothing written: "unchanged" (same content
at the same path), "skipped" (update_strategy no-update) or "deduplicated"
(same content in another collection, in a copy the writer may read, its own
or with no owner, at least as visible as the write and under the same source
ACL domain)
'
content:
application/json:
schema:
$ref: '#/components/schemas/IngestResult'
'201':
description: Document created (action "created")
content:
application/json:
schema:
$ref: '#/components/schemas/IngestResult'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: '`not_document_owner` (another member''s private document, or a
sensitivity change of an owned one) or `sensitivity_change_requires_admin`
'
'404':
description: The path holds a document the writer may not read; nothing is written
'409':
description: '`code: "concurrent_write"` — another write brought the same forgotten
path back while this one was in flight; nothing was written. Send it again:
it is judged against the document now at the path (FB-0217).
'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'GET /documents
Multi-get documents by glob pattern — Fetch multiple documents at once by path glob. The pattern query parameter is mandatory; max_bytes bounds the total body payload and collection narrows the glob to one collection. The same blocked-collection predicate applied to search applies here.
- Auth: bearer
- Params:
None,pattern*,collection,max_bytes - operationId:
listDocuments
get:
operationId: listDocuments
summary: Multi-get documents by glob pattern
description: 'Fetch multiple documents at once by path glob. The `pattern` query
parameter is mandatory; `max_bytes` bounds the total body payload and `collection`
narrows the glob to one collection. The same blocked-collection predicate applied
to search applies here.
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- name: pattern
in: query
required: true
schema:
type: string
description: Glob pattern over document paths
- name: collection
in: query
schema:
type: string
- name: max_bytes
in: query
schema:
type: integer
default: 10240
description: Bound on total body payload returned
responses:
'200':
description: Multi-get result
content:
application/json:
schema:
type: object
properties:
pattern:
type: string
collection:
anyOf:
- type: string
- type: 'null'
count:
type: integer
documents:
type: array
items:
type: object
errors:
type: array
items:
type: object
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'GET /documents/{id}
Get a document by docid — Copies of one content under several paths share a docid; the newest copy the caller may read is served, and collection + path pick one. A document the caller may not read answers exactly like a missing one. The answer carries id, the row id (id:<n> names that copy).
- Auth: bearer
- Params:
None,None,None,None - operationId:
getDocument
get:
operationId: getDocument
summary: Get a document by docid
description: 'Copies of one content under several paths share a docid; the newest
copy the caller may read is served, and `collection` + `path` pick one. A document
the caller may not read answers exactly like a missing one. The answer carries
`id`, the row id (`id:<n>` names that copy).
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
responses:
'200':
description: Document details
content:
application/json:
schema:
$ref: '#/components/schemas/Document'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/AmbiguousDocid'PATCH /documents/{id}/visibility
Update document visibility — The identifier is resolved like GET /documents/{id} (FB-0219): copies of one content are the newest copy, id:<n> names a row, and collection + path pick one copy. A tenant admin resolves among every document of the tenant, anyone else among those it may read. It took any row of the 6-character prefix. A client that changes one copy (the SaaS) should send id:<n>.
- Auth: bearer
- Params:
None,None,None,None - Body: object(
visibility* (enum(private, tenant)) ) - operationId:
patchDocumentVisibility
patch:
operationId: patchDocumentVisibility
summary: Update document visibility
description: 'The identifier is resolved like GET /documents/{id} (FB-0219): copies
of one content are the newest copy, `id:<n>` names a row, and `collection` + `path`
pick one copy. A tenant admin resolves among every document of the tenant, anyone
else among those it may read. It took any row of the 6-character prefix. A client
that changes one copy (the SaaS) should send `id:<n>`.
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- visibility
properties:
visibility:
type: string
enum:
- private
- tenant
responses:
'200':
description: Visibility updated
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
docid:
type: string
description: Short docid of the document changed
id:
type: integer
description: Its row id
visibility:
type: string
user_id:
type: string
nullable: true
sensitivity:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: Not the document's owner, and not a tenant admin
'404':
description: Not found, or a document the caller may not read
'409':
$ref: '#/components/responses/AmbiguousDocid'POST /documents/{id}/pin
Pin a document for permanent prioritization
- Auth: bearer
- Params:
None,None,None,None - operationId:
pinDocument
post:
operationId: pinDocument
summary: Pin a document for permanent prioritization
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
responses:
'200':
description: Document pinned
content:
application/json:
schema:
type: object
properties:
docid:
type: string
description: Short docid of the document acted on
id:
type: integer
description: Its row id
pinned:
type: boolean
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: Not found, or a document the caller may not read (FB-0232)
'409':
$ref: '#/components/responses/AmbiguousDocid'POST /documents/{id}/snooze
Temporarily hide a document from context
- Auth: bearer
- Params:
None,None,None,None - Body: object(
until(string) ) - operationId:
snoozeDocument
post:
operationId: snoozeDocument
summary: Temporarily hide a document from context
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
requestBody:
content:
application/json:
schema:
type: object
properties:
until:
type: string
format: date-time
responses:
'200':
description: Document snoozed
content:
application/json:
schema:
type: object
properties:
docid:
type: string
description: Short docid of the document acted on
id:
type: integer
description: Its row id
snoozed:
type: boolean
until:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: Not found, or a document the caller may not read (FB-0232)
'409':
$ref: '#/components/responses/AmbiguousDocid'POST /documents/{id}/forget
Permanently deactivate a document — Deactivates exactly one document: the newest copy the caller may read of the content the docid names, or the copy collection + path pick, or the row id:<n> names. Bare digits that are one row's id and another document's hash prefix are a 409 listing both; nothing is deactivated. The caller must be able to read the document; an owned private document needs its owner, a tenant admin or the platform credential. What was derived from it goes in the same transaction (FB-0222, ADR-088); cascade counts it. dry_run=true counts the same cascade, run and rolled back, and changes nothing.
- Auth: bearer
- Params:
None,None,None,None,dry_run - operationId:
forgetDocument
post:
operationId: forgetDocument
summary: Permanently deactivate a document
description: 'Deactivates exactly one document: the newest copy the caller may read
of the content the docid names, or the copy `collection` + `path` pick, or the
row `id:<n>` names. Bare digits that are one row''s id and another document''s
hash prefix are a 409 listing both; nothing is deactivated. The caller must be
able to read the document; an owned private document needs its owner, a tenant
admin or the platform credential. What was derived from it goes in the same transaction
(FB-0222, ADR-088); `cascade` counts it. dry_run=true counts the same cascade,
run and rolled back, and changes nothing.
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
- name: dry_run
in: query
schema:
type: string
enum:
- 'true'
- 'false'
description: Count what the forget would take (cascade, rolled back) without forgetting
responses:
'200':
description: Document forgotten
content:
application/json:
schema:
type: object
properties:
docid:
type: string
description: Short docid of the forgotten document, whatever identifier
named it
id:
type: integer
description: Its row id
forgotten:
type: boolean
dry_run:
type: boolean
cascade:
type: object
description: What went with it, by table (FB-0222)
additionalProperties:
type: integer
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: '`not_document_owner`: another member''s private document'
'404':
description: Not found, or a document the caller may not read (same body)
'409':
$ref: '#/components/responses/AmbiguousDocid'POST /documents/{id}/feedback
Submit relevance feedback for a document — The identifier is resolved like GET /documents/{id} (FB-0219), among the documents the voter may read: copies of one content are the newest copy, id:<n> names a row, collection + path pick one copy.
- Auth: bearer
- Params:
None,None,None,None - Body: object(
feedback* (enum(POSITIVE, NEGATIVE, VERY_NEGATIVE)),reason(string),user_id(string) ) - operationId:
documentFeedback
post:
operationId: documentFeedback
summary: Submit relevance feedback for a document
description: 'The identifier is resolved like GET /documents/{id} (FB-0219), among
the documents the voter may read: copies of one content are the newest copy, `id:<n>`
names a row, `collection` + `path` pick one copy.
'
tags:
- Documents
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- $ref: '#/components/parameters/DocumentIdentifier'
- $ref: '#/components/parameters/DocumentCollection'
- $ref: '#/components/parameters/DocumentPath'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- feedback
properties:
feedback:
type: string
enum:
- POSITIVE
- NEGATIVE
- VERY_NEGATIVE
reason:
type: string
user_id:
type: string
description: Voter, honored only for the platform credential and the
tenant's SaaS service key (they act for the session they name). Any
other credential votes as its own user; one with no user votes once,
as itself.
responses:
'200':
description: Feedback recorded
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
docid:
type: string
description: Short docid of the document voted on
id:
type: integer
description: Its row id
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: No active document the voter may read
'409':
$ref: '#/components/responses/AmbiguousDocid'POST /conversations
Ingest a whole conversation (turn windows and dated sketch) — Indexes a conversation the way the transcript watcher does: turn windows plus derived documents. POST /documents stays the path for loose text.
- Auth: bearer
- Body: object(
collection* (string),slug* (string),title(string),messages* (array[object(role* (string),content* (string),date(string) )]),userName(string),assistantName(string),sessionId(string),windowSize(integer),overlap(integer) ) - operationId:
ingestConversation
post:
operationId: ingestConversation
summary: Ingest a whole conversation (turn windows and dated sketch)
description: 'Indexes a conversation the way the transcript watcher does: turn windows
plus derived documents. `POST /documents` stays the path for loose text.
'
tags:
- Documents
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- collection
- slug
- messages
properties:
collection:
type: string
slug:
type: string
title:
type: string
messages:
type: array
items:
type: object
required:
- role
- content
properties:
role:
type: string
content:
type: string
date:
type: string
userName:
type: string
assistantName:
type: string
sessionId:
type: string
windowSize:
type: integer
overlap:
type: integer
responses:
'200':
description: Documents written for the conversation
content:
application/json:
schema:
type: object
'400':
description: 'Missing collection, slug or messages, or a slug carrying `#forgotten-`,
reserved for forgotten documents (FB-0217)
'
'401':
$ref: '#/components/responses/Unauthorized'Health
GET /healthz
Public liveness probe — Returns 200 if the process is up. No auth, no store dependency.
- Auth: none
- operationId:
healthz
get:
operationId: healthz
summary: Public liveness probe
description: Returns 200 if the process is up. No auth, no store dependency.
tags:
- Health
security: []
responses:
'200':
description: Process is alive
content:
application/json:
schema:
type: object
required:
- status
- service
- timestamp
properties:
status:
type: string
enum:
- ok
service:
type: string
timestamp:
type: string
format: date-timeGET /health
Health check with database status — Public callers (through the tunnel, no credential) get only status, version and uptime_seconds. Local operators and authenticated callers also get git_hash, database, db_health, tenant corpus counts and request context.
- Auth: none
- operationId:
health
get:
operationId: health
summary: Health check with database status
description: Public callers (through the tunnel, no credential) get only status,
version and uptime_seconds. Local operators and authenticated callers also get
git_hash, database, db_health, tenant corpus counts and request context.
tags:
- Health
security: []
responses:
'200':
description: Service health
content:
application/json:
schema:
type: object
required:
- status
- service
properties:
status:
type: string
service:
type: string
version:
type: string
database:
type: string
documents:
type: integer
needsEmbedding:
type: integer
hasVectors:
type: boolean
request:
$ref: '#/components/schemas/RequestContext'MCP Tokens
GET /api/v1/mcp/tokens
List MCP API tokens
- Auth: bearer
- Params:
None - operationId:
listMcpTokens
get:
operationId: listMcpTokens
summary: List MCP API tokens
tags:
- MCP Tokens
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
responses:
'200':
description: Token list
content:
application/json:
schema:
type: object
properties:
tokens:
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
prefix:
type: string
is_active:
type: boolean
credential_kind:
type: string
enum:
- personal
- gateway
- integration
acts_for_users:
type: boolean
created_at:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'POST /api/v1/mcp/tokens
Create an MCP API token
- Auth: bearer
- Params:
None - Body: object(
name* (string),expires_at(string),credential_kind(enum(personal, gateway)),acts_for_users(boolean) ) - operationId:
createMcpToken
post:
operationId: createMcpToken
summary: Create an MCP API token
tags:
- MCP Tokens
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
expires_at:
type: string
format: date-time
credential_kind:
type: string
enum:
- personal
- gateway
default: personal
description: personal = bound to a person (user_id, else the creator)
and acts as that person. gateway = no person, admin only; reads the
company view (private documents included), narrowed to the X-User-ID
a request names — always send X-User-ID for a person's request. integration
credentials are created at POST /api/v1/authority/integrations.
acts_for_users:
type: boolean
default: false
description: Gateway only (so admin only) — writes act as the tenant
member it names, over that user's own documents only.
responses:
'200':
description: Token created (full key returned only once)
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
id:
type: string
key:
type: string
description: Full API key (shown only at creation)
'401':
$ref: '#/components/responses/Unauthorized'GET /api/v1/mcp/tokens/{tokenId}
Get MCP token details
- Auth: bearer
- Params:
None,tokenId* - operationId:
getMcpToken
get:
operationId: getMcpToken
summary: Get MCP token details
tags:
- MCP Tokens
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- name: tokenId
in: path
required: true
schema:
type: string
responses:
'200':
description: Token details
content:
application/json:
schema:
type: object
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'PUT /api/v1/mcp/tokens/{tokenId}
Update MCP token
- Auth: bearer
- Params:
None,tokenId* - Body: object(
name(string),is_active(boolean) ) - operationId:
updateMcpToken
put:
operationId: updateMcpToken
summary: Update MCP token
tags:
- MCP Tokens
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- name: tokenId
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
is_active:
type: boolean
responses:
'200':
description: Token updated
content:
application/json:
schema:
type: object
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'DELETE /api/v1/mcp/tokens/{tokenId}
Delete MCP token
- Auth: bearer
- Params:
None,tokenId* - operationId:
deleteMcpToken
delete:
operationId: deleteMcpToken
summary: Delete MCP token
tags:
- MCP Tokens
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
- name: tokenId
in: path
required: true
schema:
type: string
responses:
'200':
description: Token deleted
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'Memory
POST /api/v1/memory/prepare
Session briefing plus memory relevant to a message — REST mirror of the MCP memory_prepare tool: identity, task state, what changed, notifications and the memory relevant to message, in one call. The tenant comes from the credential.
- Auth: bearer
- Body: object(
message* (string),collection(string),episode_id(string),recall_budget(integer),include_recall(boolean),fast_mode(boolean) ) - operationId:
memoryPrepare
post:
operationId: memoryPrepare
summary: Session briefing plus memory relevant to a message
description: 'REST mirror of the MCP `memory_prepare` tool: identity, task state,
what changed, notifications and the memory relevant to `message`, in one call.
The tenant comes from the credential.
'
tags:
- Memory
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- message
properties:
message:
type: string
description: The task or question (alias `query`).
collection:
type: string
episode_id:
type: string
recall_budget:
type: integer
include_recall:
type: boolean
default: true
fast_mode:
type: boolean
default: false
responses:
'200':
description: Briefing and relevant memory
content:
application/json:
schema:
type: object
properties:
conflicts:
type: array
description: 'The open conflicts about the message''s subject the
caller may read (FB-0221 phase 3), also told in `blocks.conflicts`
and in the `__conflicts__` document delivered first; omitted when
there are none, in `fast_mode`, and with `VALORBRAIN_CONFLICT_ANNOTATE=false`.
'
items:
$ref: '#/components/schemas/OpenConflict'
'400':
description: '`message` missing'
'401':
$ref: '#/components/responses/Unauthorized'POST /api/v1/memory/store
Persist a typed memory (decision, observation, lesson…) — REST mirror of the MCP memory_store tool.
- Auth: bearer
- Body: object(
type(string),title* (string),content* (string),collection(string),tags(array[string]),confidence(number) ) - operationId:
memoryStore
post:
operationId: memoryStore
summary: Persist a typed memory (decision, observation, lesson…)
description: REST mirror of the MCP `memory_store` tool.
tags:
- Memory
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- title
- content
properties:
type:
type: string
default: note
description: decision, observation, problem, milestone, handoff, lesson
or note.
title:
type: string
minLength: 5
content:
type: string
minLength: 20
collection:
type: string
description: Defaults to the caller agent's collection.
tags:
type: array
items:
type: string
confidence:
type: number
responses:
'200':
description: Stored memory (path and docid)
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
action:
type: string
enum:
- inserted
- updated
- deduplicated
docid:
type: string
description: 'Short docid (6-char hash prefix), the identifier GET
/documents/{id}, /search and forget use. With "deduplicated", the
existing document''s. Before FB-0219 this field carried the numeric
row id.
'
id:
type: integer
description: Row id of the document (what `docid` carried before FB-0219)
collection:
type: string
path:
type: string
type:
type: string
title:
type: string
message:
type: string
'400':
description: Title or content too short
'401':
$ref: '#/components/responses/Unauthorized'OAuth
GET /.well-known/oauth-authorization-server
OAuth authorization server metadata — Public discovery endpoint per RFC 9414.
- Auth: none
- operationId:
oauthAsMetadata
get:
operationId: oauthAsMetadata
summary: OAuth authorization server metadata
description: Public discovery endpoint per RFC 9414.
tags:
- OAuth
security: []
responses:
'200':
description: Authorization server metadata
content:
application/json:
schema:
type: objectGET /.well-known/oauth-protected-resource
OAuth protected resource metadata — Public discovery endpoint per RFC 9728.
- Auth: none
- operationId:
oauthRsMetadata
get:
operationId: oauthRsMetadata
summary: OAuth protected resource metadata
description: Public discovery endpoint per RFC 9728.
tags:
- OAuth
security: []
responses:
'200':
description: Protected resource metadata
content:
application/json:
schema:
type: objectPOST /oauth/register
Dynamic client registration
- Auth: none
- Body: object(
client_name(string),redirect_uris(array[string]),grant_types(array[string]),scope(string) ) - operationId:
oauthRegister
post:
operationId: oauthRegister
summary: Dynamic client registration
tags:
- OAuth
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
client_name:
type: string
redirect_uris:
type: array
items:
type: string
grant_types:
type: array
items:
type: string
scope:
type: string
description: Space-separated subset of "read write"; default "read write"
responses:
'201':
description: Client registered
content:
application/json:
schema:
type: object
properties:
client_id:
type: string
token_endpoint_auth_method:
type: string
enum:
- none
scope:
type: string
'400':
$ref: '#/components/responses/BadRequest'GET /oauth/authorize
OAuth authorization endpoint — Redirects to consent page.
- Auth: none
- Params:
response_type,client_id,redirect_uri,code_challenge,code_challenge_method,scope,state,resource - operationId:
oauthAuthorize
get:
operationId: oauthAuthorize
summary: OAuth authorization endpoint
description: Redirects to consent page.
tags:
- OAuth
security: []
parameters:
- name: response_type
in: query
required: true
schema:
type: string
enum:
- code
description: Only "code" is accepted
- name: client_id
in: query
required: true
schema:
type: string
- name: redirect_uri
in: query
required: true
schema:
type: string
- name: code_challenge
in: query
required: true
schema:
type: string
description: PKCE challenge (S256)
- name: code_challenge_method
in: query
schema:
type: string
default: S256
enum:
- S256
- name: scope
in: query
schema:
type: string
default: read
- name: state
in: query
schema:
type: string
- name: resource
in: query
schema:
type: string
description: RFC 8707 resource indicator; must be served by this AS
responses:
'302':
description: Redirect to consent page
'400':
$ref: '#/components/responses/BadRequest'POST /oauth/token
OAuth token exchange
- Auth: none
- operationId:
oauthToken
post:
operationId: oauthToken
summary: OAuth token exchange
tags:
- OAuth
security: []
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required:
- grant_type
properties:
grant_type:
type: string
code:
type: string
client_id:
type: string
client_secret:
type: string
redirect_uri:
type: string
responses:
'200':
description: Token response
content:
application/json:
schema:
type: object
properties:
access_token:
type: string
token_type:
type: string
expires_in:
type: integer
refresh_token:
type: string
'400':
$ref: '#/components/responses/BadRequest'POST /oauth/revoke
Revoke an OAuth token
- Auth: none
- operationId:
oauthRevoke
post:
operationId: oauthRevoke
summary: Revoke an OAuth token
tags:
- OAuth
security: []
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required:
- token
properties:
token:
type: string
responses:
'200':
description: Token revokedObservability
POST /api/v1/memory/recall
Token-budgeted memory recall — Pull category-ranked memory in a fixed token budget (mem0-style).
- Auth: bearer
- Params:
None - Body: object(
query(string),budget(integer),format(enum(json, markdown)) ) - operationId:
memoryRecall
post:
operationId: memoryRecall
summary: Token-budgeted memory recall
description: Pull category-ranked memory in a fixed token budget (mem0-style).
tags:
- Observability
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
query:
type: string
budget:
type: integer
default: 1500
format:
type: string
enum:
- json
- markdown
default: markdown
responses:
'200':
description: Budgeted memory recall
content:
application/json:
schema:
type: object
'401':
$ref: '#/components/responses/Unauthorized'POST /api/v1/memory/used
Declare which memories an answer actually used (quality loop) — REST mirror of the MCP memory_used tool. The agent declares the docids ('#ab12cd' hex prefixes) or paths of the memories it relied on; optionally a verdict ("confirmed"/"corrected") when the user reacted to what the memory said. Feeds usage coverage, ranking signals and the trust loop. Infra agents excluded downstream.
- Auth: bearer
- Params:
None - Body: object(
docids* (array[string]),verdict(enum(confirmed, corrected)),note(string) ) - operationId:
memoryUsed
post:
operationId: memoryUsed
summary: Declare which memories an answer actually used (quality loop)
description: 'REST mirror of the MCP `memory_used` tool. The agent declares the
docids (''#ab12cd'' hex prefixes) or paths of the memories it relied on; optionally
a verdict ("confirmed"/"corrected") when the user reacted to what the memory said.
Feeds usage coverage, ranking signals and the trust loop. Infra agents excluded
downstream.
'
tags:
- Observability
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- docids
properties:
docids:
type: array
items:
type: string
description: Docids ('#ab12cd') or document paths; [] declares an empty
working set (no usage event)
verdict:
type: string
enum:
- confirmed
- corrected
description: User confirmed or corrected what the memory said (V5)
note:
type: string
description: Why the memories were useful
responses:
'200':
description: Declaration recorded
content:
application/json:
schema:
type: object
properties:
declared:
type: integer
marked:
type: integer
description: 'Recall deliveries this declaration credited: per document,
the latest delivery by explicit retrieval to the caller''s session
(X-Session-ID, or the vbm_ token''s session key) in the 12 hours
before the declaration. 0 without a session.
'
unresolved:
type: array
items:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'GET /api/v1/memory/health
Memory health diagnostics — Open (and in-progress) update proposals, open conflicts, high-priority proposals and canonical sources with drift. expired_proposals_count counts proposals that expired in the last 30 days: an open proposal nobody picks or resolves for 30 days becomes expired.
- Auth: bearer
- Params:
None - operationId:
memoryHealth
get:
operationId: memoryHealth
summary: Memory health diagnostics
description: 'Open (and in-progress) update proposals, open conflicts, high-priority
proposals and canonical sources with drift. `expired_proposals_count` counts proposals
that expired in the last 30 days: an open proposal nobody picks or resolves for
30 days becomes `expired`.'
tags:
- Observability
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
responses:
'200':
description: Health diagnostics
content:
application/json:
schema:
type: object
'401':
$ref: '#/components/responses/Unauthorized'Search
POST /search
Hybrid search (BM25 + vector + rerank) — Full hybrid search: BM25 and dense vectors fused by RRF, then a cross-encoder rerank and MMR diversity. An LLM only expands the query (optional HyDE); it never ranks. Optional self-correct retrieval. Personalized PageRank exists behind a flag and is off in production. Searches DOCUMENTS (prose): keyed facts (upsert_keyed_fact / keyed_facts) are NOT part of the text index — query them via keyed_facts_as_of, or receive the current values with declared precedence via memory_prepare / working_context.
- Auth: bearer
- Params:
None - Body: object(
query* (string),collection(string),limit(integer),order(enum(relevance, event_time)),intent(string),expand(boolean),self_correct(boolean),mode(enum(auto, keyword, semantic, hybrid)),compact(boolean),profile(enum(speed, balanced, deep)),explain(boolean) ) - operationId:
search
post:
operationId: search
summary: Hybrid search (BM25 + vector + rerank)
description: 'Full hybrid search: BM25 and dense vectors fused by RRF, then a cross-encoder
rerank and MMR diversity. An LLM only expands the query (optional HyDE); it never
ranks. Optional self-correct retrieval. Personalized PageRank exists behind a
flag and is off in production. Searches DOCUMENTS (prose): keyed facts (upsert_keyed_fact
/ keyed_facts) are NOT part of the text index — query them via keyed_facts_as_of,
or receive the current values with declared precedence via memory_prepare / working_context.
'
tags:
- Search
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
properties:
query:
type: string
description: Search query
collection:
type: string
description: Filter to collection (comma-separated list is split)
limit:
type: integer
default: 10
order:
type: string
enum:
- relevance
- event_time
description: Delivery order of the final set
intent:
type: string
expand:
type: boolean
description: Force HyDE expansion on/off
self_correct:
type: boolean
description: Self-correct retrieval
mode:
type: string
enum:
- auto
- keyword
- semantic
- hybrid
compact:
type: boolean
default: true
profile:
type: string
enum:
- speed
- balanced
- deep
explain:
type: boolean
description: Attach retrieval channels per hit
responses:
'200':
description: Search results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/SearchResult'
query:
type: string
mode:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'POST /search/temporal
Temporal search with time-aware filtering
- Auth: bearer
- Params:
None - Body: object(
query* (string),reference_date(string),limit(integer),user_id(string),run_id(string) ) - operationId:
temporalSearch
post:
operationId: temporalSearch
summary: Temporal search with time-aware filtering
tags:
- Search
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
properties:
query:
type: string
reference_date:
type: string
format: date-time
description: Anchor for temporal intent detection (default now)
limit:
type: integer
default: 10
maximum: 50
user_id:
type: string
run_id:
type: string
responses:
'200':
description: Temporally filtered results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/SearchResult'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'POST /search/hierarchical
Hierarchical search across memory layers
- Auth: bearer
- Params:
None - Body: object(
query* (string),max_depth(integer),top_k(integer),score_alpha(number) ) - operationId:
hierarchicalSearch
post:
operationId: hierarchicalSearch
summary: Hierarchical search across memory layers
tags:
- Search
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
properties:
query:
type: string
max_depth:
type: integer
default: 3
top_k:
type: integer
default: 20
score_alpha:
type: number
default: 0.7
responses:
'200':
description: Hierarchical results
content:
application/json:
schema:
type: object
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'POST /retrieve
Unified retrieval with auto-routing — Auto-classifies query intent and routes to optimal search backend.
- Auth: bearer
- Params:
None - Body: object(
query* (string),mode(enum(auto, keyword, semantic, causal, timeline, discovery, complex, hybrid)),limit(integer),collection(string),compact(boolean),profile(enum(speed, balanced, deep)),include_structured(boolean),explain(boolean) ) - operationId:
retrieve
post:
operationId: retrieve
summary: Unified retrieval with auto-routing
description: Auto-classifies query intent and routes to optimal search backend.
tags:
- Search
parameters:
- $ref: '#/components/parameters/TenantIdHeader'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
properties:
query:
type: string
maxLength: 2000
mode:
type: string
enum:
- auto
- keyword
- semantic
- causal
- timeline
- discovery
- complex
- hybrid
default: auto
limit:
type: integer
collection:
type: string
description: Comma-separated list is split into multiple collections
compact:
type: boolean
default: true
profile:
type: string
enum:
- speed
- balanced
- deep
include_structured:
type: boolean
explain:
type: boolean
responses:
'200':
description: Retrieved results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/SearchResult'
mode:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'413':
description: Query longer than 2000 chars