API

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 required

POST /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 workspace

POST /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: object

Documents

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-time

GET /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: object

GET /.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: object

POST /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 revoked

Observability

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'

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

On this page