# AUTO-GENERATED tier-A mirror spec — do not edit.
# Source: openapi/runtime/traces.yaml (runtime 0.71.2)
#  + policy: openapi/mirror-policies/traces.json
# Regenerate: node scripts/generate-mirror-specs.mjs
openapi: 3.0.3
info:
  title: naturali.ai — Traces API
  version: 1.0.0
  description: >-
    Traces: the execution record of a run — its tree of child traces, the generations underneath
    them, and the content-purge control that erases a tenant's data while leaving the audit skeleton
    behind. A fully runtime-backed module — this spec is generated verbatim from the runtime's own,
    re-rooted under /v1/projects/{project_id}. The project in the path is authorized by naturali and
    enforced upstream by the project's scoped credential.


    This module mirrors the upstream runtime verbatim (tier A, #304): paths are the runtime's own
    re-rooted under /v1/projects/{project_id}, and every field, method, status code and error shape
    passes through unchanged. Errors raised by the runtime arrive in its envelope; errors raised by
    naturali itself (authentication, project resolution, an unreachable runtime) use naturali's.
  contact:
    name: naturali.ai
    url: https://naturali.ai
servers:
  - url: "{baseUrl}"
    description: Host of your naturali.ai deployment; every path carries the /v1 prefix.
    variables:
      baseUrl:
        description: Base host URL.
        default: https://api.naturali.ai
tags:
  - name: Traces
    description: Inspect execution traces and trace trees
security:
  - bearerAuth: []
  - oauth2:
      - mcp:access
paths:
  /v1/projects/{project_id}/traces:
    get:
      tags:
        - Traces
      summary: List traces
      description: Returns a paginated list of execution traces for the project.
      operationId: listTraces
      parameters:
        - name: limit
          in: query
          required: false
          description: Maximum number of results to return
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: offset
          in: query
          required: false
          description: Number of results to skip
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: List of traces
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Trace"
                  total:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/traces/{trace_id}:
    get:
      tags:
        - Traces
      summary: Get a trace
      description: Returns a single trace by ID.
      operationId: getTrace
      x-naturali-resource:
        kind: trace
        from: trace_id
      parameters:
        - name: trace_id
          in: path
          required: true
          schema:
            type: string
          description: Public ID of the trace
      responses:
        "200":
          description: Trace details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Trace"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Trace not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/traces/{trace_id}/tree:
    get:
      tags:
        - Traces
      summary: Get trace tree
      description: >
        Returns the full execution tree rooted at the given trace (or its root if the given trace is
        a child). Each node represents one agent's execution session. The `children` array contains
        traces triggered by sub-agent tool calls from that trace.
      operationId: getTraceTree
      x-naturali-resource:
        kind: trace
        from: trace_id
      parameters:
        - name: trace_id
          in: path
          required: true
          schema:
            type: string
          description: Public ID of any trace in the tree (root or child)
        - name: include
          in: query
          required: false
          description: >
            Comma-separated list of related resources to embed on each node. Supported value:
            `generations` — attaches all generations that belong to each trace node (including
            sub-agent generations linked via `initiator_generation_id`).
          schema:
            type: string
            example: generations
      responses:
        "200":
          description: Trace tree rooted at the resolved root trace
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TraceTreeNode"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Trace not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/traces/{trace_id}/content:
    delete:
      tags:
        - Traces
      summary: Purge trace content
      description: >
        Deletes the trace's steps object from storage and clears its content columns (`file_id`,
        `error`), cascading to every descendant trace and to all of their generations. A descendant
        holds its own steps object covering the same run, so the cascade is what makes the erasure
        complete rather than merely partial.


        The rows survive as auditable skeletons with `content_redacted_at` set — ids, timestamps,
        step counts, and the generations' usage-attribution fields are preserved, because the
        billing and audit ledger must outlive a tenant's erasure of the content. A purged trace
        therefore reads back as a skeleton, not a 404: a 404 would prove nothing.


        Idempotent — purging an already-purged trace succeeds and leaves the original
        `content_redacted_at` in place.
      operationId: purgeTraceContent
      x-naturali-resource:
        kind: trace
        from: trace_id
      parameters:
        - name: trace_id
          in: path
          required: true
          schema:
            type: string
          description: Public ID of the trace
      responses:
        "200":
          description: The purged trace skeleton
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Trace"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Trace not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    parameters:
      - $ref: "#/components/parameters/ProjectId"
