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

# Create a model pricing rule



## OpenAPI

````yaml /api-reference/openapi.yaml post /api/llm-gateway/admin/model-pricing
openapi: 3.1.0
info:
  title: Barndoor.ai Public API
  description: Unified public API specification for Barndoor.ai platform
  version: 2.18.0
servers:
  - url: https://{host}
    description: Barndoor public API
    variables:
      host:
        default: platform.barndoor.ai
        description: >-
          The host serving your Barndoor deployment. Defaults to production;
          override it for another environment or a dedicated deployment.
security:
  - ApiKey: []
  - OAuth2:
      - openid
      - profile
      - email
tags:
  - name: dlp
    x-group: Data Control Center
  - name: identity
    x-group: Identity
  - name: llm-gateway
    x-group: LLM Gateway
  - name: notification
    x-group: Notifications
  - name: policy
    x-group: Policies
  - name: registry
    x-group: MCP Gateway
  - name: system-management
    x-group: Log Exports
paths:
  /api/llm-gateway/admin/model-pricing:
    post:
      tags:
        - llm-gateway
      summary: Create a model pricing rule
      operationId: create_pricing
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePricingRequest'
        required: true
      responses:
        '200':
          description: The created record
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminModelPricing'
        '400':
          description: Malformed request
        '401':
          description: Missing or invalid credentials
        '403':
          description: Caller is not permitted to act on this resource in this organization
        '409':
          description: >-
            A pricing version already exists for this rule at that
            `effective_from` instant
