> ## 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.

# List starter judgments

> Ready-made judgments for common questions: ticket triage, moderation,
churn risk, lead quality and review queues (D-v15-611). Each is a
definition whose paths are placeholders such as `{subject}`, the
placeholders it needs, and a suggested outcome setting. Create one
with `from_starter` and your own `paths` on
`POST /namespaces/{ns}/judgments`, with `dry_run: true` first to see
the filled definition and what it would cost. The same for every
caller and plan.




## OpenAPI

````yaml /api-reference/openapi.yaml get /starters
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:
      a retried append adds nothing while its values are still in the array,
      and a retried upsert or patch sets the same content again (§6.4).
      `Idempotency-Key` is accepted on the mutating routes that declare it
      and, while the node still caches the original response, returns it
      verbatim. Marking or unmarking a non-production prefix, and starting
      this month's recipe-tuning run, change nothing when repeated, so they
      take none.
    - **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, fan-out and
      evaluation export jobs (§6.2, §6.9, §7.10.5).
  - name: Engines
    description: The engine registry (§6.5, §7.4.5).
  - name: Organization
    description: |
      Settings of the whole organization: prefixes marked non-production,
      which the tenant fee and template calibration pools leave out (§9).
paths:
  /starters:
    get:
      tags:
        - Judgments
      summary: List starter judgments
      description: |
        Ready-made judgments for common questions: ticket triage, moderation,
        churn risk, lead quality and review queues (D-v15-611). Each is a
        definition whose paths are placeholders such as `{subject}`, the
        placeholders it needs, and a suggested outcome setting. Create one
        with `from_starter` and your own `paths` on
        `POST /namespaces/{ns}/judgments`, with `dry_run: true` first to see
        the filled definition and what it would cost. The same for every
        caller and plan.
      operationId: listStarters
      responses:
        '200':
          description: The starter catalogue.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StarterList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/Internal'
