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

# Execute a payout

> Send money out of a virtual account.

`mode` decides where the money comes from: `FIAT` spends the account's balance and needs a `recipient_id`, `CRYPTO` funds the payout from a deposit you make to a temporary address. Redeem a `quote_id` from a preview to settle at exactly that price.



## OpenAPI

````yaml /openapi/kira-api.2026-04-14.json post /v1/virtual-accounts/{virtual_account_id}/payout
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: Recipients
  - name: Quotations
  - name: Payouts
  - name: Reference
paths:
  /v1/virtual-accounts/{virtual_account_id}/payout:
    post:
      tags:
        - Payouts
      summary: Execute a payout
      description: >-
        Send money out of a virtual account.


        `mode` decides where the money comes from: `FIAT` spends the account's
        balance and needs a `recipient_id`, `CRYPTO` funds the payout from a
        deposit you make to a temporary address. Redeem a `quote_id` from a
        preview to settle at exactly that price.
      operationId: post_v1-virtual-accounts-virtual-account-id-payout
      parameters:
        - in: path
          name: virtual_account_id
          required: true
          schema:
            type: string
            format: uuid
          description: The account the money leaves from.
        - in: header
          name: X-Api-Version
          required: false
          description: >-
            Version applied to this request. It wins over your account's pinned
            version — see [Versioning](/using-the-api/versioning).
          schema:
            type: string
            example: '2026-04-14'
        - in: header
          name: Idempotency-Key
          required: true
          schema:
            type: string
            format: uuid
            example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
          description: >-
            A UUID you generate for this call. Retrying with the same key
            returns the first payout instead of sending a second one; reusing it
            with a different body is rejected with a `409`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PayoutRequest'
            examples:
              fiat:
                summary: From the account balance to a saved recipient
                value:
                  amount: '1000.00'
                  mode: FIAT
                  recipient_id: cccccccc-dddd-eeee-ffff-000000000000
                  nature_of_payment: vendor
                  reference: INV-2026-0042
                  supporting_documents:
                    - type: invoice
                      file: data:application/pdf;base64,JVBERi0xLjQK…
              quoted:
                summary: Redeeming a price from a preview
                value:
                  amount: '1000.00'
                  mode: FIAT
                  recipient_id: cccccccc-dddd-eeee-ffff-000000000000
                  quote_id: dddddddd-eeee-ffff-0000-111111111111
              crypto:
                summary: Funded by a USDC deposit
                value:
                  amount: '1000.00'
                  mode: CRYPTO
                  recipient_id: cccccccc-dddd-eeee-ffff-000000000000
                  payment_instructions:
                    network: polygon
                    currency: USDC
                  nature_of_payment: first_party
      responses:
        '201':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayoutResult'
              example:
                id: 99999999-aaaa-bbbb-cccc-dddddddddddd
                virtual_account_id: 11111111-2222-3333-4444-555555555555
                recipient_id: cccccccc-dddd-eeee-ffff-000000000000
                status: PENDING
                amount: '1000.00'
                currency: USD
                fees:
                  base_fees:
                    bank_account_fee: '10.00'
                    bank_account_fee_percentage: '0.00'
                    fixed_fee: '0.00'
                    percentage_fee: '2.50'
                    total: '12.50'
                  client_markup:
                    fixed_fee: '1.00'
                    percentage_fee: '0.00'
                    total: '1.00'
                  network_fee: '0.00'
                  total_fees: '13.50'
                  total: '13.50'
                recipient_amount: '986.50'
                recipient_currency: USD
                created_at: '2026-09-01T12:00:00.000Z'
                metadata: {}
        '400':
          description: >-
            The request was rejected. Two different bodies arrive with this
            status, so read `error` before anything else:


            - **`Invalid data`** — a field in the body is missing or malformed.
            `details` names each problem.

            - **`Bad Request`** — the body was fine but the payout cannot be
            priced: the account has not enough balance, or the amount cannot
            carry the fees.
          content:
            application/json:
              examples:
                document:
                  summary: A supporting document is not valid base64 or is over 3 MB
                  value:
                    code: validation_error
                    error: Invalid data
                    details:
                      - message: >-
                          supporting_documents.0.file is Invalid base64 content
                          or file size exceeds 3MB
                field:
                  summary: A field in the body is missing or wrong
                  value:
                    code: validation_error
                    error: Invalid data
                    details:
                      - message: amount is Amount must be greater than zero
                balance:
                  summary: The account cannot cover the payout
                  value:
                    statusCode: 400
                    error: Bad Request
                    message: Insufficient balance for this payout
                    timestamp: '2026-09-01T12:00:00.000Z'
                    path: >-
                      /v1/virtual-accounts/11111111-2222-3333-4444-555555555555/payout
        '401':
          description: >-
            Your credentials could not be read. The message talks about routing,
            but the cause is one of these:


            - The `Authorization` header is missing.

            - The token is not a token, or was not issued for your account.

            - The `x-api-key` header is missing or wrong.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: invalid_request
                message: >-
                  The request could not be matched to a valid route, or was
                  malformed. Verify the path and HTTP method against the API
                  reference. This is a routing or request error, not a
                  credentials or signature problem.
        '404':
          description: >-
            No account of yours has that `virtual_account_id`, or the
            `recipient_id` does not belong to you.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    description: Repeats the HTTP status.
                  error:
                    type: string
                    description: Always `Not Found`.
                  message:
                    type: string
                    description: What went wrong, in one sentence.
                  timestamp:
                    type: string
                    description: When the call was rejected, as an ISO 8601 timestamp.
                  path:
                    type: string
                    description: The path you called.
                  code:
                    type: string
                    description: A short machine-readable reason.
              example:
                statusCode: 404
                error: Not Found
                message: Virtual account 11111111-2222-3333-4444-555555555555 not found
                timestamp: '2026-09-01T12:00:00.000Z'
                path: >-
                  /v1/virtual-accounts/11111111-2222-3333-4444-555555555555/payout
        '422':
          description: >-
            The request was fine but the payout cannot go ahead — most often a
            missing supporting document, or a recipient whose rail this account
            does not serve.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    description: Repeats the HTTP status.
                  error:
                    type: string
                    description: Always `Unprocessable Entity`.
                  message:
                    type: string
                    description: What went wrong, in one sentence.
                  timestamp:
                    type: string
                    description: When the call was rejected, as an ISO 8601 timestamp.
                  path:
                    type: string
                    description: The path you called.
                  code:
                    type: string
                    description: A short machine-readable reason.
              example:
                statusCode: 422
                error: Unprocessable Entity
                message: A supporting document is required for this payout
                timestamp: '2026-09-01T12:00:00.000Z'
                path: >-
                  /v1/virtual-accounts/11111111-2222-3333-4444-555555555555/payout
      security:
        - bearerAuth: []
          apiKeyAuth: []
      servers:
        - url: https://api.balampay.com/sandbox
          description: Sandbox
        - url: https://api.balampay.com
          description: Production
