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

# Get a feedback submission as stored

> Reads back any feedback submission in the key's environment: one from `POST /v1/feedback`, a seed example's from `POST /v1/decisions/{decision_id}/seeds`, or a review answer. `claims` are in the order and shape they were sent, and `claim_count` says how many there are. `resolved_from_item` says the submission named an item and the server picked the evaluation. `superseded_by` is set when a later submission replaced this one; a replaced submission no longer counts. `supersedes` is the one this replaced. `split` is the side of the training line the item's group is on: `seed` is a starting example, `train` is used for fitting, `holdout` is kept back to test suggestions and never shown to a suggestion generator, and `burned` is a holdout group whose cases were shown in a preview, that was merged with a near-duplicate group, or whose content was later imported as a seed example; it counts as training from then on. It is null when the item has no group yet. Held-out feedback is kept back to test suggestions, so even its author reads only that it was recorded and how many claims it holds: while the group is `holdout` (or the content's text belongs to a held-out group), `withheld` is `holdout` and `claims`, `reason`, `reason_pending` and `unsure` are left out; they come back once the group is burned. A submission whose item has no split yet is withheld the same way, as `unassigned`. `withdrawn_at` marks a claimless withdrawal of the chain; ancestors never revive. On a spot check, `after_reveal` is false on the reviewer's blind answer and true on a later change of it; it is left out while `withheld` is set. `reason_pending` on a superseded submission means its reason was never added before the answer was replaced: read the chain head. `supersedes` and `superseded_by` only ever name a submission on the same evaluation. 404 for an unknown id, another organization's or environment's submission, or one whose evaluation was deleted.



## OpenAPI

