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

# Create a quotation

> Create a **quotation** for a prospective payout and reserve a redeemable quote. A quotation prices the payout the same way `POST /v1/virtual-accounts/{virtual_account_id}/payout/preview` does — reusing the three payout calculation flows — but does not require a virtual account and **always persists a quote**. The response returns `quote_id` and `quote_expires_at`; redeem the `quote_id` on a payout to settle at the exact quoted amount, fees, and FX rate. The default quote lifespan is **15 minutes**.

All monetary amounts are **USD decimal strings** (e.g. `"1000.00"`).

**Identify the destination** with exactly one of:

-   `recipient_id` — a saved recipient (`WIRE`, `ACH`, or `WALLET`).
-   `account_type` — the rail (`WIRE` | `ACH` | `WALLET`) to price without a saved recipient. When `account_type` is `WALLET` and no `recipient_id` is given, `wallet_network` and `wallet_token` are also required.

Send at least one; if both are sent, `recipient_id` takes precedence.

**The flow is auto-detected** from the request:

-   **Fiat-to-bank** — a `WIRE`/`ACH` destination; omit `payment_instructions`. `recipient_currency` is `USD`.
-   **Crypto-funded (crypto-to-bank)** — supply `payment_instructions` (the stablecoin/network you deposit to fund the payout); `recipient_currency` is `USD`.
-   **Fiat-to-crypto** — a `WALLET` destination; the recipient receives stablecoins and `recipient_currency` is `USDC` or `USDT`.

**Key request fields:**

-   `amount` (required) — positive USD decimal string.
-   `inverse_calculation` (default `false`) — when `true`, `amount` is the desired recipient amount and the engine back-solves the source amount.
-   `client_markup` — per-quote markup override `{ fixed_fee, percentage_fee, fx_markup? }` as decimal strings (`percentage_fee` is `0`–`1`, e.g. `0.01` = 1%). Replaces your configured markup for this quote only.

**Response** returns the source `amount`/`currency`, the `recipient_amount`/`recipient_currency`, an aggregated `fees` breakdown (base fees, your markup, network fee, optional FX detail, and totals), and the reserved `quote_id` / `quote_expires_at`.

**Errors:** `400` `validation_error` (request failed schema validation) or `bad_request` (e.g. `"Total fees exceed or equal the payout amount"`, returned when `amount` is below the rail minimum); `401` `unauthorized`; `404` `not_found` for an unknown recipient or client.

**Note:** this is the `2026-04-14` **preview-shape** quotation. The line-by-line **itemized** fee envelope — integer minor units, `pricing_context`, depeg-aware `conversion`, and an itemized `fees[]` array — requires pinning API version `2026-06-01` or later. See the **Itemized quotations** guide.

{/* version-stamp:start — generated by scripts/stamp-versions.ts, do not edit */}

<Update label="2026-04-14">Changed in this version.</Update>

{/* version-stamp:end */}


## OpenAPI

````yaml /openapi/kira-api.2026-04-14.json post /v1/quotations
openapi: 3.1.0
info:
  title: Kira API
  version: '2026-04-14'
  description: >-
    REST API for users, KYC/KYB verification, virtual accounts, payouts,
    recipients, and webhooks. Every request requires an `x-api-key` header and a
    bearer access token (see Authentication). Pin your account to version
    `2026-04-14` before integrating.
  contact:
    name: Kira API Support
    email: support@kirafin.ai
servers:
  - url: https://api.balampay.com
    description: Production
  - url: https://api.balampay.com/sandbox
    description: Sandbox
security:
  - bearerAuth: []
    apiKeyAuth: []
tags:
  - name: Authentication
  - name: Versioning
  - name: Users
  - name: Virtual Accounts
  - name: Quotations
  - name: Payouts
  - name: Recipients
  - name: Reference