components:
  schemas:
    PayoutRequest:
      type: object
      properties:
        amount:
          type: string
          description: >-
            How much to send in USD, as a positive decimal string with up to 8
            decimals. With `inverse_calculation` this is what the recipient
            should end up with instead.
        mode:
          type: string
          enum:
            - FIAT
            - CRYPTO
          description: >-
            Where the money comes from. `FIAT` spends the account's balance and
            requires `recipient_id`; `CRYPTO` funds the payout from a deposit
            you make. When you omit it, sending `payment_instructions` means
            `CRYPTO`.
        recipient_id:
          type: string
          format: uuid
          description: >-
            Who gets paid. Required on a `FIAT` payout. Where the rail accepts
            only Latin characters, creating the payout rejects a recipient name
            or address field written entirely in another script with a 400
            naming the field (for example `address.street_name`); accented
            characters pass (José becomes Jose).
        quote_id:
          type: string
          format: uuid
          description: >-
            A `quote_id` from a preview. Sending it settles at exactly the
            amounts, fees and rate you were quoted.
        inverse_calculation:
          type: boolean
          description: >-
            Work backwards: treat `amount` as what the recipient receives and
            work out what leaves the account. `false` when you omit it.
        client_markup:
          type: object
          description: >-
            Your own fees for this one payout, replacing whatever is configured
            on your account. `fixed_fee` and `percentage_fee` are both required
            once you send the object.
          properties:
            fixed_fee:
              type: string
              description: A flat charge, as a decimal string with up to 2 decimals.
            percentage_fee:
              type: string
              description: >-
                A share of the amount, as a decimal between `0` and `1` — `0.01`
                is 1%.
            fx_markup:
              type: string
              description: Your cut of the currency conversion.
          required:
            - fixed_fee
            - percentage_fee
        payment_instructions:
          type: object
          description: >-
            The token and chain you will deposit to fund the payout. Sending
            this makes it crypto-funded, and the address to deposit to comes
            back on the response.
          properties:
            network:
              type: string
              enum:
                - solana
                - polygon
                - tron
              description: Chain you will deposit on.
            currency:
              type: string
              enum:
                - USDC
                - USDT
              description: Token you will deposit.
          required:
            - network
            - currency
        nature_of_payment:
          type: string
          enum:
            - vendor
            - pobo
            - first_party
            - spot_3p
            - spot_1p
            - related_entities
            - other
          description: >-
            What the payout is for. It decides whether a supporting document is
            required — see [Payout
            values](/reference/payouts/values#nature_of_payment).
        supporting_documents:
          type: array
          minItems: 1
          maxItems: 2
          description: >-
            Proof of what the payout is for. One or two files, at most one of
            each type. A crypto payout needs one unless `nature_of_payment` is
            `first_party`.
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - invoice
                  - other
                description: What the file is.
              file:
                type: string
                description: >-
                  The file as a base64 data URI —
                  `data:application/pdf;base64,…`. PDF, PNG or JPG, up to 3 MB
                  before encoding.
              description:
                type: string
                maxLength: 255
                description: A note about the file, for your own records.
            required:
              - type
              - file
        reference:
          type: string
          description: >-
            Your own reference for the payout. It comes back unchanged on a
            read. A few prefixes are reserved and rejected.
        extra_info:
          type: object
          description: Your own notes on the payout. They come back on a read.
          properties:
            memo:
              type: string
              description: >-
                Short note that travels with the payment where the rail allows
                it.
            invoice_number:
              type: string
              description: Your invoice number. Up to 100 characters.
            internal_notes:
              type: string
              description: A note for your own records. Up to 1000 characters.
        metadata:
          type: object
          additionalProperties:
            type: string
          description: >-
            Your own key/value pairs, returned unchanged. Up to 50 keys. A key
            is 1 to 40 characters and cannot contain `[` or `]`; a value is up
            to 500 characters.


            Set at creation only — a payout cannot be changed afterwards.
      required:
        - amount
    PayoutResult:
      type: object
      description: Every amount is a decimal string.
      properties:
        id:
          type: string
          format: uuid
          description: Payout UUID. Use it to read the payout later.
        virtual_account_id:
          type: string
          format: uuid
          description: The account the money leaves from.
        recipient_id:
          type: string
          format: uuid
          description: Who gets paid.
        status:
          type: string
          description: >-
            Where the payout has got to — see [Payout
            values](/reference/payouts/values#payout-status).
        amount:
          type: string
          description: What leaves the account.
        currency:
          type: string
          description: Currency of `amount`. Always `USD`.
        fees:
          $ref: '#/components/schemas/PayoutFees'
        recipient_amount:
          type: string
          description: What the recipient ends up with.
        recipient_currency:
          type: string
          description: Currency of `recipient_amount`.
        payment_instructions:
          type: object
          additionalProperties: true
          description: >-
            The funding token and chain, echoed back. Only on a crypto-funded
            payout.
        deposit_instructions:
          type: object
          additionalProperties: true
          description: >-
            Where to deposit to fund the payout, on a crypto-funded one. Nothing
            moves until that deposit arrives.
        quote_id:
          type: string
          format: uuid
          description: The quote you redeemed, when you sent one.
        quote_expires_at:
          type: string
          description: When that quote stops holding, as an ISO 8601 timestamp.
        created_at:
          type: string
          description: When the payout was created, as an ISO 8601 timestamp.
        metadata:
          type: object
          description: >-
            The key/value pairs you sent, returned unchanged. `{}` when you sent
            none.
          additionalProperties: true
    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
    PayoutFees:
      type: object
      description: What comes off the amount before the recipient is paid.
      properties:
        base_fees:
          type: object
          description: What Kira charged, each a decimal string.
          properties:
            bank_account_fee:
              type: string
              description: The rail's own flat charge.
            bank_account_fee_percentage:
              type: string
              description: The rail's own percentage charge.
            fixed_fee:
              type: string
              description: A flat charge.
            percentage_fee:
              type: string
              description: A charge worked out from the amount.
            conversion_on_ramp_fee:
              type: string
              description: >-
                Charge for turning USD into a token. Only on a payout that
                converts.
            total:
              type: string
              description: This group added up.
        client_markup:
          type: object
          description: What you charged, each a decimal string.
          properties:
            fixed_fee:
              type: string
              description: A flat charge.
            percentage_fee:
              type: string
              description: A charge worked out from the amount.
            conversion_on_ramp_fee:
              type: string
              description: >-
                Charge for turning USD into a token. Only on a payout that
                converts.
            total:
              type: string
              description: This group added up.
        network_fee:
          type: string
          description: >-
            The chain's transfer cost. `0` when the payout does not touch a
            chain.
        fx:
          type: object
          description: >-
            How the conversion was priced. Only on a payout that converts
            between USD and a token.
          properties:
            commercial_rate:
              type: string
              description: >-
                Reference market rate, in USD per unit of the token. Shown for
                display.
            mid_market_rate:
              type: string
              description: The same value as `commercial_rate`, under a clearer name.
            applied_rate:
              type: string
              description: The reference rate less the markup. Shown for display only.
            base_markup_rate:
              type: string
              description: Kira's share of the spread, as a rate.
            client_markup_rate:
              type: string
              description: Your share of the spread, as a rate.
            markup_cost:
              type: string
              description: What the spread comes to in USD.
            depeg_loss:
              type: string
              description: >-
                USD given up because the token was trading below parity. Kept
                separate so it is not read as revenue.
        total_fees:
          type: string
          description: >-
            `base_fees.total` and `client_markup.total` added up. `network_fee`
            is not in it — add that separately on a payout delivered as digital
            currency.
        total:
          type: string
          description: The same value as `total_fees`.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        The `data.access_token` value from [Get access
        token](/api-reference/authentication/get-access-token).
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key issued by Kira.

````