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

# Hash a decision spec

> Returns the structure hash, every node's hash and the default-weights hash of a spec, without registering it or touching data. Public: needs no API key. Key order, whitespace around a string, Unicode normalization (NFC), the order of `inputs` and combine `terms`, defaults spelled out (`effect: "raises"`, `prior: "mean"`, empty `criteria`) and `meta` do not change the hashes; any other edit to a prompt, guidance or target text does.



## OpenAPI

````yaml /openapi.json post /v1/specs/hash
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/specs/hash:
    post:
      tags:
        - specs
      summary: Hash a decision spec
      description: >-
        Returns the structure hash, every node's hash and the default-weights
        hash of a spec, without registering it or touching data. Public: needs
        no API key. Key order, whitespace around a string, Unicode normalization
        (NFC), the order of `inputs` and combine `terms`, defaults spelled out
        (`effect: "raises"`, `prior: "mean"`, empty `criteria`) and `meta` do
        not change the hashes; any other edit to a prompt, guidance or target
        text does.
      operationId: hashSpec
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StructureRegistration'
      responses:
        '200':
          description: The spec's hashes
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SpecHashResponse'
        '400':
          description: 'Invalid request: `param` names the field at fault when one applies'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
      security: []
components:
  schemas:
    StructureRegistration:
      type: object
      properties:
        spec:
          $ref: '#/components/schemas/Spec'
      required:
        - spec
      additionalProperties: false
    SpecHashResponse:
      type: object
      properties:
        structure:
          $ref: '#/components/schemas/VersionHash'
        nodes:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/VersionHash'
          description: >-
            Each of the spec's nodes, by name, mapped to that node's hash (not
            its definition).
        default_weights:
          $ref: '#/components/schemas/VersionHash'
      required:
        - structure
        - nodes
        - default_weights
      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
    Spec:
      type: object
      properties:
        format:
          type: string
          enum:
            - moonbounce.spec/0
        guidance:
          type: string
          minLength: 1
          maxLength: 20000
        nodes:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/SpecNode'
          description: >-
            The spec's named nodes, 1 to 64: boolean features and the
            aggregators that read them. Every reference (`output`, a combine
            term's `node`, a calibrate's `node`) names a node in this map, with
            no cycles.
        output:
          $ref: '#/components/schemas/Name'
        target:
          type: string
          minLength: 1
          maxLength: 4000
          description: >-
            The yes/no statement the output's score is the probability of.
            Required when `output` is a combine or calibrate node, optional on a
            boolean output. Feedback `target` claims need it.
        meta:
          $ref: '#/components/schemas/Meta'
      required:
        - format
        - nodes
        - output
      additionalProperties: false
    VersionHash:
      type: string
      pattern: ^sha256:[0-9a-f]{64}$
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication
        - permission_denied
        - not_found
        - conflict
        - rate_limited
        - engine_failed
        - unavailable
        - internal
    SpecNode:
      oneOf:
        - $ref: '#/components/schemas/BooleanFeature'
        - $ref: '#/components/schemas/Combine'
        - $ref: '#/components/schemas/Calibrate'
      discriminator:
        propertyName: type
        mapping:
          boolean: '#/components/schemas/BooleanFeature'
          combine: '#/components/schemas/Combine'
          calibrate: '#/components/schemas/Calibrate'
    Name:
      type: string
      pattern: ^[a-z][a-z0-9_]{0,63}$
    Meta:
      type: object
      properties:
        title:
          type: string
          maxLength: 200
        description:
          type: string
          maxLength: 4000
        owner:
          type: string
          maxLength: 200
        tags:
          type: array
          items:
            type: string
            maxLength: 64
          maxItems: 32
        display:
          type: object
          additionalProperties:
            type: object
            properties:
              text:
                type: string
                minLength: 1
                maxLength: 40
              help:
                type: string
                maxLength: 200
            required:
              - text
            additionalProperties: false
      additionalProperties: false
    BooleanFeature:
      type: object
      properties:
        type:
          type: string
          enum:
            - boolean
        prompt:
          type: string
          minLength: 1
          maxLength: 4000
        guidance:
          type: string
          minLength: 1
          maxLength: 4000
        inputs:
          type: array
          items:
            $ref: '#/components/schemas/Name'
          minItems: 1
          description: >-
            Names of the `subject` parts this feature reads (default: all of
            them); `context` parts are always read. Every name must match a
            subject part's `name`, or the request is a 400 CONTENT_INVALID.
        criteria:
          type: object
          properties:
            'true':
              type: string
              minLength: 1
              maxLength: 4000
            'false':
              type: string
              minLength: 1
              maxLength: 4000
          additionalProperties: false
      required:
        - type
        - prompt
      additionalProperties: false
    Combine:
      type: object
      properties:
        type:
          type: string
          enum:
            - combine
        terms:
          type: array
          items:
            $ref: '#/components/schemas/CombineTerm'
          minItems: 1
          maxItems: 64
        prior:
          type: string
          enum:
            - mean
            - any
          description: >-
            Default combine weights before fitting. mean averages oriented
            inputs; any computes sigmoid(-4 + 8·Σraises - 8·Σlowers), a logistic
            of a signed sum: one strong raise is enough and weak raises add up.
        fixed:
          type: object
          properties:
            link:
              type: string
              enum:
                - identity
                - logistic
              description: >-
                identity: the weighted sum plus bias, clipped to 0..1; logistic:
                the sigmoid of the weighted sum plus bias.
            weights:
              type: object
              additionalProperties:
                type: number
              description: Signed weights per term key (node; options are reserved).
            bias:
              type: number
              description: Offset added to the weighted sum before applying the link.
          required:
            - link
            - weights
            - bias
          additionalProperties: false
          description: >-
            Numbers fixed in code, never overridden by fitted weights. Signed
            weights multiply raw P(yes): raises weights must be >= 0 and lowers
            weights <= 0.
      required:
        - type
        - terms
      additionalProperties: false
      description: >-
        Scores a node from its terms. Before fitting (and without fixed
        numbers), mean averages the oriented inputs, so each of n terms weighs
        1/n and adding a term dilutes the others; any computes sigmoid(-4 +
        8·Σraises - 8·Σlowers): one strong raise is enough, weak raises add up,
        and lowers cancel raises. Fitted or fixed numbers replace the prior.
    Calibrate:
      type: object
      properties:
        type:
          type: string
          enum:
            - calibrate
        node:
          $ref: '#/components/schemas/Name'
      required:
        - type
        - node
      additionalProperties: false
    CombineTerm:
      type: object
      properties:
        node:
          $ref: '#/components/schemas/Name'
        option:
          type: string
          pattern: ^[a-z][a-z0-9_]{0,63}$
          description: >-
            Reserved for choice and scale features, which are not available yet:
            any value is a 400.
        effect:
          type: string
          enum:
            - raises
            - lowers
          default: raises
          description: >-
            raises: a yes pushes the score up; lowers: a yes pushes it down. The
            sign lives here; fixed weights must agree with it.
      required:
        - node
      additionalProperties: false

````

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