paths:
  /v1/quotations:
    post:
      tags:
        - Quotations
      summary: Create a quotation
      description: >-
        Create a **quotation** for a prospective payout and reserve a redeemable
        quote. A quotation prices the payout the same way `POST
        /v1/virtual-accounts/{virtual_account_id}/payout/preview` does — reusing
        the three payout calculation flows — but does not require a virtual
        account and **always persists a quote**. The response returns `quote_id`
        and `quote_expires_at`; redeem the `quote_id` on a payout to settle at
        the exact quoted amount, fees, and FX rate. The default quote lifespan
        is **15 minutes**.


        All monetary amounts are **USD decimal strings** (e.g. `"1000.00"`).


        **Identify the destination** with exactly one of:


        -   `recipient_id` — a saved recipient (`WIRE`, `ACH`, or `WALLET`).

        -   `account_type` — the rail (`WIRE` | `ACH` | `WALLET`) to price
        without a saved recipient. When `account_type` is `WALLET` and no
        `recipient_id` is given, `wallet_network` and `wallet_token` are also
        required.


        Send at least one; if both are sent, `recipient_id` takes precedence.


        **The flow is auto-detected** from the request:


        -   **Fiat-to-bank** — a `WIRE`/`ACH` destination; omit
        `payment_instructions`. `recipient_currency` is `USD`.

        -   **Crypto-funded (crypto-to-bank)** — supply `payment_instructions`
        (the stablecoin/network you deposit to fund the payout);
        `recipient_currency` is `USD`.

        -   **Fiat-to-crypto** — a `WALLET` destination; the recipient receives
        stablecoins and `recipient_currency` is `USDC` or `USDT`.


        **Key request fields:**


        -   `amount` (required) — positive USD decimal string.

        -   `inverse_calculation` (default `false`) — when `true`, `amount` is
        the desired recipient amount and the engine back-solves the source
        amount.

        -   `client_markup` — per-quote markup override `{ fixed_fee,
        percentage_fee, fx_markup? }` as decimal strings (`percentage_fee` is
        `0`–`1`, e.g. `0.01` = 1%). Replaces your configured markup for this
        quote only.


        **Response** returns the source `amount`/`currency`, the
        `recipient_amount`/`recipient_currency`, an aggregated `fees` breakdown
        (base fees, your markup, network fee, optional FX detail, and totals),
        and the reserved `quote_id` / `quote_expires_at`.


        **Errors:** `400` `validation_error` (request failed schema validation)
        or `bad_request` (e.g. `"Total fees exceed or equal the payout amount"`,
        returned when `amount` is below the rail minimum); `401` `unauthorized`;
        `404` `not_found` for an unknown recipient or client.


        **Note:** this is the `2026-04-14` **preview-shape** quotation. The
        line-by-line **itemized** fee envelope — integer minor units,
        `pricing_context`, depeg-aware `conversion`, and an itemized `fees[]`
        array — requires pinning API version `2026-06-01` or later. See the
        **Itemized quotations** guide.
      operationId: post_v1-quotations
      parameters:
        - in: header
          name: X-Api-Version
          required: false
          description: >-
            Optional. The date-versioned API version to apply for this request
            (e.g. `2026-04-14`). When sent it always wins, even over your pinned
            account default. When omitted, the API uses your account's pinned
            version if set, otherwise a baseline default.
          schema:
            type: string
            example: '2026-04-14'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuotationRequest'
            examples:
              fiat-to-bank-via-recipient:
                summary: Fiat-to-bank quote for a saved recipient
                value:
                  amount: '1000.00'
                  recipient_id: '{{recipient_id}}'
              fiat-to-crypto-via-account-type:
                summary: Fiat-to-crypto quote without a saved recipient
                value:
                  amount: '1000.00'
                  account_type: WALLET
                  wallet_network: solana
                  wallet_token: USDC
      responses:
        '201':
          description: Created. The quotation was priced and a quote reserved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuotationResponse'
              example:
                amount: '1000.00'
                currency: USD
                fees:
                  base_fees:
                    bank_account_fee: '5.00'
                    bank_account_fee_percentage: '0.005'
                    fixed_fee: '5.00'
                    percentage_fee: '5.00'
                    total: '10.00'
                  client_markup:
                    fixed_fee: '0.00'
                    percentage_fee: '2.50'
                    total: '2.50'
                  network_fee: '0.00'
                  total_fees: '12.50'
                  total: '12.50'
                recipient_amount: '987.50'
                recipient_currency: USD
                quote_id: a1b2c3d4-0000-0000-0000-000000000000
                quote_expires_at: '2026-04-14T18:15:00.000Z'
        '400':
          description: >-
            Validation error (`validation_error`) or a business-rule failure
            (`bad_request`, e.g. fees exceed the amount).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Recipient or client not found (`not_found`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
          apiKeyAuth: []
components:
  schemas:
    QuotationRequest:
      type: object
      description: >-
        Create-quotation request (API version `2026-04-14`). Prices a
        prospective payout and **always reserves a redeemable quote**. Identify
        the destination with exactly one of `recipient_id` or `account_type` —
        send at least one (if both are sent, `recipient_id` wins). There is no
        top-level `currency`: payouts are always priced in USD. Unknown fields
        are ignored.
      required:
        - amount
      properties:
        amount:
          type: string
          description: >-
            Positive USD decimal amount, e.g. `"1000.00"`. Up to 2 decimals for
            fiat and fiat-to-crypto flows; up to 8 decimals for crypto-funded
            flows (`payment_instructions` supplied), which are rounded **down**
            to 2 decimals when your account has high-precision round-down
            enabled. When `inverse_calculation` is `true`, this is instead the
            amount the recipient should receive.
          example: '1000.00'
        recipient_id:
          type: string
          format: uuid
          description: >-
            UUID of a saved recipient (`WIRE`, `ACH`, or `WALLET`). Provide this
            or `account_type`. The recipient's rail and — for a `WALLET`
            recipient — its network/token drive the pricing.
        account_type:
          type: string
          enum:
            - WIRE
            - WALLET
            - ACH
          description: >-
            Rail to price against without a saved recipient. Provide this
            instead of `recipient_id`. When `WALLET` (and no `recipient_id`),
            `wallet_network` and `wallet_token` are also required.
        wallet_network:
          type: string
          enum:
            - solana
            - polygon
            - tron
          description: >-
            Destination network for a fiat-to-crypto quote. Required when
            `account_type` is `WALLET` without a `recipient_id`.
        wallet_token:
          type: string
          enum:
            - USDC
            - USDT
          description: >-
            Destination stablecoin for a fiat-to-crypto quote. Required with
            `wallet_network`. Note: `tron` does not support `USDC`.
        inverse_calculation:
          type: boolean
          default: false
          description: >-
            When `true`, treat `amount` as the amount the recipient should
            receive and back-solve the source amount. The recipient receives at
            least the requested amount (rounding may deliver up to one minor
            unit more, never less).
        payment_instructions:
          type: object
          description: >-
            Supply to price a **crypto-funded** payout — the stablecoin and
            network you will deposit to fund it. Omit for a fiat-funded payout.
          required:
            - network
            - currency
          properties:
            network:
              type: string
              enum:
                - solana
                - polygon
                - tron
            currency:
              type: string
              enum:
                - USDC
                - USDT
        client_markup:
          type: object
          description: >-
            Override your account-configured markup for this quote only. Values
            are **decimal strings** (this is the `2026-04-14` shape — not the
            integer cents/bps of the `2026-06-01` itemized envelope).
          required:
            - fixed_fee
            - percentage_fee
          properties:
            fixed_fee:
              type: string
              description: >-
                Flat markup in USD, up to 2 decimals, non-negative. `"5.00"` =
                $5.00.
            percentage_fee:
              type: string
              description: >-
                Percentage markup as a decimal between `0` and `1` (up to 4
                decimals). `"0.01"` = 1%.
            fx_markup:
              type: string
              description: >-
                Optional FX markup as a non-negative decimal (up to 4 decimals).
                Applies to flows with a currency conversion.
    QuotationResponse:
      type: object
      description: >-
        Create-quotation response (API version `2026-04-14`). Mirrors the payout
        preview and always carries a redeemable `quote_id`. All monetary values
        are **decimal strings** — not the integer minor units of the
        `2026-06-01` itemized envelope. Redeem `quote_id` on `POST
        /v1/virtual-accounts/{virtual_account_id}/payout` to settle at the
        quoted amount, fees, and rate before it expires.
      required:
        - amount
        - currency
        - fees
        - recipient_amount
        - recipient_currency
        - quote_id
        - quote_expires_at
      properties:
        amount:
          type: string
          description: Source amount in USD, 2 decimals.
        currency:
          type: string
          description: Always `USD`.
          example: USD
        fees:
          type: object
          description: >-
            The fee breakdown, all values USD decimal strings. `fees.total` and
            `fees.total_fees` are identical (documented duplicate — use either).
          required:
            - base_fees
            - client_markup
            - network_fee
            - total_fees
            - total
          properties:
            base_fees:
              type: object
              description: Kira's base fees for the rail.
              required:
                - bank_account_fee
                - bank_account_fee_percentage
                - fixed_fee
                - percentage_fee
                - total
              properties:
                bank_account_fee:
                  type: string
                bank_account_fee_percentage:
                  type: string
                fixed_fee:
                  type: string
                percentage_fee:
                  type: string
                total:
                  type: string
                  description: Sum of the base fees.
            client_markup:
              type: object
              description: >-
                Your markup (the account-configured markup, or the
                `client_markup` override when supplied).
              required:
                - fixed_fee
                - percentage_fee
                - total
              properties:
                fixed_fee:
                  type: string
                percentage_fee:
                  type: string
                total:
                  type: string
                  description: Sum of your markup.
            network_fee:
              type: string
              description: >-
                Blockchain network fee. `"0.00"` for fiat-to-bank; a stablecoin
                amount (up to 6 decimals) for crypto-funded and fiat-to-crypto
                flows.
            fx:
              type: object
              description: >-
                FX detail — present only for flows with a currency conversion
                (crypto-funded and fiat-to-crypto). Absent for fiat-to-bank.
              required:
                - commercial_rate
                - applied_rate
                - base_markup_rate
                - client_markup_rate
                - markup_cost
              properties:
                commercial_rate:
                  type: string
                  description: >-
                    Mid-market reference rate used for the conversion (USD per
                    unit of crypto).
                mid_market_rate:
                  type: string
                  description: >-
                    Alias of `commercial_rate` with explicit naming. May be
                    absent.
                applied_rate:
                  type: string
                  description: Rate actually applied after markup. Display-only.
                base_markup_rate:
                  type: string
                client_markup_rate:
                  type: string
                markup_cost:
                  type: string
                  description: USD captured by Kira as FX-spread revenue.
                depeg_loss:
                  type: string
                  description: >-
                    USD lost to peg drift, shown as a separate deduction so it
                    does not inflate Kira revenue. Present only when the
                    stablecoin trades below par.
            total_fees:
              type: string
              description: Total fees deducted from the source amount.
            total:
              type: string
              description: Alias of `total_fees` (identical value).
        recipient_amount:
          type: string
          description: >-
            Amount the recipient receives after fees. USD with 2 decimals for
            bank rails; the stablecoin amount with up to 6 decimals for
            fiat-to-crypto.
        recipient_currency:
          type: string
          description: '`USD` for bank rails; `USDC`/`USDT` for fiat-to-crypto.'
        quote_id:
          type: string
          format: uuid
          description: >-
            The reserved quote. Redeem it on `POST
            /v1/virtual-accounts/{virtual_account_id}/payout` to lock the quoted
            amount, fees, and rate. Single-use; the quote must belong to the
            same client and not be expired or already redeemed.
        quote_expires_at:
          type: string
          description: >-
            ISO-8601 expiry. Default quote lifespan is 15 minutes; re-quote if
            it lapses.
        payment_instructions:
          type: object
          description: Echoed back only when the request supplied it.
          properties:
            network:
              type: string
              enum:
                - solana
                - polygon
                - tron
            currency:
              type: string
              enum:
                - USDC
                - USDT
    ValidationErrorResponse:
      type: object
      description: >-
        Validation / request error. The body shape is **not uniform** across the
        API — it varies by endpoint and by which validation layer rejects the
        request. The fields below are the union of what may appear; treat them
        all as optional. Observed shapes include `{ code, message }`, `{ code,
        message, errors[] }`, `{ code, error, details[] }`, `{ error, details[]
        }`, and a nested `{ error: { code, message, details } }`. Always branch
        on the HTTP status, not on a fixed body shape.
      properties:
        code:
          type: string
        message:
          type: string
        error:
          type:
            - string
            - object
          description: >-
            A short error label (e.g. `"Invalid data"`), or on some endpoints a
            nested `{ code, message, details }` object.
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
            required:
              - field
              - message
        details:
          type:
            - array
            - object
          description: >-
            Per-issue detail. Shape varies by endpoint — typically an array of
            `{ message }` or `{ path, message, code }`, occasionally an object.
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
        code:
          type: string
        statusCode:
          type: number
        error:
          type: string
        timestamp:
          type: string
        path:
          type: string
        details: {}
      required:
        - message
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Access token from `POST /auth` (the `data.access_token` value).
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key issued by Kira. Required on every request, including `/auth`.

````