> ## Documentation Index
> Fetch the complete documentation index at: https://docs.get-exo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Retrieve context

> Retrieve identity-conditioned context for a query.

Exo answers from the org's trained ExoBrain when one is available and transparently falls back to a hybrid vector plus keyword search over your stored content otherwise; `path` and `degraded` say which engine served the call, and `degraded` is also true when the brain answered from a knowledge graph that has changed since it was trained (`degradationReason` is then `brain_stale`). The response carries ranked `sources`, any detected `contradictions`, a `cognition` block (brain path only) and a `usage` block.

Data is scoped to the effective subject: the API key owner by default, or the subject named by the `X-Exo-Subject` header. Set `stream` to true to receive the same result as a `text/event-stream` carrying `sources`, `contradictions`, `cognition` and `done` events.

## Authorization

This route requires the `read` scope.

A missing or invalid credential returns 401 [`authentication_error`](/errors/authentication_error). A valid credential without the scope returns 403 [`permission_denied`](/errors/permission_denied), and the problem body names the exact scope required.

## Headers

These are request conventions the contract does not declare as parameters, so they do not appear in the schema tables below.

| Header            | Applies      | What it does                                                                                                                                           |
| ----------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `X-Exo-API-Key`   | Required     | Your Exo API key, `exo_<env>_<token>`. `Authorization: Bearer exo_...` is accepted as an alternate.                                                    |
| `X-Exo-Subject`   | Optional     | Acts for a provisioned subject instead of the key owner. An unprovisioned id returns 403 [`subject_not_provisioned`](/errors/subject_not_provisioned). |
| `Idempotency-Key` | Not honoured | This route does not replay: reads have no side effect to replay.                                                                                       |
| `X-Request-Id`    | Response     | Returned on every response, including `204`s. Quote it in a support request.                                                                           |

## Success responses

| Status | Meaning                                                            |
| ------ | ------------------------------------------------------------------ |
| `200`  | Ranked sources plus the contradiction, cognition and usage blocks. |

## Errors

| Status | Code                                                   | When                                                           |
| ------ | ------------------------------------------------------ | -------------------------------------------------------------- |
| `400`  | [`invalid_request`](/errors/invalid_request)           | Malformed request, for example an invalid cursor.              |
| `401`  | [`authentication_error`](/errors/authentication_error) | Missing or invalid credentials.                                |
| `403`  | [`permission_denied`](/errors/permission_denied)       | Missing scope, or an unprovisioned subject selector.           |
| `404`  | [`not_found`](/errors/not_found)                       | The resource does not exist, or is not visible to this caller. |
| `409`  | [`conflict`](/errors/conflict)                         | A conflict with the current state of the resource.             |
| `422`  | [`validation_error`](/errors/validation_error)         | The request was understood but failed field validation.        |
| `429`  | [`rate_limit_exceeded`](/errors/rate_limit_exceeded)   | Rate limit exceeded. Retry after the Retry-After interval.     |
| `503`  | [`service_degraded`](/errors/service_degraded)         | A dependency is temporarily unavailable. Safe to retry.        |

Every error is an RFC 9457 `application/problem+json` body carrying a stable `code`, a `requestId`, and a `suggestedAction` where Exo has one. See [Errors](/platform/errors).

## Notes

* **`cognition` is null on the hybrid path.** The block is the brain's reasoning trace, and the vector plus keyword fallback has no reasoning state to report. Read `path` before you read `cognition`.
* **`degraded` can be true on the brain path.** It means the brain answered from a knowledge graph that has changed since it trained, and `degradationReason` is then `brain_stale`. The other two reasons, `no_brain` and `cold_start`, only ever appear with `path: "hybrid"`.
* **The `contradictions` entries here are not the `Contradiction` object.** `GET /v1/contradictions` returns the named schema with `id`, `a`, `b`, `status` and `detectedAt`. This route returns the retrieval-time shape instead: `kind`, `subkind`, `nodeId` as `node_id`, `marker`, `before`, `after`, `tension`, `in_active_subgraph` and `snippet`, plus `from_concept` and `to_concept` on a reversal. The schema types the field as a free-form object for exactly this reason. Treat it as advisory and read the contradictions resource when you need the stable object.
* **Streaming changes the content type, not the content.** With `stream: true` the same result arrives as `text/event-stream` in event order `sources`, `contradictions`, `cognition`, `done`.
* **`expand` accepts one relation in v1.** `sources.content` replaces the 280-character `snippet` preview with the full stored chunk text. Any other value is 422 `invalid_expand`.


## OpenAPI

````yaml openapi.json POST /v1/retrieve
openapi: 3.1.0
info:
  contact:
    name: Exo
    url: https://get-exo.com/
  description: >-
    The Exo public developer API: ingest content, retrieve identity-conditioned
    context, and read the knowledge graph. Authenticate every request with an
    Exo API key, either as the X-Exo-API-Key header or as Authorization: Bearer
    exo_... . Errors follow RFC 9457 problem+json with a stable snake_case code
    on every body.
  title: Exo API
  version: 1.0.0
