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

# List a decision's labeled cases

> Reads only. The decision's labeled cases in the key's environment, newest label first: the cases a preview replays, one per item group, each with its `evaluation_id`, label (`expected`) and where it came from (`label_source`, `consensus`, `feedback_source`), its split, the version it ran under and what it gave then, the `expected_answer` corrections by question hash, and the reasons people wrote. Evaluations with feedback that are not cases are counted in `excluded`, by reason. Filters: `outcomes` (comma-separated, no spaces, or a JSON array of strings for names that contain a comma; a case whose label is another outcome is excluded as `outcome_not_in_result`, as a preview excludes it). A preview over versions that produce those outcomes replays the newest 500 of that list; it may also keep an evaluation stored before attribute inputs were kept, which this list counts as `attribute_inputs_unavailable`, when its versions leave that attribute's default unchanged. `structure_hash` (the version it ran under) and `since` (inclusive) and `until` (exclusive) on when the evaluation ran choose which evaluations count, before one case per item group is kept, so a case labeled under an older version is listed for that version even when a newer evaluation of the item exists, and `excluded` counts only those evaluations. `label_source` then narrows the cases; `total` counts the cases after every filter. Content is left out unless `include=content`, which caps a page at 50 cases (200 without). Pass next_cursor as cursor, with the same filters, while has_more is true. A case that gets newer feedback while you page moves ahead of the cursor: list again from the start to see relabeled cases.



## OpenAPI

