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

# Consume AI usage

> Record what a customer consumed and charge it against their balance. Hyperline prices the usage itself and applies the policy markup — an amount sent by the caller is never read. The call writes one append-only ledger entry and updates the customer's balance atomically. Replaying an `idempotency_key` returns the original result unchanged.

How it charges depends on the customer's mode. In `wallet` mode the usage is priced against the workspace's resolved rates in the wallet's minor units, and the wallet ledger is not touched — a background settlement rolls entries up separately. In `credits` mode it is priced against the policy's credit rate card and the customer's credit balance is decremented for real, in the same transaction, with no settlement afterwards; a customer without enough credits is refused with a 402 and nothing is deducted, so a call is never partially charged.

In `windows` mode the usage is weighted into units and metered against every one of the customer's overlapping rolling allowances — a 5h and a 7d window, say. Each window instance is anchored at the first call after the previous one expired and runs for exactly its duration, so `resets_at` is a real instant rather than a moving average. Every window meters every call, and a call that does not fit in *all* of them is refused whole with a 402 carrying `meters` and the soonest `resets_at`: no window is incremented, so a refused call leaves no trace.



## OpenAPI

````yaml post /v1/ai/billing/consume
openapi: 3.1.0
info:
  title: Hyperline Ingest API
  version: 0.0.0
servers:
  - url: https://ingest.hyperline.co
  - url: https://sandbox.ingest.hyperline.co