components:
  schemas:
    Trace:
      type: object
      properties:
        id:
          type: string
          description: Public ID of the trace
          example: trace_V1StGXR8Z5jdHi6B
        project_id:
          x-naturali-ref: projects
          type: string
          description: Public ID of the project
        agent_id:
          x-naturali-ref: agents
          type: string
          description: Public ID of the agent that produced this trace
        file_id:
          x-naturali-ref: files
          type: string
          nullable: true
          description: >
            Public ID of the File containing the full serialized steps JSON. Null if the trace has
            not been saved yet (save is fire-and-forget).
          example: file_xyz789
        step_count:
          type: integer
          description: Number of steps recorded in this trace
          example: 2
        parent_trace_id:
          x-naturali-ref: traces
          type: string
          nullable: true
          description: >
            Public ID of the parent trace. Null if this trace is the root (i.e., it was not
            triggered by a sub-agent call from another trace).
        root_trace_id:
          x-naturali-ref: traces
          type: string
          nullable: true
          description: >
            Public ID of the root trace for the entire execution tree. Null if this trace is itself
            the root.
        error:
          type: object
          nullable: true
          description: >
            Structured error payload recorded when a generation in this trace failed (e.g. an
            upstream AI provider error). Null if no failure has been recorded.
          properties:
            code:
              type: string
              example: AI_PROVIDER_ERROR
            message:
              type: string
              example: "Provider returned 402: insufficient credits"
            meta:
              type: object
        content_redacted_at:
          type: string
          format: date-time
          nullable: true
          description: >
            When the trace's content was purged. Non-null means the steps object has been deleted
            from storage and the content columns cleared, while this row survives as an auditable
            skeleton (ids, timestamps, step count). A purged trace still reads back as a skeleton
            with this marker set rather than as a 404, so the erasure is provable.
        content_redacted_by_principal_type:
          type: string
          nullable: true
          description: Principal kind that purged the content ('user' or 'api_key')
          example: user
        content_redacted_by_principal_id:
          type: string
          nullable: true
          description: >
            Public ID of the principal that purged the content — the API key's own id for key auth,
            so the record names which key acted.
        created_at:
          type: string
          format: date-time
    TraceTreeNode:
      type: object
      description: A trace node in the execution tree, with nested children.
      properties:
        id:
          type: string
          description: Public ID of the trace
        project_id:
          x-naturali-ref: projects
          type: string
        agent_id:
          x-naturali-ref: agents
          type: string
        file_id:
          x-naturali-ref: files
          type: string
          nullable: true
        step_count:
          type: integer
        parent_trace_id:
          x-naturali-ref: traces
          type: string
          nullable: true
        root_trace_id:
          x-naturali-ref: traces
          type: string
          nullable: true
        error:
          type: object
          nullable: true
          description: Structured error payload recorded when a generation in this trace failed
        created_at:
          type: string
          format: date-time
        content_redacted_at:
          type: string
          format: date-time
          nullable: true
          description: >
            When the trace's content was purged. Non-null means the steps object has been deleted
            from storage and the content columns cleared, while this row survives as an auditable
            skeleton (ids, timestamps, step count). A purged trace still reads back as a skeleton
            with this marker set rather than as a 404, so the erasure is provable.
        content_redacted_by_principal_type:
          type: string
          nullable: true
          description: Principal kind that purged the content ('user' or 'api_key')
          example: user
        content_redacted_by_principal_id:
          type: string
          nullable: true
          description: >
            Public ID of the principal that purged the content — the API key's own id for key auth,
            so the record names which key acted.
        children:
          type: array
          description: Child traces triggered by sub-agent calls from this trace
          items:
            $ref: "#/components/schemas/TraceTreeNode"
        generations:
          type: array
          description: >
            Generations that belong to this trace node. Only present when `include=generations` is
            requested. Includes top-level generations and sub-agent child generations linked via
            `initiator_generation_id`.
          items:
            $ref: "#/components/schemas/Generation"
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          description: Structured error. Every error response uses this shape, so `code` can be read without
            first checking the type of `error`.
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: "Machine-readable error code: lower_snake for an error naturali raises
                (`access_denied`), UPPER_SNAKE for one the runtime reports (`RESOURCE_NOT_FOUND`)."
              example: access_denied
            message:
              type: string
              description: Human-readable explanation.
              example: Your role in this project does not carry this action.
            details:
              type: object
              additionalProperties: true
              description: Structured context for an error naturali raises, such as the `resource` and `limit` of
                a `plan_limit_reached`.
            meta:
              type: object
              description: Structured context for an error the runtime reports.
    Generation:
      type: object
      properties:
        id:
          type: string
          description: Public ID of the generation
          example: gen_V1StGXR8Z5jdHi6B
        project_id:
          x-naturali-ref: projects
          type: string
          description: Public ID of the project
        agent_id:
          x-naturali-ref: agents
          type: string
          description: Public ID of the agent that ran this generation
        trace_id:
          x-naturali-ref: traces
          type: string
          description: Public ID of the trace this generation belongs to
        initiator_generation_id:
          x-naturali-ref: generations
          type: string
          nullable: true
          description: >
            Public ID of the generation that started this one: a sub-agent invocation, an approval
            continuation, a client-tool re-handoff or a memory-rule handler turn. Null for top-level
            generations.
        chain_id:
          x-naturali-ref: chains
          type: string
          nullable: true
          description: >
            Public ID of the continuation chain this generation belongs to. Set on every member of a
            chain — the continuations and the root they descend from — and null on a generation that
            is not part of one.
        conversation_id:
          x-naturali-ref: conversations
          type: string
          nullable: true
          description: >
            Public ID of the conversation this turn served, or null for a generation started outside
            one — a direct call, a trigger, an orchestration node. This is the edge a memory
            assertion walks up to reach the conversation a fact was learned in.
        session_id:
          x-naturali-ref: sessions
          type: string
          nullable: true
          description: >
            Public ID of the session this generation was dispatched through, or null for a
            generation started outside one. This is the link a per-session cost reading follows; the
            session's own `usage` field reports the roll-up directly.
        actor_id:
          x-naturali-ref: actors
          type: string
          nullable: true
          description: >
            Public ID of the end-user actor the generation was attributed to, or null when none was.
            Copied onto the generation's usage event.
        started_by_principal_type:
          type: string
          nullable: true
          description: Type of the principal that started the generation
        started_by_principal_id:
          type: string
          nullable: true
          description: ID of the principal that started the generation
        status:
          type: string
          description: Lifecycle status of the generation
          enum:
            - in_progress
            - requires_action
            - completed
            - failed
          example: failed
        started_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: When the generation reached a terminal state
        last_activity_at:
          type: string
          format: date-time
          nullable: true
        stop_reason:
          type: string
          nullable: true
          description: >
            Why the generation stopped. Either the model provider's own finish reason relayed
            unchanged ('stop', 'tool-calls', 'length', …) or one the platform names itself:
            'max_steps' when the turn spent its whole step budget on tool calls, 'depth_guard' when
            a nested call exceeded the call depth, 'chain_limit' when a continuation chain reached
            its generation budget, or 'error' when the turn failed.
          example: error
        error:
          type: object
          nullable: true
          description: >
            Structured error payload recorded when the generation failed. Contains at least
            `message`; `code` is set for mapped errors (e.g. AI_PROVIDER_ERROR for upstream provider
            failures).
          properties:
            code:
              type: string
              example: AI_PROVIDER_ERROR
            message:
              type: string
              example: "Provider returned 402: insufficient credits"
            meta:
              type: object
        action_id:
          type: string
          nullable: true
          description: >
            Logical action label supplied on the generate request. Recorded on the generation's
            usage event for per-action spend rollups.
        trigger_id:
          x-naturali-ref: triggers
          type: string
          nullable: true
          description: Trigger that initiated the generation, when applicable
        orchestration_run_id:
          x-naturali-ref: orchestration-runs
          type: string
          nullable: true
          description: |
            Orchestration run that dispatched the generation. Null for a standalone generation.
        node_id:
          type: string
          nullable: true
          description: >
            Node within `orchestration_run_id` that dispatched the generation. Together with the run
            it forms the usage event's replay identity.
        node_attempt:
          type: integer
          nullable: true
          description: >
            The node's 1-based retry attempt, completing the run + node + attempt replay identity. A
            retried node produces one generation per attempt; this is what tells them apart. Null
            for a generation no orchestration node dispatched.
        agent_version:
          type: integer
          nullable: true
          description: >
            Agent config version that served this generation, resolved by the served-version
            resolver (see [agent versions](/docs/modules/agents#versions-and-releases)).
        extraction:
          type: object
          nullable: true
          description: >
            What each [memory rule](/docs/modules/memories#memory-rules) bound to
            `agents.generation.completed` wrote for this turn, keyed by the rule's id — a store may
            have several rules, and one flat pair of counts could not say which produced them.
            Absent when no rule fired. Rules bound to `conversations.message.generated` are recorded
            in `memory_assertions` only. The rows behind every count are in `memory_assertions`, so
            the summary and what it summarizes can be reconciled.
          additionalProperties:
            type: object
            properties:
              candidates:
                type: integer
                description: Number of candidates the rule's handler proposed
              created:
                type: integer
                description: Number of new memories created
              superseded:
                type: integer
                description: >
                  Number of candidates that restated a known fact that had changed, retiring the
                  memory holding it
              skipped:
                type: integer
                description: Number of candidates skipped (e.g. duplicates)
        memory_assertions:
          type: array
          description: >
            Every memory write this turn made, oldest first — each memory rule's firings and the
            agent's own `write_memory` calls alike, which the `extraction` counts never covered.
            Present on the single read only; a listing would make it one extra query per generation.
          items:
            $ref: "#/components/schemas/MemoryAssertion"
        tool_surface:
          type: object
          nullable: true
          description: >-
            What this turn's tool definitions cost to send — the one part of a prompt no provider
            reports and no caller can derive, since the tool block is a constant inside the reported
            totals and identical on every step.


            Null when the surface was never measured: a generation from before the field, or a path
            that resolves none. That is **not** what `tools: 0` means, which is a measured agent
            with nothing bound.


            Not a meter. `estimated_tokens` is an estimate and is never priced — `usage` and the
            usage events are the billing record.
          properties:
            tools:
              type: integer
              description: Tools resolved for the turn, before any per-step narrowing by `step_rules`.
              example: 61
            bytes:
              type: integer
              description: Serialized length of those definitions — name, description and input schema — in
                canonical JSON, not the provider's wire format. Exact, and comparable across
                providers, which is what makes two agents' surfaces worth comparing.
              example: 152161
            estimated_tokens:
              type: integer
              description: "`bytes` over a measured bytes-per-token ratio. An estimate, and named one."
              example: 45148
        retrieval:
          type: array
          nullable: true
          description: >-
            What `knowledge_config` retrieval injected into this turn, in the order it was injected:
            which document, at which version, and which chunk, or which memory. Written by the
            server at turn start and never writable; pointers only, never the text.


            Null when no retrieval ran — the agent has no `knowledge_config`, or the turn had
            neither a query nor a filter to search with. An empty array is a retrieval that ran and
            matched nothing.


            Not content: a content purge leaves it standing, and zero retention still writes it.
            `document_version` names an archived version, so the text the turn read stays readable
            after the document changes.
          items:
            oneOf:
              - $ref: "#/components/schemas/GenerationRetrievedDocument"
              - $ref: "#/components/schemas/GenerationRetrievedMemory"
            discriminator:
              propertyName: source_type
              mapping:
                document: "#/components/schemas/GenerationRetrievedDocument"
                memory: "#/components/schemas/GenerationRetrievedMemory"
        idempotency_key:
          type: string
          nullable: true
          description: The deduplication key the generation was started under, unique within the project and
            claimed for as long as the generation record exists. Null for a generation started
            without one.
          example: discord-1287654321098765432
        usage:
          allOf:
            - $ref: "#/components/schemas/UsageTotals"
          nullable: true
          description: >-
            What the turn cost: token counts and `cost_usd` for every event metered against this
            generation. Present on the single-generation read; omitted from the listing, where it
            would be a query per row.


            Null when nothing has been metered yet — a turn still in flight, or one whose metering
            failed. A turn is metered once at the end, so this is one event's figures in the
            ordinary case.
        routing:
          type: object
          nullable: true
          description: >
            What the model route did for this generation. Present only when the agent resolves its
            model through a `model_route_id`.
          properties:
            route_id:
              x-naturali-ref: model-routes
              type: string
              description: The route that resolved the model
            target_index:
              type: integer
              nullable: true
              description: >
                Position in the route's `targets` of the target that served the last LLM call; null
                when every attempt failed.
            fallbacks:
              type: integer
              description: >
                How many times the route moved past a target during this generation (cumulative
                across a multi-step run).
            attempts:
              type: array
              description: >
                Every attempt, in order, across every LLM call of the run. An attempt with no
                `error_class` succeeded.
              items:
                type: object
                properties:
                  target_index:
                    type: integer
                  ai_provider_id:
                    x-naturali-ref: ai-providers
                    type: string
                  model:
                    type: string
                  error_class:
                    type: string
                    enum:
                      - provider_error
                      - timeout
                      - rate_limited
                    description: >
                      Why the attempt failed. Absent on the serving attempt, and absent on a
                      deterministic failure (which fails the generation instead of failing over).
        metadata:
          description: >
            Caller-owned key/value annotations, attached at create time (via the `metadata` field on
            the create-agent-generation request) or afterwards (via the update-generation request),
            and returned verbatim. The server writes nothing here: every piece of state it owns —
            usage attribution, the served agent version, the route's record, the extraction summary,
            internal recovery state — is a field of its own, so no key written here can reach
            platform state. Keys are never transformed, and no key is reserved.
          example:
            team: payments
            ticket_id: OPS-4821
          allOf:
            - $ref: "#/components/schemas/NullableMetadataBag"
        content_redacted_at:
          type: string
          format: date-time
          nullable: true
          description: >
            When the generation's content was purged. Non-null means `metadata`, `error`,
            `extraction` and the internal recovery state have been cleared, while the usage/audit
            skeleton — ids, timestamps, status, stop reason and the attribution fields — is
            preserved.
        content_redacted_by_principal_type:
          type: string
          nullable: true
          description: Principal kind that purged the content ('user' or 'api_key')
          example: user
        content_redacted_by_principal_id:
          type: string
          nullable: true
          description: >
            Public ID of the principal that purged the content — the API key's own id for key auth,
            so the record names which key acted.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    MemoryAssertion:
      type: object
      description: "One write attempt against a memory store: some principal, through some mechanism,
        claimed a fact. Append-only, and recorded whatever the outcome — including the skips, which
        left no record anywhere before."
      properties:
        id:
          type: string
          example: massert_V1StGXR8Z5jdHi6B
        memory_store_id:
          x-naturali-ref: memory-stores
          type: string
          example: mstore_V1StGXR8Z5jdHi6B
        memory_id:
          type: string
          nullable: true
          description: "The memory this assertion resolved into: the new memory for `created` and
            `superseded`, the existing memory that matched for `skipped`, the memory withdrawn for
            `retracted`. Null only once that memory has been deleted."
          example: mem_V1StGXR8Z5jdHi6B
        superseded_memory_id:
          type: string
          nullable: true
          description: The memory this assertion retired, on a `superseded` outcome; null otherwise, a
            retraction included — it retires its own memory, which `memory_id` already names. Read
            back from `memories.superseded_by_memory_id` rather than stored here, because validity
            lives on the memory — where every read filters it — and exactly one memory is superseded
            per assertion.
          example: mem_V1StGXR8Z5jdHi6B
        content:
          type: string
          description: "The text as asserted, which is not necessarily the memory's text: a `skipped`
            assertion records what was claimed, while the memory keeps what it already held."
          example: The customer prefers email communication over phone calls
        mechanism:
          type: string
          enum:
            - tool
            - rule
            - api
            - formation
          description: Which door the write came through. `tool` is the agent's `write_memory` call mid-turn;
            `rule` is a post-turn pass over the finished turn; `api` is `POST
            /v1/projects/{project_id}/memories`; `formation` is a `memory` resource in an applied
            template. It answers *how*, never *who* — the principal fields answer that.
          example: tool
        rule_id:
          x-naturali-ref: memory-rules
          type: string
          nullable: true
          description: The memory rule whose firing wrote this, set only when `mechanism` is `rule` — the
            built-in extractor included, since that is a rule with no handler. Null once the rule
            has been deleted, and on assertions written before memory rules shipped.
          example: mrule_V1StGXR8Z5jdHi6B
        generation_id:
          x-naturali-ref: generations
          type: string
          nullable: true
          description: The turn that asserted the fact — the origin of anything an agent wrote, and the edge a
            conversation is reachable from. Null on the `api` and `formation` doors, which have no
            generation behind them.
          example: gen_V1StGXR8Z5jdHi6B
        principal_type:
          type: string
          description: Who claimed the fact, in the vocabulary a generation records its starter with, plus
            `agent`. On both agent doors the principal is the agent itself — the extractor runs
            under its identity.
          example: agent
        principal_id:
          type: string
          example: agent_V1StGXR8Z5jdHi6B
        outcome:
          type: string
          enum:
            - created
            - superseded
            - skipped
            - retracted
          description: What the write resolved to. `created` is a distinct fact, `superseded` is the same fact
            changed (the top match was invalidated and replaced), `skipped` is a fact already known,
            `retracted` is a fact that stopped holding with nothing replacing it.
          example: created
        similarity:
          type: number
          nullable: true
          description: The cosine similarity the outcome was decided against — the top match's, or the
            declared target's when `declared` is true, where it decides nothing and only records how
            far apart the two statements were. Null when there was nothing to compare against, when
            the content could not be embedded, and on a `retracted` outcome, which compares nothing.
          example: 0.97
        declared:
          type: boolean
          description: Whether the write named the memory it replaced (`supersedes` on create) instead of the
            thresholds choosing one. Always false on a `created`, `skipped` or `retracted` outcome.
          example: false
        created_at:
          type: string
          format: date-time
    GenerationRetrievedDocument:
      type: object
      required:
        - source_type
        - document_id
        - document_version
        - chunk_id
        - page
        - similarity_score
      properties:
        source_type:
          type: string
          enum:
            - document
          example: document
        document_id:
          x-naturali-ref: documents
          type: string
          description: Public ID of the document the chunk belongs to
          example: doc_V1StGXR8Z5jdHi6B
        document_version:
          type: integer
          nullable: true
          description: The document version the chunk was read from. Read it back with the document's versions
            to see the exact text the turn was given.
          example: 3
        chunk_id:
          type: string
          description: Public ID of the injected chunk. Stops resolving once the document is re-chunked;
            `document_version` is the durable pointer.
          example: dchunk_V1StGXR8Z5jdHi6B
        page:
          type: integer
          nullable: true
          description: Page within the source PDF (1-indexed). Null for plain text.
          example: 2
        similarity_score:
          type: number
          nullable: true
          description: Raw cosine similarity (0–1) between the turn's query and the result. Null when the turn
            had no query, or the search answered from the lexical channel alone. The rank is the
            array order.
          example: 0.82
    GenerationRetrievedMemory:
      type: object
      required:
        - source_type
        - memory_store_id
        - memory_id
        - similarity_score
      properties:
        source_type:
          type: string
          enum:
            - memory
          example: memory
        memory_store_id:
          x-naturali-ref: memory-stores
          type: string
          description: Public ID of the memory store the memory belongs to
          example: mstore_V1StGXR8Z5jdHi6B
        memory_id:
          type: string
          description: Public ID of the injected memory
          example: mem_V1StGXR8Z5jdHi6B
        similarity_score:
          type: number
          nullable: true
          description: Raw cosine similarity (0–1) between the turn's query and the result. Null when the turn
            had no query, or the search answered from the lexical channel alone. The rank is the
            array order.
          example: 0.82
    UsageTotals:
      type: object
      description: >
        Token counts and cost for one slice of the meter. Tokens and cost only: a `compute_second`
        or `gb_day` meter is reported by the aggregate's `components` array.


        The three input dimensions partition the prompt — `input_tokens` = `uncached_input_tokens` +
        `cached_tokens` + `cache_write_tokens` — and are separate because they are separately
        priced. Note that the `input_tokens` **component** on a usage event is the uncached figure
        alone; here `input_tokens` is the whole prompt.
      properties:
        cost_usd:
          type: number
          nullable: true
          description: Sum of priced component costs; null when nothing in the slice was priced. Always null
            at step altitude — the ledger prices one event per generation at write time, and a price
            read back per step would disagree with it after any price change.
        input_tokens:
          type: integer
          description: Full prompt tokens, reconstructed from the components.
        uncached_input_tokens:
          type: integer
          description: Prompt tokens priced at the plain input rate — the prompt minus cache reads and cache
            writes.
        output_tokens:
          type: integer
        cached_tokens:
          type: integer
          description: Prompt tokens served from the provider's prompt cache.
        cache_write_tokens:
          type: integer
          description: Prompt tokens written into the provider's prompt cache.
        reasoning_tokens:
          type: integer
          description: A non-billable subset of `output_tokens`, reported where the provider breaks it out.
    NullableMetadataBag:
      type: object
      nullable: true
      description: A `MetadataBag` on a field where `null` is meaningful — a full-replacement update that
        clears the bag, or a record whose bag was never set.
      example:
        author: John
        revision: 2
  parameters:
    ProjectId:
      name: project_id
      in: path
      required: true
      description: Project public ID (proj_ prefix).
      schema:
        type: string
        example: proj_V1StGXR8Z5jdHi6B
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: A naturali API key (nat_sk_…) or a session JWT.
    oauth2:
      type: oauth2
      description: "A connected app's OAuth access token, issued by this API's authorization server
        (discovery: /.well-known/oauth-authorization-server). Its one scope carries every operation,
        confined to the projects the user chose when approving the app."
      flows:
        authorizationCode:
          authorizationUrl: https://api.naturali.ai/authorize
          tokenUrl: https://api.naturali.ai/token
          refreshUrl: https://api.naturali.ai/token
          scopes:
            mcp:access: Every operation this API serves, on the projects the grant covers.