servers:
  - url: https://api.get-exo.com
security:
  - ApiKeyHeader: []
  - BearerAuth: []
tags:
  - name: retrieve
    x-group: Retrieval
  - name: search
    x-group: Search
  - name: ingest
    x-group: Ingestion
  - name: jobs
    x-group: Jobs
  - name: subjects
    x-group: Subjects
  - name: recall
    x-group: Recall
  - name: graph
    x-group: Graph
  - name: insights
    x-group: Contradictions and proposals
  - name: condition
    x-group: Condition
  - name: brain
    x-group: Brain
  - name: sessions
    x-group: Coding sessions
  - name: connectors
    x-group: Connectors
  - name: events
    x-group: Events and webhooks
  - name: meta
    x-group: Identity
  - name: keys
    x-group: Keys and sandbox
  - name: usage
    x-group: Usage
  - name: settings
    x-group: Settings
  - name: exports
    x-group: Exports
  - name: team
    x-group: Team
  - name: admin
    x-group: Account and purge
paths:
  /v1/retrieve:
    post:
      tags:
        - retrieve
      summary: Retrieve context
      description: >-
        Retrieve identity-conditioned context for a query.


        Exo answers from the org's trained ExoBrain when one is available and
        transparently falls back to a hybrid vector plus keyword search over
        your stored content otherwise; `path` and `degraded` say which engine
        served the call, and `degraded` is also true when the brain answered
        from a knowledge graph that has changed since it was trained
        (`degradationReason` is then `brain_stale`). The response carries ranked
        `sources`, any detected `contradictions`, a `cognition` block (brain
        path only) and a `usage` block.


        Data is scoped to the effective subject: the API key owner by default,
        or the subject named by the `X-Exo-Subject` header. Set `stream` to true
        to receive the same result as a `text/event-stream` carrying `sources`,
        `contradictions`, `cognition` and `done` events.
      operationId: postRetrieve
      parameters:
        - description: >-
            Comma-separated relations to expand beyond the lean default. Valid
            values: sources.content (the full stored text of each source, beyond
            the 280-character snippet).
          in: query
          name: expand
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: >-
              Comma-separated relations to expand beyond the lean default. Valid
              values: sources.content (the full stored text of each source,
              beyond the 280-character snippet).
            title: Expand
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RetrieveRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RetrieveResponse'
          description: Ranked sources plus the contradiction, cognition and usage blocks.
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: Malformed request, for example an invalid cursor.
        '401':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: Missing or invalid credentials.
        '403':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: Missing scope or unprovisioned subject.
        '404':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: The requested resource does not exist.
        '409':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: Conflict, for example a duplicate in-flight idempotent request.
        '422':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: Validation Error
        '429':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: >-
            Rate limit exceeded; retry after the interval in the Retry-After
            header.
        '503':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
          description: A dependency is temporarily unavailable; safe to retry with backoff.