````yaml /openapi.json get /v1/decisions/{decision_id}/cases
openapi: 3.1.0
info:
  title: Moonbounce Decisions API
  version: 0.0.0
  description: >-
    Moonbounce decisions: evaluate an item's state against a decision structure
    (System One questions, attributes you supply and aggregations over both),
    record feedback and import labeled examples, review a ranked queue, and
    improve the structure through suggestions that ship as code diffs, each with
    a preview (backtest) and an evidence label.


    **Authentication.** Send an API key as `Authorization: Bearer <key>` on
    every operation except `GET /health` and `POST /v1/structures/hash`. Call
    the API from a server, never a browser: a key must not reach one, and the
    API sends no CORS headers. A key belongs to one organization and one
    environment: production, or test for a key with the `env:test` permission.
    Test traffic never counts as production traffic.


    **Requests.** JSON bodies (`Content-Type: application/json`) of at most 1
    MB, parsed strictly: duplicate keys, lone surrogates, integers outside
    ±(2^53 - 1), `__proto__` keys, U+0000 and nesting deeper than 64 are a 400.


    **Retries.** Send an `Idempotency-Key` on every POST under /v1 that takes
    one (all but `POST /v1/structures/hash` and `POST /v1/review/items/fill`,
    whose retry is another fill within the day's budget). Keep it for the
    request's retries. The same key with the same request returns the first
    stored result, marked `Idempotent-Replayed: true`, for 24 hours (410 if that
    result was since deleted); with another request it is 422
    IDEMPOTENCY_KEY_REUSED. Keys are scoped to the organization and environment
    across every operation, so use a fresh key per request. A request that
    failed before its result was stored runs again when retried. 429 and 503
    under /v1 may carry `Retry-After` (seconds); a daily QUOTA_EXCEEDED cap
    instead names its reset time.


    **Errors.** Every error under /v1 is `{"error": {"type", "message",
    "reason"?, "param"?, "details"?}}` (ErrorBody); `GET /health` answers its
    own shape. Every response carries a `Request-Id` header. Rate limits apply
    per key, and per client IP for requests without a valid key; a 429
    RATE_LIMITED carries `Retry-After`.
servers:
  - url: https://api.moonbounce.ai
    description: Production
security: []
paths:
  /v1/decisions/{decision_id}/cases:
    get:
      tags:
        - feedback
      summary: List a decision's labeled cases
      description: >-
        Reads only. The decision's labeled cases in the key's environment,
        newest label first: the cases a preview replays, one per item group,
        each with its `evaluation_id`, label (`expected`) and where it came from
        (`label_source`, `consensus`, `feedback_source`), its split, the version
        it ran under and what it gave then, the `expected_answer` corrections by
        question hash, and the reasons people wrote. Evaluations with feedback
        that are not cases are counted in `excluded`, by reason. Filters:
        `outcomes` (comma-separated, no spaces, or a JSON array of strings for
        names that contain a comma; a case whose label is another outcome is
        excluded as `outcome_not_in_result`, as a preview excludes it). A
        preview over versions that produce those outcomes replays the newest 500
        of that list; it may also keep an evaluation stored before attribute
        inputs were kept, which this list counts as
        `attribute_inputs_unavailable`, when its versions leave that attribute's
        default unchanged. `structure_hash` (the version it ran under) and
        `since` (inclusive) and `until` (exclusive) on when the evaluation ran
        choose which evaluations count, before one case per item group is kept,
        so a case labeled under an older version is listed for that version even
        when a newer evaluation of the item exists, and `excluded` counts only
        those evaluations. `label_source` then narrows the cases; `total` counts
        the cases after every filter. Content is left out unless
        `include=content`, which caps a page at 50 cases (200 without). Pass
        next_cursor as cursor, with the same filters, while has_more is true. A
        case that gets newer feedback while you page moves ahead of the cursor:
        list again from the start to see relabeled cases.
      operationId: listCases
      parameters:
        - schema:
            $ref: '#/components/schemas/DecisionId'
          required: true
          name: decision_id
          in: path
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
            minLength: 1
            maxLength: 1024
          required: false
          name: cursor
          in: query
        - schema:
            type: string
            minLength: 1
            maxLength: 4096
            description: >-
              Outcome names, comma-separated (no spaces) or as a JSON array
              (`["refund, partial","deny"]`). Only cases labeled one of them are
              listed.
          required: false
          description: >-
            Outcome names, comma-separated (no spaces) or as a JSON array
            (`["refund, partial","deny"]`). Only cases labeled one of them are
            listed.
          name: outcomes
          in: query
        - schema:
            $ref: '#/components/schemas/StructureHash'
          required: false
          name: structure_hash
          in: query
        - schema:
            $ref: '#/components/schemas/LabelSource'
          required: false
          description: >-
            Where the label came from: `human`, `synthetic` (an agent made it)
            or `unknown`. Only `human` counts toward the no-new-severe-mistake
            rule.
          name: label_source
          in: query
        - schema:
            $ref: '#/components/schemas/Timestamp'
          required: false
          name: since
          in: query
        - schema:
            $ref: '#/components/schemas/Timestamp'
          required: false
          name: until
          in: query
        - schema:
            type: string
            enum:
              - content
          required: false
          name: include
          in: query
      responses:
        '200':
          description: A page of cases
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CasePage'
        '400':
          description: 'Invalid request: `param` names the field at fault when one applies'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '401':
          description: Missing or invalid API key (reason KEY_INVALID)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '403':
          description: The key may not do this
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '429':
          description: >-
            RATE_LIMITED: retry after Retry-After seconds; QUOTA_EXCEEDED:
            details.reset_at gives the daily reset time (no Retry-After)
          headers:
            Retry-After:
              schema:
                type: string
                description: Seconds to wait before retrying, when waiting helps.
              required: false
              description: Seconds to wait before retrying, when waiting helps.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
        '503':
          description: >-
            Temporarily unavailable, with Retry-After (for example reason
            AUTH_UNAVAILABLE, ENGINE_UNAVAILABLE or STORE_UNAVAILABLE): retry
            with the same Idempotency-Key
          headers:
            Retry-After:
              schema:
                type: string
                description: Seconds to wait before retrying, when waiting helps.
              required: true
              description: Seconds to wait before retrying, when waiting helps.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security:
        - bearerAuth:
            - decisions:develop
components:
  schemas:
    DecisionId:
      type: string
      pattern: ^[a-z][a-z0-9_.-]{0,127}$
    StructureHash:
      type: string
      pattern: ^sha256:[0-9a-f]{64}$
    LabelSource:
      type: string
      enum:
        - human
        - synthetic
        - unknown
      description: >-
        Where the label came from: `human`, `synthetic` (an agent made it) or
        `unknown`. Only `human` counts toward the no-new-severe-mistake rule.
    Timestamp:
      type: string
      format: date-time
    CasePage:
      type: object
      properties:
        environment:
          $ref: '#/components/schemas/Environment'
        decision_id:
          $ref: '#/components/schemas/DecisionIdOutput'
        cases:
          type: array
          items:
            $ref: '#/components/schemas/Case'
        total:
          type: integer
          minimum: 0
          description: Cases that match the filters, across every page.
        excluded:
          $ref: '#/components/schemas/CaseExcluded'
        next_cursor:
          type:
            - string
            - 'null'
        has_more:
          type: boolean
      required:
        - environment
        - decision_id
        - cases
        - total
        - excluded
        - next_cursor
        - has_more
    ErrorBody:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              $ref: '#/components/schemas/ErrorType'
            reason:
              type: string
              pattern: ^[A-Z][A-Z0-9_]+$
              description: >-
                Set where a caller can act on it, one of the reasons in the
                ErrorReason schema. New reasons may be added: treat an unknown
                one by the status and `type`.
            message:
              type: string
              description: For people; don't parse it.
            param:
              type: string
              description: >-
                The request field at fault, as a dotted path
                (`attribute_values.region`, `claims.1.value`).
            details:
              type: object
              properties:
                issues:
                  type: array
                  items:
                    $ref: '#/components/schemas/ErrorIssue'
              additionalProperties: {}
          required:
            - type
            - message
          additionalProperties: true
          x-moonbounce-sdk-known-fields: true
      required:
        - error
      additionalProperties: true
      x-moonbounce-sdk-known-fields: true
    Environment:
      type: string
      enum:
        - production
        - test
      description: >-
        The environment of the key that made the call: `production` or `test`.
        Evaluations, feedback, reviews and suggestions are separate per
        environment; registered structures are shared.
    DecisionIdOutput:
      type: string
      pattern: ^[a-z][a-z0-9_.-]{0,127}$
    Case:
      type: object
      properties:
        evaluation_id:
          type: string
          pattern: >-
            ^evl_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
          description: The evaluation the label is about (getEvaluation reads it).
        item_id:
          type: string
        assignment_mode:
          type: string
          enum:
            - primary
            - example
        expected:
          type: string
          minLength: 1
          maxLength: 200
          description: 'The label: the outcome the feedback settled on.'
        label_source:
          $ref: '#/components/schemas/LabelSourceOutput'
        consensus:
          $ref: '#/components/schemas/CaseConsensus'
        feedback_source:
          $ref: '#/components/schemas/DecidingFeedbackSource'
        split:
          $ref: '#/components/schemas/Split'
        ran:
          type: object
          properties:
            structure_hash:
              $ref: '#/components/schemas/StructureHashOutput'
            engine_profile:
              type: string
              description: >-
                The engine and model each question ran on, as an evaluate run
                reports it.
            status:
              type: string
              enum:
                - computed
                - decided
                - abstained
              description: The evaluation's status then.
            outcome:
              type:
                - string
                - 'null'
              minLength: 1
              maxLength: 200
              description: The outcome it gave then; null when it gave none.
          required:
            - structure_hash
            - engine_profile
            - status
            - outcome
          description: >-
            The evaluation the label is about: the version it ran under and what
            it gave.
        answer_corrections:
          type: array
          items:
            type: object
            properties:
              question_hash:
                type: string
              questions:
                type: array
                items:
                  type: string
                description: The question's names in the structure the case ran under.
              expected:
                type: boolean
                description: The answer the feedback says the question should have given.
            required:
              - question_hash
              - questions
              - expected
          description: >-
            The `expected_answer` corrections in the case's feedback (owner,
            reviewers or an imported example), by question hash, resolved as
            previews read them.
        reasons:
          type: array
          items:
            type: object
            properties:
              feedback_id:
                $ref: '#/components/schemas/FbkIdOutput'
              text:
                type: string
            required:
              - feedback_id
              - text
          description: >-
            What the feedback's authors wrote (owner, reviewers or an imported
            example), oldest first: often the best clue for a rewrite.
        feedback_ids:
          type: array
          items:
            $ref: '#/components/schemas/FbkIdOutput'
          description: The live feedback on the case, oldest first.
        deciding_feedback_id:
          type: string
          pattern: >-
            ^fbk_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
          description: The feedback whose claims decided the label (getFeedback reads it).
        created_at:
          type: string
          format: date-time
          description: When the evaluation ran.
        labeled_at:
          type: string
          format: date-time
          description: >-
            When the deciding feedback was sent. Cases are listed newest label
            first.
        content:
          type: object
          properties:
            state: {}
            attribute_values:
              $ref: '#/components/schemas/AttributeValuesOutput'
          description: >-
            Only with `include=content`: the stored state and the attribute
            values the caller supplied (defaults not applied).
      required:
        - evaluation_id
        - item_id
        - assignment_mode
        - expected
        - label_source
        - consensus
        - feedback_source
        - split
        - ran
        - answer_corrections
        - reasons
        - feedback_ids
        - deciding_feedback_id
        - created_at
        - labeled_at
    CaseExcluded:
      type: object
      properties:
        withdrawn:
          type: integer
          minimum: 1
        retired:
          type: integer
          minimum: 1
        excluded:
          type: integer
          minimum: 1
        contested:
          type: integer
          minimum: 1
        no_consensus:
          type: integer
          minimum: 1
        no_outcome:
          type: integer
          minimum: 1
        outcome_not_in_result:
          type: integer
          minimum: 1
        no_deciding_ballot:
          type: integer
          minimum: 1
        attribute_inputs_unavailable:
          type: integer
          minimum: 1
        no_split:
          type: integer
          minimum: 1
        duplicate_group:
          type: integer
          minimum: 1
      description: >-
        Evaluations with feedback that are not cases, by reason: `withdrawn`
        (all feedback withdrawn), `retired` (feedback older than the last policy
        change), `excluded` (flagged input_broken), `contested` (reviewers
        disagree), `no_consensus` (no feedback that decides an outcome),
        `no_outcome` (feedback rules outcomes out without naming one),
        `outcome_not_in_result` (expected outcome not in `outcomes`),
        `no_deciding_ballot`, `attribute_inputs_unavailable` (stored before
        attribute inputs were kept, with a default that can't be read back),
        `no_split` (not yet in a split group), `duplicate_group` (another
        evaluation of the same item group counts instead).
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication
        - permission_denied
        - not_found
        - conflict
        - rate_limited
        - engine_failed
        - unavailable
        - internal
    ErrorIssue:
      type: object
      properties:
        param:
          type: string
        code:
          type: string
          pattern: ^[A-Z][A-Z0-9_]+$
          description: >-
            Stable, extensible issue code; unknown codes still have a parameter
            and human-readable message.
        message:
          type: string
      required:
        - param
        - code
        - message
      additionalProperties: true
      x-moonbounce-sdk-known-fields: true
    LabelSourceOutput:
      type: string
      enum:
        - human
        - synthetic
        - unknown
      description: >-
        Where the label came from: `human`, `synthetic` (an agent made it) or
        `unknown`. Only `human` counts toward the no-new-severe-mistake rule.
    CaseConsensus:
      type: string
      enum:
        - owner
        - majority
        - example
      description: >-
        How the label was decided: the owner's feedback, a reviewer majority, or
        an imported example's label.
    DecidingFeedbackSource:
      type: string
      enum:
        - owner
        - reviewer
        - import
        - synthetic_review
      description: >-
        The source of the feedback that decided the label (`import` is an
        imported example).
    Split:
      type: string
      enum:
        - example
        - train
    StructureHashOutput:
      type: string
      pattern: ^sha256:[0-9a-f]{64}$
    FbkIdOutput:
      type: string
      pattern: >-
        ^fbk_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
    AttributeValuesOutput:
      type: object
      additionalProperties:
        anyOf:
          - type: string
            maxLength: 200
          - type: number
          - type: boolean
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key, sent as `Authorization: Bearer <key>`. Each operation lists
        the scope its key needs: `decisions:evaluate` (evaluate and read
        evaluations), `decisions:feedback` (your app's feedback) or
        `decisions:develop` (everything else, including owner feedback and the
        review queue). An operation listing no scope takes any scoped key. A key
        with no scope, or without the operation's, gets 403 INSUFFICIENT_SCOPE.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.