security: []
paths:
  /v1/ai/billing/consume:
    post:
      tags:
        - AI
      summary: Consume AI usage
      description: >-
        Record what a customer consumed and charge it against their balance.
        Hyperline prices the usage itself and applies the policy markup — an
        amount sent by the caller is never read. The call writes one append-only
        ledger entry and updates the customer's balance atomically. Replaying an
        `idempotency_key` returns the original result unchanged.


        How it charges depends on the customer's mode. In `wallet` mode the
        usage is priced against the workspace's resolved rates in the wallet's
        minor units, and the wallet ledger is not touched — a background
        settlement rolls entries up separately. In `credits` mode it is priced
        against the policy's credit rate card and the customer's credit balance
        is decremented for real, in the same transaction, with no settlement
        afterwards; a customer without enough credits is refused with a 402 and
        nothing is deducted, so a call is never partially charged.


        In `windows` mode the usage is weighted into units and metered against
        every one of the customer's overlapping rolling allowances — a 5h and a
        7d window, say. Each window instance is anchored at the first call after
        the previous one expired and runs for exactly its duration, so
        `resets_at` is a real instant rather than a moving average. Every window
        meters every call, and a call that does not fit in *all* of them is
        refused whole with a 402 carrying `meters` and the soonest `resets_at`:
        no window is incremented, so a refused call leaves no trace.
      operationId: consumeAiBilling
      requestBody:
        description: Consumption payload.
        content:
          application/json:
            schema:
              type: object
              properties:
                customer:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: >-
                    Customer to bill — the external id your application knows
                    them by, or a Hyperline `cus_…` id. Resolved exactly the way
                    AI telemetry resolves it.
                  example: acme-corp
                agent:
                  type: string
                  minLength: 1
                  maxLength: 128
                  description: >-
                    The agent making the call, as `run({ agent })` names it.
                    Optional, and absent means the customer's shared pool —
                    which is what every call did before per-agent billing
                    existed. Naming an agent only changes anything once an
                    operator has given that agent a billing policy of its own;
                    until then it resolves to the same shared pool and the
                    response says so with `agent: null`.
                  example: invoice-copilot
                usage:
                  type: object
                  properties:
                    llm_calls:
                      type: array
                      items:
                        type: object
                        properties:
                          provider:
                            type: string
                            minLength: 1
                            maxLength: 64
                            description: The model's provider, e.g. `anthropic`.
                            example: anthropic
                          model:
                            type: string
                            minLength: 1
                            maxLength: 128
                            description: The model invoked, e.g. `claude-sonnet-5`.
                            example: claude-sonnet-5
                          input_tokens:
                            type: integer
                            minimum: 0
                            description: Uncached input tokens.
                            example: 12400
                          output_tokens:
                            type: integer
                            minimum: 0
                            description: Output tokens.
                            example: 1300
                          extra:
                            type:
                              - object
                              - 'null'
                            additionalProperties:
                              type: number
                              minimum: 0
                              maximum: 1000000000000
                            description: >-
                              Cost dimensions beyond the two token classes —
                              cached input tokens, web searches, whatever the
                              resolved rate knows how to bill. Keys must match
                              `[a-z0-9_.]{1,64}`, values must be finite and at
                              most 1e12, at most 20 keys.
                            example:
                              cached_input: 9000
                        required:
                          - provider
                          - model
                          - input_tokens
                          - output_tokens
                      maxItems: 500
                      description: Model invocations to price.
                    items:
                      type: array
                      items:
                        type: object
                        properties:
                          vendor:
                            type: string
                            minLength: 1
                            maxLength: 64
                            description: The vendor the item was bought from, e.g. `exa`.
                            example: exa
                          item:
                            type: string
                            minLength: 1
                            maxLength: 128
                            description: The item purchased, e.g. `search`.
                            example: search
                          quantity:
                            type: number
                            minimum: 0
                            description: How many, in `unit`.
                            example: 3
                          unit:
                            type: string
                            minLength: 1
                            maxLength: 64
                            description: The dimension `quantity` is counted in.
                            example: units
                        required:
                          - vendor
                          - item
                          - quantity
                          - unit
                      maxItems: 500
                      description: >-
                        Non-LLM cost items to price — a search API call, a
                        vector query.
                  description: >-
                    What was consumed. Priced server-side against your resolved
                    rates — an amount sent by the client is never trusted, and
                    never read.
                  example:
                    llm_calls:
                      - provider: anthropic
                        model: claude-sonnet-5
                        input_tokens: 12400
                        output_tokens: 1300
                        extra:
                          cached_input: 9000
                    items:
                      - vendor: exa
                        item: search
                        quantity: 3
                        unit: units
                idempotency_key:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: >-
                    Replay key. Replaying it returns the original amount and
                    breakdown unchanged, with a freshly read balance.
                  example: cns_9f2c1ab4e77d3105bb0a
              required:
                - customer
                - usage
                - idempotency_key
      responses:
        '200':
          description: Consumption recorded.
          content:
            application/json:
              schema:
                type: object
                properties:
                  agent:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The billing scope that answered: the agent's own slug when
                      it has a policy of its own, and null when the customer's
                      shared pool answered — including when an agent was named
                      but has no policy of its own.
                    example: invoice-copilot
                  amount:
                    type: string
                    description: >-
                      Total charged, at full precision — a sub-cent model call
                      is not rounded away, and neither is a fractional credit.
                    example: '4.182'
                  denomination:
                    type: string
                    enum:
                      - minor_units
                      - credits
                      - units
                    description: >-
                      What `amount` and every breakdown line count: the wallet's
                      minor units, credit units, or weighted allowance units.
                    example: minor_units
                  breakdown:
                    type: array
                    items:
                      type: object
                      properties:
                        kind:
                          type: string
                          enum:
                            - llm_call
                            - item
                            - markup
                          description: Which kind of line this is.
                          example: llm_call
                        provider:
                          type:
                            - string
                            - 'null'
                          description: >-
                            The provider or vendor the line prices. Null on a
                            markup line.
                          example: anthropic
                        model:
                          type:
                            - string
                            - 'null'
                          description: >-
                            The model or item the line prices. Null on a markup
                            line.
                          example: claude-sonnet-5
                        quantity:
                          type:
                            - string
                            - 'null'
                          description: >-
                            How much was priced, in `unit`. Null on a markup
                            line.
                          example: '12400'
                        unit:
                          type:
                            - string
                            - 'null'
                          description: >-
                            The dimension `quantity` is counted in. Null on a
                            markup line.
                          example: tokens
                        amount:
                          type: string
                          description: What the line costs, counted in `denomination`.
                          example: '3.482'
                        denomination:
                          type: string
                          enum:
                            - minor_units
                            - credits
                            - units
                          description: >-
                            What `amount` and every breakdown line count: the
                            wallet's minor units, credit units, or weighted
                            allowance units.
                          example: minor_units
                        usd_amount:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Set only on a credits line the rate card did not
                            price directly, which was therefore converted from
                            the USD price registry. The USD figure it came from,
                            so a receipt can show both numbers instead of a bare
                            credit count.
                          example: '0.0348'
                        rate:
                          type:
                            - string
                            - 'null'
                          description: >-
                            The rate the line was priced at, when there is one
                            to name. Null on an unpriced line — there was no
                            rate, which is the point.
                          example: 1000/5000 per 1M in/out
                        price_status:
                          type: string
                          enum:
                            - priced
                            - partial
                            - unpriced
                          description: >-
                            Whether `amount` means anything. `priced` is the
                            normal case and is what an absent value means.
                            `unpriced` means nothing could price this line — not
                            your rate card, not your catalog, not the model
                            registry — so it was recorded at 0 and **you were
                            not charged for it**: a 0 with `unpriced` is
                            unknown, not free. `partial` means some dimensions
                            of the line were priced and others were not. The
                            line keeps its provider/model, quantity and unit so
                            the gap is recoverable; fixing your rate card
                            affects future calls only, never this entry.
                          example: priced
                      required:
                        - kind
                        - provider
                        - model
                        - quantity
                        - unit
                        - amount
                    description: >-
                      Itemized lines behind `amount`: one per LLM call, one per
                      cost item, plus a `markup` line when the policy charges
                      one. In credits mode every line is in credits, and a line
                      the rate card did not price directly also carries the
                      `usd_amount` it was converted from. Read each line's
                      `price_status`: a line nothing could price is present at 0
                      and marked `unpriced` rather than dropped, so the receipt
                      always accounts for everything that was sent.
                  balance:
                    type: object
                    properties:
                      denomination:
                        type: string
                        enum:
                          - minor_units
                          - credits
                          - units
                        description: >-
                          What the three numbers count. `minor_units` is the
                          wallet's currency (wallet mode); `credits` is a count
                          of credit units, which has no currency at all (credits
                          mode); `units` is the weighted unit rolling allowances
                          are metered in (windows mode). Read this rather than
                          inferring it from `mode`: a balance is meaningless
                          without its unit.
                        example: minor_units
                      wallet:
                        type: string
                        description: >-
                          The settled source balance — the wallet's balance in
                          wallet mode, the credit pot's balance in credits mode.
                        example: '12500'
                      unsettled:
                        type: string
                        description: >-
                          Consumption recorded but not yet rolled into a wallet
                          transaction. Always `0` in credits mode, where a
                          consume decrements the real credit pot inside its own
                          transaction and leaves nothing in flight.
                        example: '43.218'
                      available:
                        type: string
                        description: >-
                          `wallet - unsettled` — what the customer can still
                          spend, and the only one of the three to gate on in
                          either mode. Correct the instant a consume commits; in
                          wallet mode it may go negative if they overspent
                          between settlements.
                        example: '12456.782'
                    required:
                      - denomination
                      - wallet
                      - unsettled
                      - available
                    description: >-
                      What the customer can spend. In wallet mode this is the
                      shadow balance — micro-consumption never touches the
                      wallet ledger directly. In credits mode it is the credit
                      pot itself, read live. In windows mode the three numbers
                      describe the *binding* window, the one with least room
                      left and therefore the one that will refuse the next call;
                      `meters` carries every window separately.
                  meters:
                    type:
                      - array
                      - 'null'
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          description: >-
                            The window this meter is for, as the policy names it
                            — `5h`, `7d`, `monthly`.
                          example: 5h
                        included_units:
                          type: string
                          description: The whole allowance for one instance of this window.
                          example: '50000'
                        used_units:
                          type: string
                          description: >-
                            Weighted units consumed inside the open instance,
                            counting the call that just returned. Zero when no
                            instance is open.
                          example: '12500'
                        remaining_units:
                          type: string
                          description: >-
                            `included_units - used_units`, floored at zero. The
                            whole allowance when no instance is open.
                          example: '37500'
                        window_started_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance was anchored — the first
                            consumption after the previous instance expired.
                            Null together with `resets_at` when no instance is
                            open.
                          example: '2026-08-20T09:14:02.113Z'
                        resets_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance expires and the allowance
                            comes back in full. Null when no instance is open:
                            nothing has been consumed since the last one ended,
                            so the clock has not started and the next call is
                            what anchors it.
                          example: '2026-08-20T14:14:02.113Z'
                      required:
                        - key
                        - included_units
                        - used_units
                        - remaining_units
                        - window_started_at
                        - resets_at
                      description: >-
                        One rolling allowance window's live state, including the
                        call that just happened.
                    description: >-
                      Every rolling allowance window after this call, in
                      `windows` mode — the units it just consumed are already in
                      `used_units`. Null in every other mode.
                  blocked:
                    type: boolean
                    description: >-
                      Whether the customer's kill switch is on. Consumption is
                      still recorded when it is — blocking is a gate for
                      `check`, not a way to lose ledger entries.
                    example: false
                  warning:
                    type:
                      - object
                      - 'null'
                    properties:
                      code:
                        type: string
                        enum:
                          - unpriced_usage
                        description: Machine-readable warning code.
                        example: unpriced_usage
                      message:
                        type: string
                        description: Human-readable explanation of the warning.
                        example: >-
                          1 usage line could not be priced and was recorded at
                          zero. Add the missing rate-card row, catalog entry, or
                          fallback conversion rate — this consume will not be
                          re-charged retroactively.
                      unpriced_lines:
                        type: number
                        description: >-
                          How many breakdown lines were recorded at 0 because
                          nothing could price them. Matches the number of lines
                          carrying `price_status: "unpriced"`.
                        example: 1
                    required:
                      - code
                      - message
                      - unpriced_lines
                    description: >-
                      Set when part of this consume could not be priced. The
                      customer was still charged for the lines that could be,
                      and the unpriceable ones are in `breakdown` with
                      `price_status: "unpriced"`. Null otherwise.
                  overage:
                    type: boolean
                    description: >-
                      True when THIS call was priced as overage: it crossed the
                      scope's boundary and the policy is `metered`, so the whole
                      call was re-priced in USD and `denomination` is
                      `minor_units` rather than `credits` or `units`. A replay
                      reports what the original call did.
                    example: true
                required:
                  - agent
                  - amount
                  - denomination
                  - breakdown
                  - balance
                  - meters
                  - blocked
                  - warning
                  - overage
        '402':
          description: >-
            Not enough credits, or a rolling allowance with no room left.
            Nothing was deducted and no window was incremented.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - not_configured
                      - unsupported_mode
                      - customer_not_found
                      - wallet_missing
                      - credit_pot_missing
                      - pricing_unavailable
                      - insufficient_credits
                      - allowance_exhausted
                      - windows_not_configured
                    description: >-
                      Machine-readable refusal code. Note that
                      `pricing_unavailable` is retained in this enum for
                      compatibility and is no longer returned: usage no rate
                      card can price is recorded at 0 and flagged on the
                      breakdown instead of refusing the call.
                    example: not_configured
                  message:
                    type: string
                    description: Human-readable explanation of the refusal.
                    example: This customer has no AI billing policy
                  balance:
                    type:
                      - object
                      - 'null'
                    properties:
                      denomination:
                        type: string
                        enum:
                          - minor_units
                          - credits
                          - units
                        description: >-
                          What the three numbers count. `minor_units` is the
                          wallet's currency (wallet mode); `credits` is a count
                          of credit units, which has no currency at all (credits
                          mode); `units` is the weighted unit rolling allowances
                          are metered in (windows mode). Read this rather than
                          inferring it from `mode`: a balance is meaningless
                          without its unit.
                        example: minor_units
                      wallet:
                        type: string
                        description: >-
                          The settled source balance — the wallet's balance in
                          wallet mode, the credit pot's balance in credits mode.
                        example: '12500'
                      unsettled:
                        type: string
                        description: >-
                          Consumption recorded but not yet rolled into a wallet
                          transaction. Always `0` in credits mode, where a
                          consume decrements the real credit pot inside its own
                          transaction and leaves nothing in flight.
                        example: '43.218'
                      available:
                        type: string
                        description: >-
                          `wallet - unsettled` — what the customer can still
                          spend, and the only one of the three to gate on in
                          either mode. Correct the instant a consume commits; in
                          wallet mode it may go negative if they overspent
                          between settlements.
                        example: '12456.782'
                    required:
                      - denomination
                      - wallet
                      - unsettled
                      - available
                    description: >-
                      The balance at the moment of the refusal, when the refusal
                      is about money — `insufficient_credits` and
                      `allowance_exhausted` carry it so an agent knows how short
                      it was without a second round trip. Null otherwise.
                  meters:
                    type:
                      - array
                      - 'null'
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          description: >-
                            The window this meter is for, as the policy names it
                            — `5h`, `7d`, `monthly`.
                          example: 5h
                        included_units:
                          type: string
                          description: The whole allowance for one instance of this window.
                          example: '50000'
                        used_units:
                          type: string
                          description: >-
                            Weighted units consumed inside the open instance,
                            counting the call that just returned. Zero when no
                            instance is open.
                          example: '12500'
                        remaining_units:
                          type: string
                          description: >-
                            `included_units - used_units`, floored at zero. The
                            whole allowance when no instance is open.
                          example: '37500'
                        window_started_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance was anchored — the first
                            consumption after the previous instance expired.
                            Null together with `resets_at` when no instance is
                            open.
                          example: '2026-08-20T09:14:02.113Z'
                        resets_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance expires and the allowance
                            comes back in full. Null when no instance is open:
                            nothing has been consumed since the last one ended,
                            so the clock has not started and the next call is
                            what anchors it.
                          example: '2026-08-20T14:14:02.113Z'
                      required:
                        - key
                        - included_units
                        - used_units
                        - remaining_units
                        - window_started_at
                        - resets_at
                      description: >-
                        One rolling allowance window's live state, including the
                        call that just happened.
                    description: >-
                      Every window's state at the moment of an
                      `allowance_exhausted` refusal, so the caller can see which
                      one ran out and by how much. Null on every other refusal.
                  resets_at:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The soonest instant one of the windows that blocked the
                      call rolls over — the earliest of them, since that is the
                      next moment the answer could change. Null when no blocking
                      window has an open instance, which means the call is
                      larger than a whole allowance and waiting will not help.
                      Null on every other refusal.
                    example: '2026-08-20T14:14:02.113Z'
                required:
                  - code
                  - message
                  - balance
                  - meters
                  - resets_at
        '404':
          description: Customer not found.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - not_configured
                      - unsupported_mode
                      - customer_not_found
                      - wallet_missing
                      - credit_pot_missing
                      - pricing_unavailable
                      - insufficient_credits
                      - allowance_exhausted
                      - windows_not_configured
                    description: >-
                      Machine-readable refusal code. Note that
                      `pricing_unavailable` is retained in this enum for
                      compatibility and is no longer returned: usage no rate
                      card can price is recorded at 0 and flagged on the
                      breakdown instead of refusing the call.
                    example: not_configured
                  message:
                    type: string
                    description: Human-readable explanation of the refusal.
                    example: This customer has no AI billing policy
                  balance:
                    type:
                      - object
                      - 'null'
                    properties:
                      denomination:
                        type: string
                        enum:
                          - minor_units
                          - credits
                          - units
                        description: >-
                          What the three numbers count. `minor_units` is the
                          wallet's currency (wallet mode); `credits` is a count
                          of credit units, which has no currency at all (credits
                          mode); `units` is the weighted unit rolling allowances
                          are metered in (windows mode). Read this rather than
                          inferring it from `mode`: a balance is meaningless
                          without its unit.
                        example: minor_units
                      wallet:
                        type: string
                        description: >-
                          The settled source balance — the wallet's balance in
                          wallet mode, the credit pot's balance in credits mode.
                        example: '12500'
                      unsettled:
                        type: string
                        description: >-
                          Consumption recorded but not yet rolled into a wallet
                          transaction. Always `0` in credits mode, where a
                          consume decrements the real credit pot inside its own
                          transaction and leaves nothing in flight.
                        example: '43.218'
                      available:
                        type: string
                        description: >-
                          `wallet - unsettled` — what the customer can still
                          spend, and the only one of the three to gate on in
                          either mode. Correct the instant a consume commits; in
                          wallet mode it may go negative if they overspent
                          between settlements.
                        example: '12456.782'
                    required:
                      - denomination
                      - wallet
                      - unsettled
                      - available
                    description: >-
                      The balance at the moment of the refusal, when the refusal
                      is about money — `insufficient_credits` and
                      `allowance_exhausted` carry it so an agent knows how short
                      it was without a second round trip. Null otherwise.
                  meters:
                    type:
                      - array
                      - 'null'
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          description: >-
                            The window this meter is for, as the policy names it
                            — `5h`, `7d`, `monthly`.
                          example: 5h
                        included_units:
                          type: string
                          description: The whole allowance for one instance of this window.
                          example: '50000'
                        used_units:
                          type: string
                          description: >-
                            Weighted units consumed inside the open instance,
                            counting the call that just returned. Zero when no
                            instance is open.
                          example: '12500'
                        remaining_units:
                          type: string
                          description: >-
                            `included_units - used_units`, floored at zero. The
                            whole allowance when no instance is open.
                          example: '37500'
                        window_started_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance was anchored — the first
                            consumption after the previous instance expired.
                            Null together with `resets_at` when no instance is
                            open.
                          example: '2026-08-20T09:14:02.113Z'
                        resets_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance expires and the allowance
                            comes back in full. Null when no instance is open:
                            nothing has been consumed since the last one ended,
                            so the clock has not started and the next call is
                            what anchors it.
                          example: '2026-08-20T14:14:02.113Z'
                      required:
                        - key
                        - included_units
                        - used_units
                        - remaining_units
                        - window_started_at
                        - resets_at
                      description: >-
                        One rolling allowance window's live state, including the
                        call that just happened.
                    description: >-
                      Every window's state at the moment of an
                      `allowance_exhausted` refusal, so the caller can see which
                      one ran out and by how much. Null on every other refusal.
                  resets_at:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The soonest instant one of the windows that blocked the
                      call rolls over — the earliest of them, since that is the
                      next moment the answer could change. Null when no blocking
                      window has an open instance, which means the call is
                      larger than a whole allowance and waiting will not help.
                      Null on every other refusal.
                    example: '2026-08-20T14:14:02.113Z'
                required:
                  - code
                  - message
                  - balance
                  - meters
                  - resets_at
        '409':
          description: No billing policy configured.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - not_configured
                      - unsupported_mode
                      - customer_not_found
                      - wallet_missing
                      - credit_pot_missing
                      - pricing_unavailable
                      - insufficient_credits
                      - allowance_exhausted
                      - windows_not_configured
                    description: >-
                      Machine-readable refusal code. Note that
                      `pricing_unavailable` is retained in this enum for
                      compatibility and is no longer returned: usage no rate
                      card can price is recorded at 0 and flagged on the
                      breakdown instead of refusing the call.
                    example: not_configured
                  message:
                    type: string
                    description: Human-readable explanation of the refusal.
                    example: This customer has no AI billing policy
                  balance:
                    type:
                      - object
                      - 'null'
                    properties:
                      denomination:
                        type: string
                        enum:
                          - minor_units
                          - credits
                          - units
                        description: >-
                          What the three numbers count. `minor_units` is the
                          wallet's currency (wallet mode); `credits` is a count
                          of credit units, which has no currency at all (credits
                          mode); `units` is the weighted unit rolling allowances
                          are metered in (windows mode). Read this rather than
                          inferring it from `mode`: a balance is meaningless
                          without its unit.
                        example: minor_units
                      wallet:
                        type: string
                        description: >-
                          The settled source balance — the wallet's balance in
                          wallet mode, the credit pot's balance in credits mode.
                        example: '12500'
                      unsettled:
                        type: string
                        description: >-
                          Consumption recorded but not yet rolled into a wallet
                          transaction. Always `0` in credits mode, where a
                          consume decrements the real credit pot inside its own
                          transaction and leaves nothing in flight.
                        example: '43.218'
                      available:
                        type: string
                        description: >-
                          `wallet - unsettled` — what the customer can still
                          spend, and the only one of the three to gate on in
                          either mode. Correct the instant a consume commits; in
                          wallet mode it may go negative if they overspent
                          between settlements.
                        example: '12456.782'
                    required:
                      - denomination
                      - wallet
                      - unsettled
                      - available
                    description: >-
                      The balance at the moment of the refusal, when the refusal
                      is about money — `insufficient_credits` and
                      `allowance_exhausted` carry it so an agent knows how short
                      it was without a second round trip. Null otherwise.
                  meters:
                    type:
                      - array
                      - 'null'
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          description: >-
                            The window this meter is for, as the policy names it
                            — `5h`, `7d`, `monthly`.
                          example: 5h
                        included_units:
                          type: string
                          description: The whole allowance for one instance of this window.
                          example: '50000'
                        used_units:
                          type: string
                          description: >-
                            Weighted units consumed inside the open instance,
                            counting the call that just returned. Zero when no
                            instance is open.
                          example: '12500'
                        remaining_units:
                          type: string
                          description: >-
                            `included_units - used_units`, floored at zero. The
                            whole allowance when no instance is open.
                          example: '37500'
                        window_started_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance was anchored — the first
                            consumption after the previous instance expired.
                            Null together with `resets_at` when no instance is
                            open.
                          example: '2026-08-20T09:14:02.113Z'
                        resets_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance expires and the allowance
                            comes back in full. Null when no instance is open:
                            nothing has been consumed since the last one ended,
                            so the clock has not started and the next call is
                            what anchors it.
                          example: '2026-08-20T14:14:02.113Z'
                      required:
                        - key
                        - included_units
                        - used_units
                        - remaining_units
                        - window_started_at
                        - resets_at
                      description: >-
                        One rolling allowance window's live state, including the
                        call that just happened.
                    description: >-
                      Every window's state at the moment of an
                      `allowance_exhausted` refusal, so the caller can see which
                      one ran out and by how much. Null on every other refusal.
                  resets_at:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The soonest instant one of the windows that blocked the
                      call rolls over — the earliest of them, since that is the
                      next moment the answer could change. Null when no blocking
                      window has an open instance, which means the call is
                      larger than a whole allowance and waiting will not help.
                      Null on every other refusal.
                    example: '2026-08-20T14:14:02.113Z'
                required:
                  - code
                  - message
                  - balance
                  - meters
                  - resets_at
        '422':
          description: >-
            The policy cannot bill this: an unsupported mode, a missing wallet
            or credit pot, an unconfigured window card, or usage no rate card
            prices.
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - not_configured
                      - unsupported_mode
                      - customer_not_found
                      - wallet_missing
                      - credit_pot_missing
                      - pricing_unavailable
                      - insufficient_credits
                      - allowance_exhausted
                      - windows_not_configured
                    description: >-
                      Machine-readable refusal code. Note that
                      `pricing_unavailable` is retained in this enum for
                      compatibility and is no longer returned: usage no rate
                      card can price is recorded at 0 and flagged on the
                      breakdown instead of refusing the call.
                    example: not_configured
                  message:
                    type: string
                    description: Human-readable explanation of the refusal.
                    example: This customer has no AI billing policy
                  balance:
                    type:
                      - object
                      - 'null'
                    properties:
                      denomination:
                        type: string
                        enum:
                          - minor_units
                          - credits
                          - units
                        description: >-
                          What the three numbers count. `minor_units` is the
                          wallet's currency (wallet mode); `credits` is a count
                          of credit units, which has no currency at all (credits
                          mode); `units` is the weighted unit rolling allowances
                          are metered in (windows mode). Read this rather than
                          inferring it from `mode`: a balance is meaningless
                          without its unit.
                        example: minor_units
                      wallet:
                        type: string
                        description: >-
                          The settled source balance — the wallet's balance in
                          wallet mode, the credit pot's balance in credits mode.
                        example: '12500'
                      unsettled:
                        type: string
                        description: >-
                          Consumption recorded but not yet rolled into a wallet
                          transaction. Always `0` in credits mode, where a
                          consume decrements the real credit pot inside its own
                          transaction and leaves nothing in flight.
                        example: '43.218'
                      available:
                        type: string
                        description: >-
                          `wallet - unsettled` — what the customer can still
                          spend, and the only one of the three to gate on in
                          either mode. Correct the instant a consume commits; in
                          wallet mode it may go negative if they overspent
                          between settlements.
                        example: '12456.782'
                    required:
                      - denomination
                      - wallet
                      - unsettled
                      - available
                    description: >-
                      The balance at the moment of the refusal, when the refusal
                      is about money — `insufficient_credits` and
                      `allowance_exhausted` carry it so an agent knows how short
                      it was without a second round trip. Null otherwise.
                  meters:
                    type:
                      - array
                      - 'null'
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          description: >-
                            The window this meter is for, as the policy names it
                            — `5h`, `7d`, `monthly`.
                          example: 5h
                        included_units:
                          type: string
                          description: The whole allowance for one instance of this window.
                          example: '50000'
                        used_units:
                          type: string
                          description: >-
                            Weighted units consumed inside the open instance,
                            counting the call that just returned. Zero when no
                            instance is open.
                          example: '12500'
                        remaining_units:
                          type: string
                          description: >-
                            `included_units - used_units`, floored at zero. The
                            whole allowance when no instance is open.
                          example: '37500'
                        window_started_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance was anchored — the first
                            consumption after the previous instance expired.
                            Null together with `resets_at` when no instance is
                            open.
                          example: '2026-08-20T09:14:02.113Z'
                        resets_at:
                          type:
                            - string
                            - 'null'
                          description: >-
                            When the open instance expires and the allowance
                            comes back in full. Null when no instance is open:
                            nothing has been consumed since the last one ended,
                            so the clock has not started and the next call is
                            what anchors it.
                          example: '2026-08-20T14:14:02.113Z'
                      required:
                        - key
                        - included_units
                        - used_units
                        - remaining_units
                        - window_started_at
                        - resets_at
                      description: >-
                        One rolling allowance window's live state, including the
                        call that just happened.
                    description: >-
                      Every window's state at the moment of an
                      `allowance_exhausted` refusal, so the caller can see which
                      one ran out and by how much. Null on every other refusal.
                  resets_at:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The soonest instant one of the windows that blocked the
                      call rolls over — the earliest of them, since that is the
                      next moment the answer could change. Null when no blocking
                      window has an open instance, which means the call is
                      larger than a whole allowance and waiting will not help.
                      Null on every other refusal.
                    example: '2026-08-20T14:14:02.113Z'
                required:
                  - code
                  - message
                  - balance
                  - meters
                  - resets_at
      security:
        - bearer: []
components:
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT

````