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

# Filter, rank and page documents

> See §6.8. A query whose estimated scan exceeds 4 GB is refused with
`too_large` and the estimate, and is not billed. Filtering or ranking on
an `on_read` judgment is `invalid_request`.




## OpenAPI

````yaml /api-reference/openapi.yaml post /namespaces/{ns}/query
openapi: 3.1.0
info:
  title: Vainona API
  version: '1'
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
  description: |
    The `/v1` contract from main spec §6. It is locked: changes within `/v1`
    are additive only, and anything breaking is `/v2`.

    - **Base URL.** `https://api.vainona.ai/v1`.
    - **Evolution.** Response objects may gain fields and enums may gain values.
      Clients must ignore what they do not know. Request objects reject unknown
      fields.
    - **Path segments.** Namespace names (`{ns}`) and document ids (`{id}`) may
      contain `/`. Send it percent-encoded as `%2F`, so that
      `acme/prod/tenant_123` is `acme%2Fprod%2Ftenant_123`.
    - **Templates (v1.5).** The judgment routes also take a namespace prefix
      ending in `/*`, such as `acme%2Fprod%2F*`. A judgment created there is a
      template: every namespace under the prefix inherits it, including ones
      created later. The most specific matching prefix wins (§7.7).
    - **Thresholds are settings (v1.5).** Named thresholds belong to the
      judgment, not to a version. They are evaluated at read time against the
      raw fields, so a change applies at once to every answer, with no
      recompute and no new version (§6.5).
    - **Entity judgments (entities, E1).** A judgment can read the documents
      that point at the judged one, through `context.related`, and apply only
      to documents matching `applies_to` (§6.5.2). Its answers carry a
      `watermark`, and creating one that runs `on_change` returns a replay
      estimate of its monthly cost until you confirm (§6.9).
    - **Referenced documents (entities, E3a).** A relation can also read the
      one document the judged document points at, through
      `join: {theirs: "id", mine: "attributes.<name>"}`. A change to what the
      relation renders of that document re-judges the judged documents that
      point at it and are inside `freshness.fanout.scope`: a fan-out. A large
      fan-out is a `fanout` job that waits for confirm (§6.5.2, §6.9).
    - **Idempotency.** Every write operation is idempotent by construction.
      `Idempotency-Key` is accepted on every mutating route and, while the node
      still caches the original response, returns it verbatim.
    - **Errors.** Every error is the `Error` envelope; the HTTP status follows
      the code (see each response).
    - **Rate limits.** Every response carries `X-RateLimit-Limit` and
      `X-RateLimit-Remaining`; a `rate_limited` response adds `Retry-After`,
      except a daily allowance that is used up, which says when it renews in
      `details.resets_at` instead.
    - **Usage.** Every response that bills carries `usage`. Judging is billed in
      engine-neutral judgment units: one judgment answered, per started 1,000
      tokens of its compiled context and its question together, at least 1
      (§9). No response ever carries an
      engine's price.
servers:
  - url: https://api.vainona.ai/v1
security:
  - apiKey: []
tags:
  - name: Namespaces
    description: Namespaces, their settings and cache warming (§6.2, §6.11).
  - name: Documents
    description: Writes, point reads and queries (§6.3 to §6.8).
  - name: Judgments
    description: >-
      Judgment definitions, versions, settings, activation, backfill and
      template detach (§6.5, §6.9, §7.7).
  - name: Outcomes and calibration
    description: |
      Post what actually happened to judged documents, and read how well answers
      match it: the calibration report, calibrated answers and threshold
      recommendations (§6.10). See [calibration](/concepts/calibration).
  - name: Jobs
    description: >-
      Backfill, shadow, periodic, deletion, reference index and fan-out jobs
      (§6.2, §6.9, §7.10.5).
  - name: Engines
    description: The engine registry (§6.5, §7.4.5).