components:
  schemas:
    RetrieveRequest:
      description: A context-retrieval request. Field names accept camelCase or snake_case.
      properties:
        expand:
          anyOf:
            - items:
                type: string
              type: array
            - type: string
            - type: 'null'
          description: >-
            Comma-separated relations to expand beyond the lean default. Valid
            values: sources.content (the full stored text of each source, beyond
            the 280-character snippet).
          title: Expand
        includeContradictions:
          default: true
          title: Includecontradictions
          type: boolean
        query:
          maxLength: 10000
          minLength: 1
          title: Query
          type: string
        scope:
          default: user
          enum:
            - user
            - org
          title: Scope
          type: string
        stream:
          default: false
          title: Stream
          type: boolean
        topK:
          default: 8
          maximum: 50
          minimum: 1
          title: Topk
          type: integer
      required:
        - query
      title: RetrieveRequest
      type: object
    RetrieveResponse:
      description: >-
        Retrieved context for a query.


        ``path`` names the engine that served the call ("brain" when the org's

        trained ExoBrain answered, "hybrid" on the vector plus keyword
        fallback).

        ``degraded`` is true on the fallback path, and also on the brain path
        when

        the brain is serving a knowledge graph that has changed since it
        trained;

        ``degradationReason`` says why ("no_brain", "brain_stale" or
        "cold_start").

        ``cognition`` is present only on the brain path.
      properties:
        cognition:
          anyOf:
            - $ref: '#/components/schemas/Cognition'
            - type: 'null'
          description: >-
            The brain's reasoning trace for this query. Null on the hybrid
            fallback path, which has no reasoning state to report.
          title: Cognition
        contradictions:
          default: []
          items:
            additionalProperties: true
            type: object
          title: Contradictions
          type: array
        degradationReason:
          anyOf:
            - type: string
            - type: 'null'
          title: Degradationreason
        degraded:
          title: Degraded
          type: boolean
        latencyMs:
          title: Latencyms
          type: integer
        path:
          enum:
            - brain
            - hybrid
          title: Path
          type: string
        query:
          title: Query
          type: string
        sources:
          items:
            additionalProperties: true
            type: object
          title: Sources
          type: array
        traceId:
          default: ''
          title: Traceid
          type: string
        usage:
          $ref: '#/components/schemas/RetrieveUsage'
      required:
        - query
        - sources
        - path
        - degraded
        - latencyMs
        - usage
      title: RetrieveResponse
      type: object
    Problem:
      description: |-
        RFC 9457 problem+json envelope (spec D9), documented in OpenAPI.

        Invariant: ``code`` equals the tail of the ``type`` URI
        (``https://docs.get-exo.com/errors/<code>``).
      properties:
        code:
          title: Code
          type: string
        detail:
          title: Detail
          type: string
        documentationUrl:
          anyOf:
            - type: string
            - type: 'null'
          title: Documentationurl
        errors:
          anyOf:
            - items:
                $ref: '#/components/schemas/FieldViolation'
              type: array
            - type: 'null'
          title: Errors
        requestId:
          default: ''
          title: Requestid
          type: string
        status:
          title: Status
          type: integer
        suggestedAction:
          anyOf:
            - type: string
            - type: 'null'
          title: Suggestedaction
        title:
          title: Title
          type: string
        type:
          title: Type
          type: string
      required:
        - type
        - title
        - status
        - detail
        - code
      title: Problem
      type: object
    Cognition:
      additionalProperties: true
      description: >-
        How Exo reasoned about a query, not just what it retrieved.


        Present on a retrieval only when the org's trained ExoBrain served the
        call;

        it is null on the hybrid vector plus keyword fallback, which has no
        reasoning

        state to report. ``focalNodeIds`` are the knowledge-graph nodes the
        brain

        settled on as the centre of the answer, ``confidence`` is how strongly
        it

        settled, and ``useSystem2`` is true when the brain judged the question
        hard

        enough to warrant slow deliberate reasoning instead of a fast
        associative

        lookup. ``driftRate`` reports how far the activated region has moved
        from

        what the brain trained on, which is the early warning that the graph has

        outgrown the brain.


        The block is versioned additively: a future reasoning tier may report
        extra

        fields, so treat unknown keys as forward compatible rather than an
        error.
      properties:
        confidence:
          description: How strongly the brain settled on this answer, from 0 to 1.
          title: Confidence
          type: number
        driftRate:
          description: >-
            How far the activated region has drifted from the state the brain
            trained on, from 0 (aligned) upward.
          title: Driftrate
          type: number
        focalNodeIds:
          description: >-
            The knowledge-graph nodes the brain settled on as the centre of the
            answer.
          items:
            type: string
          title: Focalnodeids
          type: array
        tier:
          description: The reasoning tier that served the call.
          title: Tier
          type: string
        useSystem2:
          description: >-
            True when the brain escalated to slow deliberate reasoning rather
            than a fast associative lookup.
          title: Usesystem2
          type: boolean
      required:
        - confidence
        - driftRate
        - tier
        - useSystem2
      title: Cognition
      type: object
    RetrieveUsage:
      description: >-
        Additive per-call usage counters (spec D13).


        MCP / exo-cli / plugin / dashboard read only sources, contradictions and

        cognition, so this extra object never breaks an existing consumer.


        - ``readUnits``: number of sources returned (the billable read unit).

        - ``embedTokens``: DOCUMENTED ESTIMATE of Voyage embed tokens for the
        query
          at ~3.5 chars/token (the same tokenizer-free proxy the Voyage client uses
          internally). The embedder's ``embed()`` return does not surface
          ``usage.total_tokens``, so this is an estimate, not the metered figure.
        - ``brainInference``: True when the ExoBrain served the query, False on
        the
          hybrid pgvector+BM25 fallback path.
      properties:
        brainInference:
          title: Braininference
          type: boolean
        embedTokens:
          title: Embedtokens
          type: integer
        readUnits:
          title: Readunits
          type: integer
      required:
        - readUnits
        - embedTokens
        - brainInference
      title: RetrieveUsage
      type: object
    FieldViolation:
      description: A single field-level violation inside a Problem ``errors[]`` list.
      properties:
        code:
          title: Code
          type: string
        field:
          title: Field
          type: string
        message:
          title: Message
          type: string
        pointer:
          title: Pointer
          type: string
      required:
        - pointer
        - field
        - code
        - message
      title: FieldViolation
      type: object
  securitySchemes:
    ApiKeyHeader:
      description: An Exo API key (exo_...) sent as the X-Exo-API-Key header.
      in: header
      name: X-Exo-API-Key
      type: apiKey
    BearerAuth:
      description: The same Exo API key (exo_...) sent as an Authorization bearer token.
      scheme: bearer
      type: http

````