components:
  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
  schemas:
    StarterList:
      type: object
      required:
        - version
        - starters
      properties:
        version:
          type: integer
          minimum: 1
          description: >-
            The catalogue's version, raised whenever a starter's definition
            changes.
        starters:
          type: array
          items:
            $ref: '#/components/schemas/Starter'
    Starter:
      type: object
      description: One ready-made judgment (D-v15-611).
      required:
        - id
        - title
        - summary
        - placeholders
        - definition
        - outcomes
      properties:
        id:
          type: string
          description: '`<family>.<judgment>`, what `from_starter` names.'
          examples:
            - churn_risk.at_risk
        title:
          type: string
        summary:
          type: string
          description: When to use it, and what it reads.
        placeholders:
          type: array
          items:
            $ref: '#/components/schemas/StarterPlaceholder'
        definition:
          type: object
          description: |
            A create body without `engine`, whose paths are placeholders: a
            string that is exactly `{name}`, as a value or an object key.
            Not a valid definition until it is filled.
        outcomes:
          description: A suggested outcome setting with placeholders, or null.
          type:
            - object
            - 'null'
    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`.
              properties:
                suggested_context:
                  description: >-
                    On a create without a context recipe, the recipe suggested
                    from the namespace's documents, or null when there are none
                    (D-v15-612).
                  oneOf:
                    - $ref: '#/components/schemas/SuggestedContext'
                    - type: 'null'
    StarterPlaceholder:
      type: object
      required:
        - name
        - kind
        - description
        - example
        - optional
      properties:
        name:
          type: string
          description: What `paths` names it by; `{name}` in the definition.
        kind:
          type: string
          enum:
            - path
            - attribute
            - value
          description: |
            `path`: `state.<key>[.<key>...]` or `attributes.<name>`.
            `attribute`: `attributes.<name>`, for a path matched or joined
            on. `value`: a literal your documents hold, such as the kind of
            document a relation reads.
        description:
          type: string
        example:
          type: string
          description: A typical path or value.
        optional:
          type: boolean
          description: >-
            Left out, it removes the list entry that holds it or the object
            entry it keys.
    ErrorCode:
      type: string
      description: |
        HTTP status by code: `invalid_request` 400, `unauthorized` 401,
        `budget_exceeded` 402, `plan_required` 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
        - plan_required
        - engine_unavailable
        - engine_version_unavailable
        - insufficient_labels
        - internal
    SuggestedContext:
      type: object
      description: |
        The recipe suggested for a create without `context` (D-v15-612), in
        the refusal's `details.suggested_context`. From up to 100 of the
        documents the definition applies to: short text fields, numbers and
        small attributes are kept; ids, timestamps, URLs, base64 and long
        values are left out; arrays longer than 5 keep their last 5; and
        `max_tokens` caps the largest context at a multiple of 500, at most
        2,000. The same documents always give the same recipe.
      required:
        - recipe
        - cost_per_answer
        - whole_state_cost_per_answer
        - sampled_documents
        - excluded
      properties:
        recipe:
          $ref: '#/components/schemas/ContextRecipe'
        cost_per_answer:
          type:
            - number
            - 'null'
          minimum: 0
          description: >-
            Mean judgment units per answer over the sample with this recipe and
            the definition's question.
        whole_state_cost_per_answer:
          type:
            - number
            - 'null'
          minimum: 0
          description: The same with the whole `state`.
        sampled_documents:
          type: integer
          minimum: 1
        excluded:
          type: array
          description: >-
            Each path left out, and why, so you can put back what the question
            needs.
          items:
            type: object
            required:
              - path
              - reason
            properties:
              path:
                type: string
              reason:
                type: string
                enum:
                  - id
                  - timestamp
                  - url
                  - binary
                  - long
                  - rare
                  - too_many
    ContextRecipe:
      type: object
      description: |
        What the engine sees. A create without it is refused with a suggested
        recipe, unless `use_context` asks for the suggestion or the whole
        `state` (D-v15-612); a version with no recipe sends the whole
        `state`, subject to the engine limit.
      additionalProperties: false
      properties:
        fields:
          type: array
          description: Paths included verbatim, in order.
          items:
            type: string
            pattern: ^(state|attributes)(\.[^.]+)+$
        last_n:
          type: object
          description: Per array path, keep the last n elements.
          additionalProperties:
            type: integer
            minimum: 1
        window:
          type: object
          description: >-
            Per array path whose elements have a timestamp field `at`, keep
            elements within the window.
          additionalProperties:
            $ref: '#/components/schemas/Duration'
        max_tokens:
          type: integer
          minimum: 1
          description: Hard cap; the compiler truncates from the end of the last field.
        related:
          type: object
          description: |
            Entities, E1 (§6.5.2). Up to 4 relations, by name: documents in
            the same namespace that point at the judged one or, from E3a, the
            one document it points at. Each renders as a `related.<name>`
            entry after `fields`, and a write that changes what it renders
            makes the judged document's answer `pending` until it is judged
            again (for a referenced document, only inside the re-judge scope;
            outside it, the answer is `stale` with `stale_reason`
            `referenced_changed`).
          minProperties: 1
          maxProperties: 4
          propertyNames:
            $ref: '#/components/schemas/Name'
          additionalProperties:
            $ref: '#/components/schemas/Relation'
    Duration:
      type: string
      description: A whole number and a unit (`s`, `m`, `h` or `d`), such as `7d` or `1h`.
      pattern: ^[1-9][0-9]*[smhd]$
    Relation:
      type: object
      description: |
        Entities, E1 (§6.5.2). Documents that point at the judged document.
        They are ordered newest `created_at` first: `window` keeps those
        created within the window, then `last_n` keeps the newest n. At least
        one of `last_n` and `window` is required, and at least one of
        `fields` and `aggregate`. A relation reads at most the newest 1,000
        documents.

        Entities, E3a: with `join: {theirs: "id", mine: "attributes.<name>"}`
        the relation reads the one document the judged document points at,
        its referenced document, and takes neither `last_n` nor `window`.
      additionalProperties: false
      required:
        - match
        - join
      allOf:
        - description: A relation renders fields or aggregates.
          if:
            not:
              required:
                - fields
          then:
            required:
              - aggregate
        - description: |
            A relation over the documents that point at the judged one is
            bounded by `last_n` or `window`; one that reads the referenced
            document takes neither.
          if:
            properties:
              join:
                type: object
                properties:
                  mine:
                    const: id
          then:
            anyOf:
              - required:
                  - last_n
              - required:
                  - window
          else:
            not:
              anyOf:
                - required:
                    - last_n
                - required:
                    - window
      properties:
        match:
          $ref: '#/components/schemas/AttributeFilter'
          description: Which documents the relation reads.
        join:
          $ref: '#/components/schemas/RelationJoin'
        last_n:
          type: integer
          minimum: 1
          maximum: 1000
          description: >-
            Keep the newest n. Not on a relation that reads a referenced
            document.
        window:
          $ref: '#/components/schemas/Duration'
          description: >-
            Keep documents created within this long before the later of the
            judged document's newest write and its newest related creation, at
            the answer's watermark. An edit to an old related document never
            moves the window. Not on a relation that reads a referenced
            document.
        fields:
          type: array
          description: >-
            Paths to include from each document, rendered under `records`,
            newest first. From entities E3a, an entry may be a `BandedField`,
            which renders a number as its band.
          minItems: 1
          items:
            oneOf:
              - $ref: '#/components/schemas/RelationField'
              - $ref: '#/components/schemas/BandedField'
        aggregate:
          $ref: '#/components/schemas/Aggregate'
    AttributeFilter:
      type: object
      description: |
        Entities, E1 (§6.5). Which documents something applies to, by their
        attributes. Each key is an attribute path; a value is equality, and a
        list of values is `In`, as in query filters. Keys combine with `And`.
      minProperties: 1
      maxProperties: 8
      propertyNames:
        type: string
        pattern: ^attributes\.[A-Za-z0-9_-]+$
      additionalProperties:
        oneOf:
          - $ref: '#/components/schemas/AttributeFilterValue'
          - type: array
            minItems: 1
            items:
              $ref: '#/components/schemas/AttributeFilterValue'
    RelationJoin:
      description: |
        How a related document is matched to the judged one: one side is
        `id`, the other an attribute holding an id. A join with an attribute
        on both sides, documents sharing a key, is E3b and `invalid_request`.
      oneOf:
        - $ref: '#/components/schemas/ReferringJoin'
        - $ref: '#/components/schemas/ReferencedJoin'
    RelationField:
      type: string
      description: A path in a related document, `id`, `created_at` or `updated_at`.
      pattern: ^((state|attributes)(\.[^.]+)+|id|created_at|updated_at)$
    BandedField:
      type: object
      description: |
        Entities, E3a (§6.5.2). A number rendered as its band rather than its
        value, in any relation. A number renders as the label whose position
        is how many cut points are at or below it: with `bands: [0.3, 0.7]`,
        0.29 is `labels[0]`, 0.3 is `labels[1]` and 0.7 or more `labels[2]`.
        A value that is not a number renders unchanged, and a missing one is
        left out. Only a move to another band changes the context, so a move
        inside one neither fans out nor costs an evaluation. `bands` must be
        strictly increasing and `labels` must have exactly one more entry;
        the server refuses anything else with `invalid_request`.
      additionalProperties: false
      required:
        - path
        - bands
        - labels
      properties:
        path:
          type: string
          description: A `state` or `attributes` path.
          pattern: ^(state|attributes)(\.[^.]+)+$
        bands:
          type: array
          description: Cut points, strictly increasing.
          minItems: 1
          maxItems: 9
          items:
            type: number
        labels:
          type: array
          description: One label per band, lowest first, so one more than `bands`.
          minItems: 2
          maxItems: 10
          items:
            type: string
            minLength: 1
            maxLength: 64
    Aggregate:
      type: object
      description: |
        Numbers over the relation's documents, after `match`, `window` and
        `last_n`, rendered as keys of its `related.<name>` entry, such as
        `count` and `sum(state.amount)`. At most 8 paths in total. `sum`,
        `min` and `max` skip values that are not numbers; `sum` of nothing
        is 0, and `min` and `max` of nothing are null. `latest` is the value
        in the newest document that has one, of any JSON type.
      additionalProperties: false
      minProperties: 1
      properties:
        count:
          const: true
          description: How many documents the relation selected.
        sum:
          $ref: '#/components/schemas/AggregatePaths'
        min:
          $ref: '#/components/schemas/AggregatePaths'
        max:
          $ref: '#/components/schemas/AggregatePaths'
        latest:
          $ref: '#/components/schemas/AggregatePaths'
    AttributeFilterValue:
      type:
        - string
        - number
        - boolean
    ReferringJoin:
      type: object
      description: |
        Entities, E1 (§6.5.2). The documents that point at the judged one: a
        related document belongs to the judged document whose `id` equals its
        `theirs` attribute.
      additionalProperties: false
      required:
        - theirs
        - mine
      properties:
        theirs:
          type: string
          description: >-
            The related document's attribute that holds the judged document's
            id, such as `attributes.parent_id`.
          pattern: ^attributes\.[A-Za-z0-9_-]+$
        mine:
          const: id
    ReferencedJoin:
      type: object
      description: |
        Entities, E3a (§6.5.2). The one document the judged document points
        at, its referenced document: the document whose `id` equals the
        judged document's `mine` attribute. A change to what the relation
        renders of it re-judges the judged documents that point at it and are
        inside `freshness.fanout.scope`.
      additionalProperties: false
      required:
        - theirs
        - mine
      properties:
        theirs:
          const: id
        mine:
          type: string
          description: >-
            The judged document's attribute that holds the referenced document's
            id, such as `attributes.group_id`.
          pattern: ^attributes\.[A-Za-z0-9_-]+$
    AggregatePaths:
      type: array
      minItems: 1
      maxItems: 8
      uniqueItems: true
      items:
        type: string
        description: A `state` or `attributes` path. Keys in it cannot contain `(` or `)`.
        pattern: ^(state|attributes)(\.[^.()]+)+$
  responses:
    Unauthorized:
      description: '`unauthorized`: the key is missing, unknown or revoked.'
      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`.

````