components:
  schemas:
    CreatePricingRequest:
      type: object
      required:
        - model_pattern
        - input_cost_per_million_tokens
        - output_cost_per_million_tokens
      properties:
        cache_read_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: |-
            Per-million-tokens rate billed for prompt-cache reads. Omit to
            inherit the Barndoor default (or leave NULL if the default has
            none, in which case the cost calculator falls back to the full
            input rate). Storing NULL preserves the "no override" semantics
            so a future seeder update can repopulate the default rate without
            the org row blocking it.
        cache_write_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: |-
            Per-million-tokens rate billed for the cache-creation premium
            that Anthropic-family models charge on the request that populates
            the prompt cache. Same NULL semantics as `cache_read_cost`.
        catalog_slug:
          type:
            - string
            - 'null'
        change_reason:
          type:
            - string
            - 'null'
          description: |-
            Optional free-text note ("Q1 pricing review", "Negotiated discount")
            surfaced on the History dialog timeline.
        effective_from:
          type:
            - string
            - 'null'
          format: date-time
          description: |-
            When the price should take effect. Omit (or pass `null`) for
            "right now". A timestamp in the future schedules the change and
            records the row with `change_source = 'admin_schedule'` so the
            History dialog can distinguish it from an immediate edit.
        input_cost_per_million_tokens:
          type: number
          format: double
        long_context:
          oneOf:
            - $ref: '#/components/schemas/LongContextTierRequest'
              description: >-
                Optional context-tiered surcharge (BCP-3904). Omit for the
                normal

                case of one rate set at every prompt size.
            - type: 'null'
        model_pattern:
          type: string
        model_provider:
          type:
            - string
            - 'null'
        output_cost_per_million_tokens:
          type: number
          format: double
        provider_id:
          type:
            - string
            - 'null'
          format: uuid
        sync_mode:
          $ref: '#/components/schemas/PricingSyncMode'
    AdminModelPricing:
      allOf:
        - $ref: '#/components/schemas/ModelPricing'
        - type: object
          required:
            - sync_mode
            - change_source
            - is_archived
          properties:
            change_reason:
              type:
                - string
                - 'null'
            change_source:
              $ref: '#/components/schemas/PricingChangeSource'
            created_by_email:
              type:
                - string
                - 'null'
            created_by_name:
              type:
                - string
                - 'null'
            created_by_user_id:
              type:
                - string
                - 'null'
              format: uuid
            is_archived:
              type: boolean
              description: >-
                True for tombstone rows produced by `archive_rule` (V35). When

                the latest effective version of a group has `is_archived =
                true`,

                the rule is considered archived: the cost calculator skips it

                and the admin summary list hides it by default. Past
                non-archived

                versions remain in the timeline so the History dialog can show

                the rule's full life including the archive event.
            sync_mode:
              $ref: '#/components/schemas/PricingSyncMode'
      description: >-
        Admin-API response shape for a single pricing row. Wraps the

        `ai_governance::ModelPricing` used by the cost calculator so that the
        hot

        path stays sync-mode-agnostic, while the admin surface still gets the

        metadata it needs to render badges, the Review-updates dialog, and (as

        of BCP-2830 v2 / V34) the per-row history timeline.
    LongContextTierRequest:
      type: object
      description: >-
        The long-context surcharge on a create/update request.


        One nested object rather than five sibling fields so a partial tier is

        awkward to express in the first place, and so the wire shape matches
        both

        the provider YAML's `long_context:` block and the `long_context` object
        the

        defaults listing returns.
      required:
        - threshold_prompt_tokens
        - input_cost_per_million_tokens
        - output_cost_per_million_tokens
      properties:
        cache_read_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: Omit to bill long-context cache reads at this tier's input rate.
        cache_write_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
        input_cost_per_million_tokens:
          type: number
          format: double
        output_cost_per_million_tokens:
          type: number
          format: double
        threshold_prompt_tokens:
          type: integer
          format: int64
          description: |-
            Total prompt tokens (non-cached input + cache-read + cache-creation)
            at or above which the tier's rates replace the base rates for the
            whole request.
    PricingSyncMode:
      type: string
      description: |-
        Per-row sync behavior. Stored as a `VARCHAR(16)` constrained to
        `tracking | pinned | auto` (see migration V33).
      enum:
        - tracking
        - pinned
        - auto
    ModelPricing:
      type: object
      required:
        - id
        - org_id
        - model_pattern
        - input_cost_per_million_tokens
        - output_cost_per_million_tokens
        - effective_from
      properties:
        cache_read_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: |-
            Per-million-token cost for input tokens served from the prompt
            cache. `None` ⇒ the calculator bills cached input at
            `input_cost_per_million_tokens`.
        cache_write_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: |-
            Per-million-token cost for input tokens added to the prompt cache.
            `None` ⇒ same fallback as `cache_read_cost_per_million_tokens`.
        catalog_slug:
          type:
            - string
            - 'null'
          description: >-
            Catalog slug for provider-level pricing (e.g. "openai",
            "aws_bedrock").
        effective_from:
          type: string
          format: date-time
        id:
          type: string
          format: uuid
        input_cost_per_million_tokens:
          type: number
          format: double
        long_context:
          oneOf:
            - $ref: '#/components/schemas/LongContextTier'
              description: >-
                Optional context-tiered surcharge (BCP-3904). `None` ⇒ one rate
                set

                at every prompt size, i.e. exactly the pre-BCP-3904 behaviour.


                Serialized as `long_context`, not as the Rust field name. This
                struct

                reaches the admin API through `AdminModelPricing`'s

                `#[serde(flatten)]`, so the field name here *is* the wire key —
                and

                every sibling surface (`DefaultPricingEntry`,
                `EffectivePricing`, the

                create/update request bodies) already spells it `long_context`.
                Left

                unrenamed, the pricing tab would write a tier successfully and
                then

                read back nothing, which is precisely how it behaved before this

                attribute existed: the surcharge saved, the dialog reopened
                unchecked,

                and the edit looked silently discarded. Pinned by

                `admin_model_pricing_serializes_the_tier_as_long_context`.
            - type: 'null'
        model_pattern:
          type: string
        model_provider:
          type:
            - string
            - 'null'
        org_id:
          type: string
          format: uuid
        output_cost_per_million_tokens:
          type: number
          format: double
        provider_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Optional reference to a specific LLM Gateway provider instance.
        provider_name:
          type:
            - string
            - 'null'
    PricingChangeSource:
      type: string
      description: |-
        How a `model_pricing` version was produced. Persisted as a
        `VARCHAR(20)` constrained to one of these eight values (see
        migrations V34 + V35). Surfaced to admins as the "source" badge on
        each entry of the `PricingHistoryDialog`.
      enum:
        - admin_create
        - admin_edit
        - admin_schedule
        - import
        - sync_manual
        - sync_auto
        - admin_archive
        - admin_restore
    LongContextTier:
      type: object
      description: >-
        The alternate rate set a pricing row switches to once a request's prompt

        reaches `threshold_prompt_tokens` (BCP-3904).


        Crossing the threshold re-rates the **whole** request, not just the
        tokens

        past it — that is how xAI, OpenAI and Azure all publish it, and it is
        why

        this is a rate switch rather than a marginal bracket.


        Note the asymmetry that makes this easy to get wrong: the gate is
        measured

        on the *prompt*, but the surcharge applies to output tokens too. The
        gate

        quantity and the billed quantities are different numbers.
      required:
        - threshold_prompt_tokens
        - input_cost_per_million_tokens
        - output_cost_per_million_tokens
      properties:
        cache_read_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: |-
            `None` ⇒ bill cache reads at this tier's input rate, mirroring the
            base-rate fallback rather than falling back to the *base* cache rate
            (which would price a long-context cache read below its own tier).
        cache_write_cost_per_million_tokens:
          type:
            - number
            - 'null'
          format: double
          description: '`None` ⇒ same fallback as `cache_read_cost_per_million_tokens`.'
        input_cost_per_million_tokens:
          type: number
          format: double
        output_cost_per_million_tokens:
          type: number
          format: double
        threshold_prompt_tokens:
          type: integer
          format: int64
          description: |-
            Total prompt tokens at or above which this tier replaces the base
            rates. Inclusive — see [`ModelPricing::rates_for_prompt`].
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: >-
        A Barndoor API key, sent as `Authorization: Bearer <key>`. Keys are
        prefixed `bdai_` and are opaque — do not attempt to decode one.
        Interchangeable with an OAuth 2.0 access token.
    OAuth2:
      type: oauth2
      x-issuer: https://auth.barndoor.ai/realms/barndoor
      description: >-
        An OAuth 2.0 access token from Barndoor's identity provider, sent as
        `Authorization: Bearer <token>`. Public clients must use PKCE.
        Interchangeable with an API key.
      flows:
        authorizationCode:
          authorizationUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/auth
          tokenUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/token
          scopes:
            openid: Issue an OIDC ID token identifying the caller.
            profile: Read the caller's basic profile claims.
            email: Read the caller's email address.
            offline_access: Issue a refresh token. Optional — no operation requires it.
        clientCredentials:
          tokenUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/token
          scopes:
            openid: Issue an OIDC ID token identifying the caller.
            profile: Read the caller's basic profile claims.
            email: Read the caller's email address.
            offline_access: Issue a refresh token. Optional — no operation requires it.

````

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