paths:
  /namespaces/{ns}/query:
    parameters:
      - $ref: '#/components/parameters/Namespace'
    post:
      tags:
        - Documents
      summary: Filter, rank and page documents
      description: |
        See §6.8. A query whose estimated scan exceeds 4 GB is refused with
        `too_large` and the estimate, and is not billed. Filtering or ranking on
        an `on_read` judgment is `invalid_request`.
      operationId: query
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryRequest'
      responses:
        '200':
          description: One page of rows.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QueryResponse'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/TooLarge'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/Internal'
components:
  parameters:
    Namespace:
      name: ns
      in: path
      required: true
      description: The namespace name, with any `/` sent as `%2F`.
      schema:
        $ref: '#/components/schemas/NamespaceName'
  schemas:
    QueryRequest:
      type: object
      additionalProperties: false
      properties:
        filters:
          $ref: '#/components/schemas/Filter'
        rank_by:
          $ref: '#/components/schemas/RankBy'
        top_k:
          type: integer
          minimum: 1
          maximum: 1000
        cursor:
          type:
            - string
            - 'null'
          description: >-
            The previous page's `next_cursor`. Valid for 10 minutes; pins the
            manifest so pages are consistent.
        include:
          type: object
          additionalProperties: false
          properties:
            attributes:
              type: array
              uniqueItems: true
              items:
                $ref: '#/components/schemas/Name'
            answers:
              type: array
              uniqueItems: true
              items:
                $ref: '#/components/schemas/Name'
            state:
              type: boolean
        answers:
          type: string
          enum:
            - any
            - fresh_only
          default: any
          description: '`fresh_only` excludes rows whose included answers are not `fresh`.'
        consistency:
          type: string
          enum:
            - strong
            - eventual
          default: strong
          description: '`eventual` may serve a cached manifest up to 60 seconds old.'
    QueryResponse:
      type: object
      required:
        - rows
        - next_cursor
        - more
        - usage
      properties:
        rows:
          type: array
          items:
            $ref: '#/components/schemas/QueryRow'
        next_cursor:
          type:
            - string
            - 'null'
        more:
          type: boolean
          description: True when rows beyond `top_k` matched.
        usage:
          $ref: '#/components/schemas/Usage'
    NamespaceName:
      type: string
      description: >-
        Up to 256 bytes. `/` separates levels of the hierarchy, as in
        `acme/prod/tenant_123`.
      pattern: ^[A-Za-z0-9._:/-]+$
      minLength: 1
      maxLength: 256
    Filter:
      description: |
        `[field, op, value]`, `["And" | "Or", [filters]]` or `["Not", filter]`.
      oneOf:
        - $ref: '#/components/schemas/EqualityFilter'
        - $ref: '#/components/schemas/RangeFilter'
        - $ref: '#/components/schemas/SetFilter'
        - $ref: '#/components/schemas/GlobFilter'
        - $ref: '#/components/schemas/ContainsFilter'
        - $ref: '#/components/schemas/ExistsFilter'
        - $ref: '#/components/schemas/AndOrFilter'
        - $ref: '#/components/schemas/NotFilter'
    RankBy:
      type: array
      description: One field and a direction. Ties are broken by `id`.
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - enum:
            - asc
            - desc
      minItems: 2
      items: false
      default:
        - updated_at
        - desc
    Name:
      type: string
      description: >-
        A judgment, attribute or threshold name. Names are path segments in
        field references, so they never contain `.`.
      pattern: ^[A-Za-z0-9_-]+$
      minLength: 1
      maxLength: 128
    QueryRow:
      type: object
      required:
        - id
        - revision
      properties:
        id:
          $ref: '#/components/schemas/DocumentId'
        revision:
          $ref: '#/components/schemas/Revision'
        attributes:
          $ref: '#/components/schemas/Attributes'
        answers:
          $ref: '#/components/schemas/Answers'
        state:
          $ref: '#/components/schemas/State'
    Usage:
      type: object
      description: What this response billed (§6.1).
      minProperties: 1
      properties:
        bytes_written:
          type: integer
          format: int64
          minimum: 0
        bytes_scanned:
          type: integer
          format: int64
          minimum: 0
        judgment_units:
          type: integer
          format: int64
          minimum: 0
          description: |
            Judgment units billed (§9): one per judgment answered, per started
            1,000 tokens of its compiled context and its question together (the
            question's text, criteria and every option or level), at least 1.
            The worker that evaluates meters
            them, so writes with `wait_for` and reads with `wait_ms` return the
            answers without their units; the units appear in your usage.
        tokens_evaluated:
          type: integer
          format: int64
          minimum: 0
          deprecated: true
          description: Never reported. Judging is billed in `judgment_units`.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
            details:
              type: object
              description: >-
                Code-specific detail, such as the scan estimate on a refused
                query. Every `internal` error has `request_id`.
    EqualityFilter:
      type: array
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - enum:
            - Eq
            - NotEq
        - $ref: '#/components/schemas/FilterScalar'
      minItems: 3
      items: false
    RangeFilter:
      type: array
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - enum:
            - Lt
            - Lte
            - Gt
            - Gte
        - type:
            - string
            - number
      minItems: 3
      items: false
    SetFilter:
      type: array
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - enum:
            - In
            - NotIn
        - type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/FilterScalar'
      minItems: 3
      items: false
    GlobFilter:
      type: array
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - const: Glob
        - type: string
      minItems: 3
      items: false
    ContainsFilter:
      type: array
      description: True when a string-array attribute contains the value.
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - const: Contains
        - type: string
      minItems: 3
      items: false
    ExistsFilter:
      type: array
      description: >-
        `["attributes.plan", "Exists", true]` matches documents that have the
        field; `false` matches those that do not.
      prefixItems:
        - $ref: '#/components/schemas/FilterField'
        - const: Exists
        - type: boolean
      minItems: 3
      items: false
    AndOrFilter:
      type: array
      prefixItems:
        - enum:
            - And
            - Or
        - type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/Filter'
      minItems: 2
      items: false
    NotFilter:
      type: array
      prefixItems:
        - const: Not
        - $ref: '#/components/schemas/Filter'
      minItems: 2
      items: false
    DocumentId:
      type: string
      description: Up to 128 bytes.
      pattern: ^[A-Za-z0-9._:/-]+$
      minLength: 1
      maxLength: 128
    Revision:
      type: integer
      format: int64
      minimum: 0
    Attributes:
      type: object
      description: >-
        Flat, filterable and sortable. At most 64 keys. Not sent to engines
        unless a context recipe names them.
      maxProperties: 64
      propertyNames:
        $ref: '#/components/schemas/Name'
      additionalProperties:
        $ref: '#/components/schemas/AttributeValue'
    Answers:
      type: object
      description: Answers keyed by judgment name.
      propertyNames:
        $ref: '#/components/schemas/Name'
      additionalProperties:
        $ref: '#/components/schemas/Answer'
    State:
      type: object
      description: >-
        The JSON content judgments are made about. At most 1 MB. Never
        filterable.
    ErrorCode:
      type: string
      description: |
        HTTP status by code: `invalid_request` 400, `unauthorized` 401,
        `budget_exceeded` 402, `forbidden` 403, `not_found` 404, `conflict` 409,
        `too_large` 413, `engine_version_unavailable` 422,
        `insufficient_labels` 422, `rate_limited` 429, `internal` 500,
        `engine_unavailable` 503.
      enum:
        - invalid_request
        - unauthorized
        - forbidden
        - not_found
        - conflict
        - too_large
        - rate_limited
        - budget_exceeded
        - engine_unavailable
        - engine_version_unavailable
        - insufficient_labels
        - internal
    AttributeValue:
      description: A string, number, boolean, string array or null.
      type:
        - string
        - number
        - boolean
        - array
        - 'null'
      items:
        type: string
    Answer:
      type: object
      description: |
        The current answer of one judgment for one document, discriminated on
        `type`. Only `type` and `freshness` are always present: numbers and
        provenance are absent when no evaluation has succeeded.
      oneOf:
        - $ref: '#/components/schemas/BoolAnswer'
        - $ref: '#/components/schemas/ChoiceAnswer'
        - $ref: '#/components/schemas/ScoreAnswer'
      discriminator:
        propertyName: type
        mapping:
          bool:
            $ref: '#/components/schemas/BoolAnswer'
          choice:
            $ref: '#/components/schemas/ChoiceAnswer'
          score:
            $ref: '#/components/schemas/ScoreAnswer'
    BoolAnswer:
      type: object
      description: A bool answer has no `value`; booleans come only from named thresholds.
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/AnswerCommon'
      properties:
        type:
          const: bool
        p:
          $ref: '#/components/schemas/Probability'
          description: >-
            The engine's probability, or for a composite judgment the
            probability its combiner gives the parts (§6.5.1). Thresholds,
            filters and ranking use it.
        calibrated:
          $ref: '#/components/schemas/BoolCalibration'
        parts:
          type: object
          description: Composite judgments only. Each part's raw `p` from the engine.
          propertyNames:
            $ref: '#/components/schemas/Name'
          additionalProperties:
            $ref: '#/components/schemas/Probability'
        features:
          $ref: '#/components/schemas/FeatureValues'
        combiner:
          $ref: '#/components/schemas/CombinerUse'
    ChoiceAnswer:
      type: object
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/AnswerCommon'
      properties:
        type:
          const: choice
        value:
          type: string
          description: The most probable option; ties go to the earlier option.
        dist:
          $ref: '#/components/schemas/Distribution'
        escape_p:
          $ref: '#/components/schemas/Probability'
          description: The probability of `none_of_the_above`.
        calibrated:
          $ref: '#/components/schemas/ChoiceCalibration'
    ScoreAnswer:
      type: object
      required:
        - type
      allOf:
        - $ref: '#/components/schemas/AnswerCommon'
      properties:
        type:
          const: score
        score:
          type: number
          description: The probability-weighted mean of level values.
        dist:
          $ref: '#/components/schemas/Distribution'
        calibrated:
          $ref: '#/components/schemas/ScoreCalibration'
    AnswerCommon:
      type: object
      required:
        - freshness
      properties:
        freshness:
          $ref: '#/components/schemas/Freshness'
        revision:
          $ref: '#/components/schemas/Revision'
          description: The document revision the numbers were computed for.
        watermark:
          $ref: '#/components/schemas/Revision'
          description: |
            Entity judgments only (entities, E1, §6.6): the log position the
            context was read at. Every write with a revision at or below it,
            to the document or its related documents, is reflected; a later
            one that touched the document makes the answer `pending` or
            `stale`. For a relation that reads a referenced document
            (entities, E3a), it also says which version of that document the
            answer read. A later write to it touches the document only when it
            changes what the relation renders and the document is inside the
            re-judge scope, so a referenced document with a `revision` above
            the watermark shows the answer read an earlier version of it.
            Absent on a `failed` answer: its numbers are the last good ones,
            and the failed attempt's position does not describe them.
        referenced_changes:
          type: array
          description: |
            Entities, E3a (§6.6). Get only, never in query rows. For a judgment
            with a relation that reads a referenced document: for each such
            relation, the newest write to the document the judged document
            points at now that changed what the relation renders, whether or
            not the document is inside the re-judge scope for it. A relation
            whose referenced document has never changed is left out, and so
            is the key when none has. A change at or below `watermark` is
            reflected in the answer. One above it makes the answer `pending`
            or `stale` when the document is inside the scope, and leaves it
            `fresh` when it is outside.
          items:
            $ref: '#/components/schemas/AnswerReferencedChange'
        judgment_version:
          $ref: '#/components/schemas/JudgmentVersionNumber'
        engine:
          type: string
        engine_version:
          type: string
        evaluation_id:
          type: string
          description: |
            The evaluation that computed these numbers. When a change leaves
            the compiled context the same, the answer is reused for the new
            revision without calling the engine, and this still names the
            earlier evaluation, whose `revision` (and, for an entity
            judgment, `watermark`) is older than the answer's.
        evaluated_at:
          $ref: '#/components/schemas/Timestamp'
        thresholds:
          type: object
          description: >-
            The judgment's current thresholds (its setting, not the answer's
            version), evaluated at read time against the raw fields.
          propertyNames:
            $ref: '#/components/schemas/Name'
          additionalProperties:
            type: boolean
    Probability:
      type: number
      minimum: 0
      maximum: 1
    BoolCalibration:
      type: object
      required:
        - p
      allOf:
        - $ref: '#/components/schemas/CalibrationCommon'
      properties:
        p:
          $ref: '#/components/schemas/Probability'
    FeatureValues:
      type: object
      description: >-
        Composite judgments with features only (entities, E1, §6.5.1). Each
        feature's raw value, as rendered in the context; null when missing.
      propertyNames:
        $ref: '#/components/schemas/FeatureRef'
      additionalProperties:
        type:
          - number
          - 'null'
    CombinerUse:
      type: object
      description: |
        Composite judgments only: the combiner `p` came from, fitted on the
        judgment's outcomes per version and engine epoch (§6.5.1). A
        composite's answer has no `calibrated` object, because the combiner
        is already fitted to outcomes.
      required:
        - outcomes
        - from_previous_epoch
      properties:
        outcomes:
          type: integer
          format: int64
          minimum: 50
          description: The labelled documents the combiner was fitted on.
        from_previous_epoch:
          type: boolean
          description: >-
            True after a Jev drift, while the answer's epoch has fewer than 50
            outcomes, so the previous epoch's combiner applies.
    Distribution:
      type: object
      description: Probability per option or level value. Sums to 1.
      additionalProperties:
        $ref: '#/components/schemas/Probability'
    ChoiceCalibration:
      type: object
      required:
        - value
        - dist
        - escape_p
      allOf:
        - $ref: '#/components/schemas/CalibrationCommon'
      properties:
        value:
          type: string
          description: The most probable option under the calibrated distribution.
        dist:
          $ref: '#/components/schemas/Distribution'
        escape_p:
          $ref: '#/components/schemas/Probability'
    ScoreCalibration:
      type: object
      required:
        - score
        - dist
      allOf:
        - $ref: '#/components/schemas/CalibrationCommon'
      properties:
        score:
          type: number
          description: >-
            The probability-weighted mean of level values under the calibrated
            distribution.
        dist:
          $ref: '#/components/schemas/Distribution'
    Freshness:
      type: string
      description: |
        Derived at read time (§7.1.6). `stale` and `failed` still carry the
        last good numbers and the `revision` they were computed for. A `failed`
        answer for a document never judged successfully has no numbers.
      enum:
        - fresh
        - pending
        - stale
        - failed
        - unavailable
    AnswerReferencedChange:
      type: object
      description: |
        Entities, E3a (§6.6, §7.1.14). A referenced change row: the newest
        write to a referenced document that changed what a relation renders.
      required:
        - relation
        - document_id
        - revision
        - at
        - declined
      properties:
        relation:
          $ref: '#/components/schemas/Name'
        document_id:
          $ref: '#/components/schemas/DocumentId'
        revision:
          $ref: '#/components/schemas/Revision'
          description: The referenced document's revision at the write.
        at:
          $ref: '#/components/schemas/Timestamp'
          description: The write's `updated_at`, which the re-judge scope counts back from.
        declined:
          type: boolean
          description: >-
            The change's `fanout` job was cancelled, so its in-scope answers
            read `stale` until the judged or referenced document next changes
            (§6.9).
    JudgmentVersionNumber:
      type: integer
      format: int32
      minimum: 1
    Timestamp:
      type: string
      format: date-time
      description: RFC 3339, UTC.
    CalibrationCommon:
      type: object
      description: |
        The answer's numbers under the judgment's calibration (§6.6, §6.10),
        computed at read time from the current fit for the answer's judgment
        version and engine epoch. Present once that fit rests on at least 100
        outcomes with at least 20 of each class (`true` and `false` for a
        bool; two values with 20 each for a choice or score). The raw fields
        never change meaning and are never replaced. Calibration never
        reverses the order of answers. See [calibration](/concepts/calibration).
      required:
        - method
        - outcomes
        - from_previous_epoch
        - extrapolated
      properties:
        method:
          $ref: '#/components/schemas/CalibrationMethod'
        outcomes:
          type: integer
          format: int64
          minimum: 100
          description: The number of outcomes the calibration was fitted on.
        from_previous_epoch:
          type: boolean
          description: |
            True after a Jev drift, while the answer's epoch does not yet have
            enough outcomes of its own: the calibration is the previous
            epoch's.
        extrapolated:
          type: boolean
          description: |
            True when the answer's raw value (`p`, or the probability of the
            most probable option or level) lies outside the range of raw values
            the fit was made on. The calibrated numbers are then a guess; post
            outcomes for documents like this one to cover it.
    CalibrationMethod:
      type: string
      description: >-
        `platt`: from 100 outcomes, Platt scaling for `bool` and temperature
        scaling over the distribution for `choice` and `score`. `isotonic`:
        isotonic regression, from 1,000.
      enum:
        - platt
        - isotonic
  headers:
    RateLimitLimit:
      description: Requests allowed per second for this key.
      schema:
        type: integer
        minimum: 0
    RateLimitRemaining:
      description: Requests left in the current window.
      schema:
        type: integer
        minimum: 0
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
        minimum: 0
  responses:
    InvalidRequest:
      description: '`invalid_request`: the request is malformed or breaks a rule of §6.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: '`unauthorized`: the key is missing, unknown or revoked.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: '`forbidden`: the key''s role or namespace prefix does not allow this.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: '`not_found`: the namespace, document, judgment or job does not exist.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: >-
        `conflict`: the namespace is being deleted, an object a read needs was
        compacted away and the read (or the query, without its cursor) must
        restart (§7.5.11), or the judgment is inherited from a template and this
        namespace cannot create, activate or delete it (§7.7).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooLarge:
      description: >-
        `too_large`: the request body (on any route), a document, or the
        estimated query scan is over its limit. `details` carries the estimate
        for queries. It also answers a write that would take
        `default/quickstart` past its size cap (10,000 documents or 100 MB),
        with `details.max_documents` and `details.max_bytes`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: >-
        `rate_limited`: slow down. `Retry-After` says for how long, except when
        a daily allowance is used up: then `details.resets_at` says when it
        renews, and there is no `Retry-After`.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Internal:
      description: >-
        `internal`: something failed on our side. Nothing partial is returned,
        and a request never commits part of itself. Most `internal` errors
        committed nothing. A write can instead fail with a message saying it may
        have been committed, when we could not tell whether its batch landed
        (§7.2.10): it then committed all of it or none of it. Retrying a write
        is safe either way, because writes are idempotent. The message is
        generic and carries a request id, also in `details.request_id`, which
        support uses to find the cause.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: |
        An organization API key. Keys carry a role (`read_write` or
        `read_only`) and may be restricted to a namespace prefix such as
        `acme/*`, or to one namespace such as `acme/prod/tenant_1`. A prefix
        matches on a `/` boundary: `acme/prod/tenant_1*` covers
        `acme/prod/tenant_1` and everything under `acme/prod/tenant_1/`,
        never `acme/prod/tenant_12`.

````