````yaml /openapi.json get /v1/feedback/{feedback_id}
openapi: 3.1.0
info:
  title: Moonbounce Decisions API
  version: 0.0.0
  description: >-
    Moonbounce decisions: evaluate items against a decision spec (features
    combined by aggregators), record feedback and seed examples, review a ranked
    queue, and improve the spec 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/specs/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/specs/hash`). 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, counted per Cloudflare location.
servers:
  - url: https://api.moonbounce.ai
    description: Production
security: []
paths:
  /v1/feedback/{feedback_id}:
    get:
      tags:
        - feedback
      summary: Get a feedback submission as stored
      description: >-
        Reads back any feedback submission in the key's environment: one from
        `POST /v1/feedback`, a seed example's from `POST
        /v1/decisions/{decision_id}/seeds`, or a review answer. `claims` are in
        the order and shape they were sent, and `claim_count` says how many
        there are. `resolved_from_item` says the submission named an item and
        the server picked the evaluation. `superseded_by` is set when a later
        submission replaced this one; a replaced submission no longer counts.
        `supersedes` is the one this replaced. `split` is the side of the
        training line the item's group is on: `seed` is a starting example,
        `train` is used for fitting, `holdout` is kept back to test suggestions
        and never shown to a suggestion generator, and `burned` is a holdout
        group whose cases were shown in a preview, that was merged with a
        near-duplicate group, or whose content was later imported as a seed
        example; it counts as training from then on. It is null when the item
        has no group yet. Held-out feedback is kept back to test suggestions, so
        even its author reads only that it was recorded and how many claims it
        holds: while the group is `holdout` (or the content's text belongs to a
        held-out group), `withheld` is `holdout` and `claims`, `reason`,
        `reason_pending` and `unsure` are left out; they come back once the
        group is burned. A submission whose item has no split yet is withheld
        the same way, as `unassigned`. `withdrawn_at` marks a claimless
        withdrawal of the chain; ancestors never revive. On a spot check,
        `after_reveal` is false on the reviewer's blind answer and true on a
        later change of it; it is left out while `withheld` is set.
        `reason_pending` on a superseded submission means its reason was never
        added before the answer was replaced: read the chain head. `supersedes`
        and `superseded_by` only ever name a submission on the same evaluation.
        404 for an unknown id, another organization's or environment's
        submission, or one whose evaluation was deleted.
      operationId: getFeedback
      parameters:
        - schema:
            $ref: '#/components/schemas/FbkId'
          required: true
          name: feedback_id
          in: path
      responses:
        '200':
          description: The submission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FeedbackRecord'
        '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'
        '404':
          description: Not found, or not in this key's organization and environment
          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), or
            details.too_large asks for a smaller request
          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:feedback
        - bearerAuth:
            - decisions:develop
components:
  schemas:
    FbkId:
      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}$
    FeedbackRecord:
      type: object
      properties:
        environment:
          $ref: '#/components/schemas/Environment'
        id:
          $ref: '#/components/schemas/FbkId'
        decision_id:
          $ref: '#/components/schemas/DecisionId'
        evaluation_id:
          $ref: '#/components/schemas/EvlId'
        item_id:
          type:
            - string
            - 'null'
        resolved_from_item:
          type: boolean
          description: >-
            True when the submission named an item and the server resolved it to
            this evaluation.
        source:
          $ref: '#/components/schemas/FeedbackSource'
        channel:
          type: string
          enum:
            - slack
            - web
            - api
            - mcp
            - import
          description: The surface the submission came through, stamped by the server.
        actor:
          type: string
          description: >-
            Who submitted it, as recorded (an `ext:` prefix marks an actor your
            key named).
        reason:
          type: string
          description: Why, as sent. Left out while `withheld` is set.
        reason_pending:
          type: boolean
          description: >-
            True when a reason was promised and has not arrived yet. On a
            superseded submission (`superseded_by` set) it means the reason was
            never added before the answer was replaced, and none will be: read
            the chain head. Left out while `withheld` is set.
        unsure:
          type: boolean
          description: Left out while `withheld` is set.
        withdrawn_at:
          type: string
          format: date-time
          description: >-
            When this claimless submission withdrew its chain. Resolve chain
            heads before excluding withdrawn chains; ancestors never revive.
        after_reveal:
          type: boolean
          description: >-
            Spot checks only. `false` on the reviewer's first answer, given
            blind; `true` on an answer that changed it after Moonbounce's call
            was revealed. Accuracy is measured on the blind answer. Omitted on
            other items, other sources, withdrawal events and withheld rows.
        supersedes:
          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 submission this one replaces.
        superseded_by:
          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: >-
            Set when a later submission replaced this one. This one no longer
            counts.
        claims:
          type: array
          items:
            $ref: '#/components/schemas/Claim'
          description: >-
            The claims, in the order and shape they were sent. Left out while
            `withheld` is set.
        claim_count:
          type: integer
          minimum: 0
          description: How many claims the submission holds.
        withheld:
          type: string
          enum:
            - holdout
            - unassigned
          description: >-
            Set when the judgment (claims, reason, reason_pending, unsure) is
            not returned, even to its author, by the same rules as the feedback
            export. `holdout`: the item's group is held out, or the content's
            text belongs to a held-out group; the judgment is kept back to test
            suggestions and is returned once the group is burned. `unassigned`:
            the item has no split yet.
        split:
          type:
            - string
            - 'null'
          enum:
            - seed
            - train
            - holdout
            - burned
            - null
          description: >-
            Which side of the training line this item's group is on: `seed` (a
            starting example, used for fitting), `train` (used for fitting),
            `holdout` (kept back to test suggestions, never shown to a
            suggestion generator) or `burned` (a holdout group whose cases were
            shown in a preview, that was merged with a near-duplicate group, or
            whose content was later imported as a seed example; it counts as
            training). Null when the item has no group yet.
        created_at:
          $ref: '#/components/schemas/Timestamp'
      required:
        - environment
        - id
        - decision_id
        - evaluation_id
        - item_id
        - resolved_from_item
        - source
        - channel
        - actor
        - claim_count
        - split
        - created_at
      additionalProperties: false
    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 (`subject.0.text`,
                `claims.1.value`).
            details:
              type: object
              additionalProperties: {}
          required:
            - type
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    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.
    DecisionId:
      type: string
      pattern: ^[a-z][a-z0-9_.-]{0,127}$
    EvlId:
      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}$
    FeedbackSource:
      type: string
      enum:
        - app_native
        - app_resolution
        - reviewer
        - owner
        - import
        - synthetic_review
    Claim:
      oneOf:
        - type: object
          properties:
            kind:
              type: string
              enum:
                - target
            value:
              type: boolean
              description: Whether the spec's target statement is true of this item.
          required:
            - kind
            - value
          additionalProperties: false
          description: >-
            Whether the target statement is true. Only for specs that declare a
            target.
        - type: object
          properties:
            kind:
              type: string
              enum:
                - outcome
            value:
              type: string
              minLength: 1
              maxLength: 64
              description: >-
                The right outcome: one of this evaluation's outcomes (`below` or
                a cut's outcome); an `abstain` name counts only where it reuses
                one of them.
          required:
            - kind
            - value
          additionalProperties: false
          description: >-
            The outcome this item should have had. On a cut score, the lowest
            outcome also says the target is false and the highest says it is
            true; middle outcomes say nothing about the target.
        - type: object
          properties:
            kind:
              type: string
              enum:
                - verdict
            value:
              type: string
              enum:
                - approve
                - reject
              description: 'approve: the shown outcome was right. reject: it was wrong.'
          required:
            - kind
            - value
          additionalProperties: false
          description: >-
            Approve or reject the outcome that was shown. Needs
            `about.evaluation_id`, and an evaluation whose outcome was shown to
            someone: primary traffic that decided (it has a score). An
            evaluation that abstained has only a fallback outcome, whatever it
            is called.
        - type: object
          properties:
            kind:
              type: string
              enum:
                - feature
            feature:
              type: string
              minLength: 1
              maxLength: 64
              description: A boolean feature of the evaluation's spec.
            value:
              type: boolean
              description: What the feature's answer should have been.
          required:
            - kind
            - feature
            - value
          additionalProperties: false
          description: >-
            The expected answer of one boolean feature. It is stored against
            that feature's prompt as it was judged, so a reworded prompt does
            not inherit it.
        - type: object
          properties:
            kind:
              type: string
              enum:
                - input_broken
            problem:
              type: string
              enum:
                - truncated
                - wrong_language
                - bad_extraction
                - unreadable
                - other
          required:
            - kind
            - problem
          additionalProperties: false
          description: >-
            The content could not be judged. The evaluation is kept out of fits
            and previews.
        - type: object
          properties:
            kind:
              type: string
              enum:
                - action
            value:
              type: string
              minLength: 1
              maxLength: 128
              description: >-
                What your app did, in your own words (for example
                `auto_approved`).
            logic_version:
              type: string
              maxLength: 128
              description: Which version of your own logic acted.
          required:
            - kind
            - value
          additionalProperties: false
          description: >-
            What your app did with the outcome. Observed behavior, not a
            statement of what is true.
    Timestamp:
      type: string
      format: date-time
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication
        - permission_denied
        - not_found
        - conflict
        - rate_limited
        - engine_failed
        - unavailable
        - internal
  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.