> ## Documentation Index
> Fetch the complete documentation index at: https://public-openfx.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# List financial accounts

> List the financial accounts your organization can currently use to fund a payout settling in a given `receiveCurrency`.



## OpenAPI

````yaml api-reference/openapi-v3-payments.json GET /v3/common/financial-accounts
openapi: 3.1.0
info:
  title: 'OpenFX v3: Payouts & Accounts API'
  version: 3.0.0
  contact:
    name: OpenFX Support
    email: support@openfx.com
    url: https://www.openfx.com
  license:
    name: Proprietary — © OpenFX. All rights reserved.
    url: https://www.openfx.com/terms-and-conditions
  description: >-
    One reference for paying out to your accounts on OpenFX v3. It covers the

    accounts you pay, the payout addresses they own, and the payouts you send
    them.

    An account carries its identity and a `status`, its standing with OpenFX as
    a whole.

    Each payout address holds the routable identifiers its country requires, and

    carries the acts the platform ran against it in `verifications[]`; its own
    `status`

    reports whether the address can back a payout. A payout is priced by a
    quote, created in

    `REQUIRES_CONFIRMATION`, confirmed, and then settled. See the

    [Payout flow](/v3/payouts) guide for the full payout state machine

    and the webhooks emitted at each step.


    **Core concepts.** [Authentication](/v3/authentication), for the token every
    request

    carries. [Idempotency keys](/v3/idempotency), for the header every write
    carries.

    [Metadata](/v3/metadata-and-tracing#withdrawal-metadata), for the object of
    your own key/value strings you attach when

    creating a record. [Pagination](/v3/pagination), for the cursors every list
    returns.

    [Identifiers](/v3/resource-ids), for the typed-prefix ids every resource
    carries.

    [Webhook delivery](/v3/webhooks/setup), for the signed deliveries and their
    retry window.

    [Rate limiting](/v3/rate-limiting), for the per-organization limit and the
    headers that report it.


    **Responses.** Reads and writes both return `{ data }`; lists return `{
    data, pagination }`.

    Every error returns `{ error }` with a stable `code` and a coarse `type`;
    branch on

    `error.code` or `error.type`, never on `error.message`. Every error `code`
    is

    registered under exactly one status; see `ErrorType`'s `CONFLICT` entry for
    the one

    exception.


    **Conventions.** Request bodies must be `application/json` (UTF-8), and
    unrecognized fields

    are rejected rather than silently dropped. An id belonging to another
    organization returns

    `404`, indistinguishable from one that never existed. An unknown route
    returns

    `404 ROUTE_NOT_FOUND`; a known route called with the wrong method returns

    `405 METHOD_NOT_ALLOWED` with an `Allow` header.


    **Forward compatibility.** The API evolves additively: new optional request
    fields, new

    response fields, new members on open enums, and new error codes can ship
    without a version

    bump. Keep a default branch on `error.code`/`error.type` and tolerate
    unrecognized enum

    values. Only removing or renaming a field, tightening a type, or changing a
    status mapping

    is a breaking change.
servers:
  - url: https://api.openfx.com
    description: Production gateway.
security:
  - bearerAuth: []
    requestSignature: []
tags:
  - name: Accounts
    description: >-
      The people and companies you send payouts to.


      An account is one identity, with one or more payout addresses they can be
      paid at.
  - name: Accounts webhooks
    description: >-
      Deliveries for an account's own lifecycle and its capabilities: creation,
      its

      `status` transitions, and each capability cell's request and settle
      events.


      `data` carries the account without its `identity` block, which is never
      delivered

      to a webhook endpoint; read it from GET /v3/common/accounts/{accountId}.


      See [Webhook authentication](/v3/webhooks/authentication) for the signing
      formula

      and how to verify a delivery.
  - name: Addresses
    description: >-
      The destinations an account can be paid at: bank accounts.


      A payout address is typed by its routing shape rather than by a region:
      `bankAccount`

      is discriminated on `routingFamily`, which selects the identifiers that
      route to it,

      an IBAN for `SEPA`, an account number and a BIC for `SWIFT`, and the
      Indian identifier set

      for `IN_LOCAL`. The response reports

      a derived `country` read off those identifiers, and `supportedRails`
      follows the

      routing family together with the identifiers supplied under it.


      Each address carries `verifications[]`, the acts the platform ran against
      it. A name

      match runs when the address is created wherever the scheme that pays it
      offers one,

      comparing the asserted `accountHolderName` with the name the receiving
      institution

      has registered; an account only SWIFT can reach has no such scheme, so its

      `verifications[]` stays empty. Its `status` is derived from those acts
      together

      with the platform's own setup, and says whether it can be paid right now.


      The record is immutable apart from archiving, so correcting anything on it
      means creating

      a replacement and archiving the old one.
  - name: Addresses webhooks
    description: >-
      Deliveries for a payout address's own lifecycle: creation, its `status`

      transitions, and each name-match verification's outcome.


      `data` carries the address without `bankAccount`, and each verification
      act

      without its `providedName` and `registeredName` strings; none of the three
      is

      ever delivered to a webhook endpoint. Read them from

      GET /v3/payments/payout-addresses/{payoutAddressId}.


      See [Webhook authentication](/v3/webhooks/authentication) for the signing
      formula

      and how to verify a delivery.
  - name: Payouts
    description: >-
      Payout quotes, payout creation, confirmation, and lifecycle.


      Every payout here is outbound: it debits one of your own financial
      accounts and credits

      the receiving account's payout address.


      A quote is an immutable, time-bounded FX price snapshot. Apply its id as
      `quoteId` on a

      payout to lock in its rate before it expires. A payout is created in

      `REQUIRES_CONFIRMATION` with no funds moved, carrying every entry in
      `confirmations[]` it

      will ever carry; POST .../confirm acknowledges them all atomically and
      moves funds.
  - name: Payouts webhooks
    description: >-
      Deliveries for a payout's own lifecycle: creation, then one per status
      transition

      from `REQUIRES_CONFIRMATION` through to a terminal state.


      `data` carries the payout with each name-bearing confirmation entry
      stripped of

      its `providedName` and `registeredName` strings, which are never delivered
      to a

      webhook endpoint; read them from GET /v3/payments/payouts/{payoutId}.


      See [Webhook authentication](/v3/webhooks/authentication) for the signing
      formula

      and how to verify a delivery.
  - name: Financial accounts
    description: >-
      The financial accounts your organization funds payouts from.


      A financial account is one of your own balances with OpenFX, held in a
      single currency.

      Every payout debits one, named by `financialAccountId`. This endpoint
      lists the financial

      accounts that can currently source a payout settling in a given
      `receiveCurrency`.
  - name: Changelog
  - name: Authentication
  - name: Idempotency keys
  - name: Metadata
  - name: Pagination
  - name: Identifiers
  - name: Webhook delivery
  - name: Rate limiting
  - name: Payout flow
  - name: EUR payout integration guide
  - name: INR payout integration guide
  - name: Working with capabilities
  - name: Capability requirements
  - name: Account, capability and payout address lifecycle
  - name: Request signing
  - name: Webhook handling
paths:
  /v3/common/financial-accounts:
    get:
      tags:
        - Financial accounts
      summary: List financial accounts available to fund a payout
      description: >-
        List the financial accounts your organization can currently use to fund
        a payout

        settling in a given `receiveCurrency`.


        The result is the set of financial accounts your organization can source
        such a payout

        from, same-currency (no-FX) and cross-currency funders alike, subject to
        your

        organization's entitlements. The list is not paginated: the whole set
        comes back at

        once, in no guaranteed order.


        An empty list means your organization is enabled for `receiveCurrency`
        but holds no

        financial account that can currently source it; not being enabled for
        that currency at

        all returns 403 PAYOUT_CURRENCY_NOT_ENABLED instead. See
        `FinancialAccount`.
      operationId: listFinancialAccounts
      parameters:
        - $ref: '#/components/parameters/XAppMode'
        - $ref: '#/components/parameters/XRequestId'
        - in: query
          name: receiveCurrency
          schema:
            $ref: '#/components/schemas/CurrencyCode'
            description: >-
              Currency the payout settles in on the receive side. The response
              is narrowed to the financial accounts that can source a payout
              delivering this currency.
            example: INR
          required: true
          description: >-
            Currency the payout settles in on the receive side. The response is
            narrowed to the financial accounts that can source a payout
            delivering this currency.
      responses:
        '200':
          description: >-
            The financial accounts available to fund a `receiveCurrency` payout
            (non-paginated). May be empty when your organization is enabled for
            the currency but has no eligible financial account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FinancialAccountList'
              examples:
                sepaEur:
                  summary: Financial accounts that can fund a EUR payout
                  description: >-
                    Response to `?receiveCurrency=EUR`: a USD financial account
                    and a USDC financial account, each funding via FX. The `id`
                    of either drops into `financialAccountId` on the quote.
                    Balances carry either sign: the USDC account stands in debit
                    at this snapshot, and its listing here is eligibility, not
                    fund sufficiency, which is checked at quote and payout time.
                  value:
                    data:
                      - object: financialAccount
                        id: finacc_AmKC5dMVXUbiAW8VzKBfqz
                        currency: USD
                        label: USD - FX Balance
                        availableBalance: '48250.000000'
                        totalBalance: '50000.000000'
                      - object: financialAccount
                        id: finacc_KPQmMzAqLPU5QRtTjrY8Hk
                        currency: USDC
                        label: USDC - FX Balance
                        availableBalance: '-3100.000000'
                        totalBalance: '-2600.000000'
                inrUsd:
                  summary: Financial accounts that can fund an INR payout
                  description: >-
                    Response to `?receiveCurrency=INR`: a USD financial account
                    that funds via USD to INR FX. An INR payout is always
                    cross-currency, since the financial account you debit is
                    never itself in INR.
                  value:
                    data:
                      - object: financialAccount
                        id: finacc_AmKC5dMVXUbiAW8VzKBfqz
                        currency: USD
                        label: USD - FX Balance
                        availableBalance: '48250.000000'
                        totalBalance: '50000.000000'
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
        '400':
          description: >-
            `receiveCurrency` is missing, malformed, or not a currency this
            platform supports: VALIDATION_QUERY_FAILED. Every request is also
            checked for a well-formed gateway context: MISSING_REQUEST_CONTEXT /
            INVALID_ORGANIZATION.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                VALIDATION_QUERY_FAILED:
                  value:
                    error:
                      code: VALIDATION_QUERY_FAILED
                      type: VALIDATION_ERROR
                      message: >-
                        A query parameter is missing, malformed, or not an
                        accepted value.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        issues:
                          - path: /receiveCurrency
                            code: invalid_type
                            message: Required
                            expected: string
                            received: undefined
                        firstIssuePath: /receiveCurrency
                MISSING_REQUEST_CONTEXT:
                  value:
                    error:
                      code: MISSING_REQUEST_CONTEXT
                      type: VALIDATION_ERROR
                      message: >-
                        The organization, user, or idempotency context every
                        request carries was absent or unreadable. Send the
                        request through the documented gateway.
                      retryStrategy: FIX_AND_RESUBMIT
                      details: {}
                INVALID_ORGANIZATION:
                  value:
                    error:
                      code: INVALID_ORGANIZATION
                      type: VALIDATION_ERROR
                      message: >-
                        The organization identifier on the request is malformed.
                        Send the request through the documented gateway.
                      retryStrategy: FIX_AND_RESUBMIT
                      details: {}
                INVALID_APP_MODE:
                  value:
                    error:
                      code: INVALID_APP_MODE
                      type: VALIDATION_ERROR
                      message: >-
                        The x-app-mode header is invalid. When present, it must
                        be either 'LIVE' or 'SANDBOX'.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        received: PRODUCTION
                        allowed:
                          - LIVE
                          - SANDBOX
                validation_header_failed:
                  summary: VALIDATION_HEADER_FAILED
                  value:
                    error:
                      code: VALIDATION_HEADER_FAILED
                      type: VALIDATION_ERROR
                      message: >-
                        The X-Request-Id header is invalid. When present, it
                        must be 1-200 characters using only letters, digits,
                        '-', '_', and '.'.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        issues:
                          - path: X-Request-Id
                            code: invalid_format
                            message: >-
                              The X-Request-Id header is invalid. When present,
                              it must be 1-200 characters using only letters,
                              digits, '-', '_', and '.'.
                        firstIssuePath: X-Request-Id
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
        '401':
          description: >-
            Authentication failed: the bearer token or the request signature did
            not verify.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                AUTH_TOKEN_MISSING:
                  value:
                    error:
                      code: AUTH_TOKEN_MISSING
                      type: AUTHENTICATION_ERROR
                      message: No Authorization header was present on the request.
                      retryStrategy: TERMINAL
                      details: {}
                AUTH_TOKEN_INVALID:
                  value:
                    error:
                      code: AUTH_TOKEN_INVALID
                      type: AUTHENTICATION_ERROR
                      message: >-
                        The bearer JWT or its request signature failed
                        verification, whether from a bad or missing signature or
                        a reused nonce.
                      retryStrategy: TERMINAL
                      details: {}
                AUTH_TOKEN_EXPIRED:
                  value:
                    error:
                      code: AUTH_TOKEN_EXPIRED
                      type: AUTHENTICATION_ERROR
                      message: The JWT's exp claim is already in the past.
                      retryStrategy: TERMINAL
                      details: {}
                AUTH_TOKEN_INVALID_CONFIG:
                  value:
                    error:
                      code: AUTH_TOKEN_INVALID_CONFIG
                      type: AUTHENTICATION_ERROR
                      message: >-
                        The JWT was minted with exp more than 60 seconds after
                        iat, or another claim outside the required shape.
                      retryStrategy: TERMINAL
                      details: {}
                AUTH_API_KEY_INVALID:
                  value:
                    error:
                      code: AUTH_API_KEY_INVALID
                      type: AUTHENTICATION_ERROR
                      message: >-
                        The API key behind the token has been revoked or no
                        longer exists.
                      retryStrategy: TERMINAL
                      details: {}
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
        '403':
          description: >-
            Your organization isn't enabled for payouts in the requested
            `receiveCurrency`: PAYOUT_CURRENCY_NOT_ENABLED.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                PAYOUT_CURRENCY_NOT_ENABLED:
                  value:
                    error:
                      code: PAYOUT_CURRENCY_NOT_ENABLED
                      type: AUTHORIZATION_ERROR
                      message: >-
                        Your organization isn't enabled for payouts in the
                        requested receiveCurrency.
                      retryStrategy: TERMINAL
                      details:
                        receiveCurrency: INR
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
        '429':
          description: >-
            Rate limit exceeded. Wait `Retry-After` seconds before retrying, or
            compute the wait from `RateLimit-Reset` (also a duration in
            seconds).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                RATE_LIMIT_EXCEEDED:
                  value:
                    error:
                      code: RATE_LIMIT_EXCEEDED
                      type: RATE_LIMITED
                      message: Rate limit exceeded. Retry after the indicated wait.
                      retryStrategy: WAIT_THEN_RETRY_SAME_KEY
                      details: {}
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
        '500':
          description: An unexpected error occurred on our side.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                INTERNAL_ERROR:
                  value:
                    error:
                      code: INTERNAL_ERROR
                      type: INTERNAL_ERROR
                      message: >-
                        An unexpected error occurred. Check the state of the
                        resource before retrying writes; for reads, retry with
                        backoff. Contact the support desk if the failure
                        persists.
                      retryStrategy: CHECK_STATE_THEN_RETRY
                      details: {}
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-Request-Timestamp:
              $ref: '#/components/headers/XRequestTimestamp'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
components:
  parameters:
    XAppMode:
      in: header
      name: X-App-Mode
      schema:
        default: SANDBOX
        example: SANDBOX
        description: >-
          Which environment this request runs against.


          An omitted header means `SANDBOX`. Send it explicitly on every call
          rather than relying

          on that default, so live money movement is never missed because a
          header was forgotten: a live API key that reaches a live instance
          without an explicit LIVE value is rejected with
          AUTH_API_KEY_SANDBOX_REQUIRED. When present, the value must be
          `SANDBOX` or `LIVE`, matched without regard to case. Any other value,
          including an empty one, returns `400` `INVALID_APP_MODE`;
          `details.received` echoes the value you sent.
        type: string
        enum:
          - SANDBOX
          - LIVE
      description: >-
        Which environment this request runs against.


        An omitted header means `SANDBOX`. Send it explicitly on every call
        rather than relying

        on that default, so live money movement is never missed because a header
        was forgotten: a live API key that reaches a live instance without an
        explicit LIVE value is rejected with AUTH_API_KEY_SANDBOX_REQUIRED. When
        present, the value must be `SANDBOX` or `LIVE`, matched without regard
        to case. Any other value, including an empty one, returns `400`
        `INVALID_APP_MODE`; `details.received` echoes the value you sent.
    XRequestId:
      in: header
      name: X-Request-Id
      schema:
        example: 9f2c1b7e-4d3a-4f81-9c2e-6b0a5d7e1f34
        description: >-
          Your own correlation id for this request, returned on the response
          exactly as you sent it.


          Optional. Where you send none the response omits it, and the
          `X-Trace-Id` response

          header is the handle to correlate on instead.
        type: string
      description: >-
        Your own correlation id for this request, returned on the response
        exactly as you sent it.


        Optional. Where you send none the response omits it, and the
        `X-Trace-Id` response

        header is the handle to correlate on instead.
  schemas:
    CurrencyCode:
      type: string
      pattern: ^[A-Z0-9]{2,15}$
      description: >-
        Uppercase currency code, matching `^[A-Z0-9]{2,15}$`.


        ISO 4217 for fiat; the canonical ticker for stablecoins (`USDC`,
        `USDT`). Case-sensitive,

        so a code is written in the exact case its standard gives it.
    FinancialAccountList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/FinancialAccount'
      required:
        - data
      additionalProperties: false
      description: >-
        The financial accounts your organization can currently fund a
        `receiveCurrency` payout from, one entry per `FinancialAccount`. See
        `listFinancialAccounts` for pagination and empty-list semantics.
    ErrorEnvelope:
      type: object
      description: >-
        The error body of every non-2xx response.


        All fields are always present. Every code and message here is OpenFX's
        own: a failed read

        collapses to `INTERNAL_ERROR`, and a failed write carries a domain code
        plus the affected

        resource id, so the client can GET the resource and decide whether to
        retry.
      required:
        - error
      additionalProperties: false
      properties:
        error:
          type: object
          description: The structured public error payload.
          required:
            - code
            - type
            - message
            - retryStrategy
            - details
          additionalProperties: false
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            type:
              $ref: '#/components/schemas/ErrorType'
            message:
              type: string
              description: >-
                Human-readable explanation. Not a stability contract, wording
                may change at any time; branch on `code`, never `message`.
              example: No account with that id in this organization.
            retryStrategy:
              $ref: '#/components/schemas/RetryStrategy'
            details:
              anyOf:
                - $ref: '#/components/schemas/ErrorDetailsACCOUNT_ARCHIVED'
                - $ref: '#/components/schemas/ErrorDetailsACCOUNT_HOLDER_MISMATCH'
                - $ref: '#/components/schemas/ErrorDetailsACCOUNT_NOT_ACTIVE'
                - $ref: '#/components/schemas/ErrorDetailsACCOUNT_NOT_FOUND'
                - $ref: >-
                    #/components/schemas/ErrorDetailsADDRESS_SERVES_NO_CAPABILITY
                - $ref: '#/components/schemas/ErrorDetailsAGREEMENTS_NOT_ACTIVE'
                - $ref: '#/components/schemas/ErrorDetailsAGREEMENTS_PENDING'
                - $ref: '#/components/schemas/ErrorDetailsAMOUNT_OUT_OF_RANGE'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_LIVE_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_API_KEY_MISSING'
                - $ref: >-
                    #/components/schemas/ErrorDetailsAUTH_API_KEY_SANDBOX_REQUIRED
                - $ref: '#/components/schemas/ErrorDetailsAUTH_FORBIDDEN_IP'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_INSUFFICIENT_SCOPE'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_EXPIRED'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_INVALID_CONFIG'
                - $ref: '#/components/schemas/ErrorDetailsAUTH_TOKEN_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsBANK_ACCOUNT_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsBENEFICIARY_DETAILS_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsCAPABILITY_DUPLICATE'
                - $ref: '#/components/schemas/ErrorDetailsCAPABILITY_NOT_ACTIVE'
                - $ref: '#/components/schemas/ErrorDetailsCURRENCY_NOT_SUPPORTED'
                - $ref: '#/components/schemas/ErrorDetailsFEATURE_NOT_ENABLED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsFINANCIAL_ACCOUNT_CURRENCY_MISMATCH
                - $ref: '#/components/schemas/ErrorDetailsFINANCIAL_ACCOUNT_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_IN_FLIGHT'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_KEY_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_KEY_MISSING'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_MISMATCH'
                - $ref: '#/components/schemas/ErrorDetailsIDEMPOTENCY_UNAVAILABLE'
                - $ref: '#/components/schemas/ErrorDetailsIDENTITY_REQUIREMENT_UNMET'
                - $ref: '#/components/schemas/ErrorDetailsINTERNAL_ERROR'
                - $ref: '#/components/schemas/ErrorDetailsINVALID_ORGANIZATION'
                - $ref: '#/components/schemas/ErrorDetailsKYC_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsMETHOD_NOT_ALLOWED'
                - $ref: '#/components/schemas/ErrorDetailsMISSING_REQUEST_CONTEXT'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_ADDRESS_ARCHIVED'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_ADDRESS_CONFLICT'
                - $ref: >-
                    #/components/schemas/ErrorDetailsPAYOUT_ADDRESS_FIELD_MISSING
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_ADDRESS_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_ADDRESS_REJECTED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsPAYOUT_ADDRESS_VERIFICATION_FAILED
                - $ref: >-
                    #/components/schemas/ErrorDetailsPAYOUT_CANCELLATION_NOT_ALLOWED
                - $ref: >-
                    #/components/schemas/ErrorDetailsPAYOUT_CONFIRMATION_NOT_ALLOWED
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_CURRENCY_NOT_ENABLED'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_INSUFFICIENT_FUNDS'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_NOT_ENABLED'
                - $ref: '#/components/schemas/ErrorDetailsPAYOUT_NOT_FOUND'
                - $ref: >-
                    #/components/schemas/ErrorDetailsPAYOUT_TEMPORARILY_UNAVAILABLE
                - $ref: '#/components/schemas/ErrorDetailsPURPOSE_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_ALREADY_CONSUMED'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_EXPIRED'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_RAIL_UNAVAILABLE'
                - $ref: '#/components/schemas/ErrorDetailsQUOTE_REJECTED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsQUOTE_SEND_CURRENCY_UNAVAILABLE
                - $ref: >-
                    #/components/schemas/ErrorDetailsQUOTE_TEMPORARILY_UNAVAILABLE
                - $ref: '#/components/schemas/ErrorDetailsRATE_LIMIT_EXCEEDED'
                - $ref: '#/components/schemas/ErrorDetailsRECEIVER_MEMO_INVALID'
                - $ref: '#/components/schemas/ErrorDetailsROUTE_NOT_FOUND'
                - $ref: '#/components/schemas/ErrorDetailsSANDBOX_MODE_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsINVALID_APP_MODE'
                - $ref: '#/components/schemas/ErrorDetailsSENDER_ACCOUNT_REQUIRED'
                - $ref: '#/components/schemas/ErrorDetailsSENDER_NOT_SUPPORTED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_BODY_FAILED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_PATH_FAILED'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_QUERY_FAILED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsVERIFICATION_EXECUTION_FAILED
                - $ref: '#/components/schemas/ErrorDetailsUNSUPPORTED_MEDIA_TYPE'
                - $ref: '#/components/schemas/ErrorDetailsVALIDATION_HEADER_FAILED'
                - $ref: >-
                    #/components/schemas/ErrorDetailsVALIDATION_PAYLOAD_TOO_LARGE
              description: >-
                Additional, code-specific context. `{}`-shaped
                (EmptyErrorDetails) when empty, never null, never omitted.
    FinancialAccount:
      type: object
      properties:
        object:
          type: string
          const: financialAccount
          description: >-
            The type of object represented, a fixed discriminator. Always
            `"financialAccount"` for this resource, and identical across every
            object of the type.
          example: financialAccount
        id:
          $ref: '#/components/schemas/FinancialAccountId'
          description: >-
            Financial account identifier. Pass as `financialAccountId` on POST
            /v3/payments/payout-quotes (and so on the resulting payout) to debit
            this financial account.
          example: finacc_AmKC5dMVXUbiAW8VzKBfqz
        currency:
          $ref: '#/components/schemas/CurrencyCode'
          description: >-
            Currency this financial account holds and is debited in, and the
            `sendCurrency` of every quote and payout that names it as
            `financialAccountId`.
          example: USD
        label:
          type: string
          description: >-
            Human-readable name for this financial account. Use it to tell two
            financial accounts in the same currency apart in a UI or a picker.
          example: USD - FX Balance
        availableBalance:
          $ref: '#/components/schemas/PlatformAmount'
          description: >-
            Funds currently available to source a payout, denominated in this
            financial account's `currency`. Carries either sign: a negative
            value means held funds exceed `totalBalance`, so the account needs
            funding before it can source anything. A point-in-time snapshot
            only: fund sufficiency is authoritative at quote and payout time,
            never inferred from this value.
          example: '5000.000000'
        totalBalance:
          $ref: '#/components/schemas/PlatformAmount'
          description: >-
            Total balance including held or earmarked funds, denominated in this
            financial account's `currency`. Carries either sign: a negative
            value is a debit balance. `availableBalance` never exceeds it, and
            the difference between the two is the held portion.
          example: '5200.000000'
      required:
        - object
        - id
        - currency
        - label
        - availableBalance
        - totalBalance
      additionalProperties: false
      description: >-
        A financial account your organization holds with OpenFX, and the source
        a payout draws its funds from. See GET /v3/common/financial-accounts for
        the accounts that can currently source a payout in a given
        `receiveCurrency`.
    Timestamp:
      type: string
      format: date-time
      pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$
      description: UTC timestamp in RFC 3339 date-time form. Values end in Z.
      example: '2026-04-28T10:00:00.000Z'
    ErrorCode:
      type: string
      description: >-
        Stable, machine-readable error code. Format `<PRODUCT>_<ERROR>`. Once
        published, never renamed or removed without a major version bump.
      enum:
        - ACCOUNT_ARCHIVED
        - ACCOUNT_HOLDER_MISMATCH
        - ACCOUNT_NOT_ACTIVE
        - ACCOUNT_NOT_FOUND
        - ADDRESS_SERVES_NO_CAPABILITY
        - AGREEMENTS_NOT_ACTIVE
        - AGREEMENTS_PENDING
        - AMOUNT_OUT_OF_RANGE
        - AUTH_API_KEY_INVALID
        - AUTH_API_KEY_LIVE_REQUIRED
        - AUTH_API_KEY_MISSING
        - AUTH_API_KEY_SANDBOX_REQUIRED
        - AUTH_FORBIDDEN_IP
        - AUTH_INSUFFICIENT_SCOPE
        - AUTH_TOKEN_EXPIRED
        - AUTH_TOKEN_INVALID
        - AUTH_TOKEN_INVALID_CONFIG
        - AUTH_TOKEN_MISSING
        - BANK_ACCOUNT_NOT_FOUND
        - BENEFICIARY_DETAILS_MISSING
        - CAPABILITY_DUPLICATE
        - CAPABILITY_NOT_ACTIVE
        - CURRENCY_NOT_SUPPORTED
        - FEATURE_NOT_ENABLED
        - FINANCIAL_ACCOUNT_CURRENCY_MISMATCH
        - FINANCIAL_ACCOUNT_NOT_FOUND
        - IDEMPOTENCY_IN_FLIGHT
        - IDEMPOTENCY_KEY_INVALID
        - IDEMPOTENCY_KEY_MISSING
        - IDEMPOTENCY_MISMATCH
        - IDEMPOTENCY_UNAVAILABLE
        - IDENTITY_REQUIREMENT_UNMET
        - INTERNAL_ERROR
        - INVALID_ORGANIZATION
        - KYC_REQUIRED
        - METHOD_NOT_ALLOWED
        - MISSING_REQUEST_CONTEXT
        - PAYOUT_ADDRESS_ARCHIVED
        - PAYOUT_ADDRESS_CONFLICT
        - PAYOUT_ADDRESS_FIELD_MISSING
        - PAYOUT_ADDRESS_NOT_FOUND
        - PAYOUT_ADDRESS_REJECTED
        - PAYOUT_ADDRESS_VERIFICATION_FAILED
        - PAYOUT_CANCELLATION_NOT_ALLOWED
        - PAYOUT_CONFIRMATION_NOT_ALLOWED
        - PAYOUT_CURRENCY_NOT_ENABLED
        - PAYOUT_INSUFFICIENT_FUNDS
        - PAYOUT_NOT_ENABLED
        - PAYOUT_NOT_FOUND
        - PAYOUT_TEMPORARILY_UNAVAILABLE
        - PURPOSE_INVALID
        - QUOTE_ALREADY_CONSUMED
        - QUOTE_EXPIRED
        - QUOTE_NOT_FOUND
        - QUOTE_RAIL_UNAVAILABLE
        - QUOTE_REJECTED
        - QUOTE_SEND_CURRENCY_UNAVAILABLE
        - QUOTE_TEMPORARILY_UNAVAILABLE
        - RATE_LIMIT_EXCEEDED
        - RECEIVER_MEMO_INVALID
        - ROUTE_NOT_FOUND
        - SANDBOX_MODE_REQUIRED
        - INVALID_APP_MODE
        - SENDER_ACCOUNT_REQUIRED
        - SENDER_NOT_SUPPORTED
        - VALIDATION_BODY_FAILED
        - VALIDATION_PATH_FAILED
        - VALIDATION_QUERY_FAILED
        - VERIFICATION_EXECUTION_FAILED
        - VALIDATION_HEADER_FAILED
        - VALIDATION_PAYLOAD_TOO_LARGE
        - UNSUPPORTED_MEDIA_TYPE
    ErrorType:
      type: string
      enum:
        - VALIDATION_ERROR
        - AUTHENTICATION_ERROR
        - AUTHORIZATION_ERROR
        - NOT_FOUND
        - CONFLICT
        - RATE_LIMITED
        - INTERNAL_ERROR
      x-enum-descriptions:
        VALIDATION_ERROR: >-
          400 (schema/syntactic) or 422 (semantic/business-rule from the
          payload's values).
        AUTHENTICATION_ERROR: '401.'
        AUTHORIZATION_ERROR: 403 (scope/environment/product-access denial).
        NOT_FOUND: 404 (including cross-org access, never 403).
        CONFLICT: >-
          409 (state conflicts; exception: IDEMPOTENCY_MISMATCH is 422 but still
          `CONFLICT`).
        RATE_LIMITED: '429.'
        INTERNAL_ERROR: '500.'
      description: >-
        Closed `type` classifier, one of seven coarse buckets mapping to HTTP
        status.


        Clients branch on `code`/`type`, never `message`.


        Closed at any published point in time but non-exhaustive at runtime,
        keep a default branch

        falling back to `INTERNAL_ERROR`.
    RetryStrategy:
      type: string
      enum:
        - RETRY_SAME_KEY
        - WAIT_THEN_RETRY_SAME_KEY
        - FIX_AND_RESUBMIT
        - CHECK_STATE_THEN_RETRY
        - TERMINAL
      x-enum-descriptions:
        RETRY_SAME_KEY: Safe to retry immediately with the same Idempotency-Key.
        WAIT_THEN_RETRY_SAME_KEY: >-
          Retry the same key after a backoff: rate limiting and an in-flight
          conflict both land here.
        FIX_AND_RESUBMIT: Invalid request; correct the field(s) in `details` and resubmit.
        CHECK_STATE_THEN_RETRY: GET the resource first; safety depends on server-side state.
        TERMINAL: >-
          Do not retry. Neither a backoff nor a fresh Idempotency-Key changes
          the outcome.
      description: >-
        Closed, machine-actionable retry strategy on every error.


        Closed at any published point in time but non-exhaustive at runtime,
        keep a default branch.
    ErrorDetailsACCOUNT_ARCHIVED:
      type: object
      additionalProperties: false
      properties:
        accountId:
          type: string
          description: The archived account named by the request.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
      description: >-
        Structured context for `ACCOUNT_ARCHIVED`: The account named by the
        request is archived, a one-way state.
      required:
        - accountId
    ErrorDetailsACCOUNT_HOLDER_MISMATCH:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `ACCOUNT_HOLDER_MISMATCH`: The receiving-side
        account holder name check on the destination payout address returned a
        blocking result, or the account identifier is known bad.
    ErrorDetailsACCOUNT_NOT_ACTIVE:
      type: object
      additionalProperties: false
      properties:
        accountId:
          type: string
          description: The account named by the request.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
        status:
          type: string
          description: The account's current standing.
          example: REJECTED
      description: >-
        Structured context for `ACCOUNT_NOT_ACTIVE`: The account's standing with
        OpenFX is not ACTIVE.
      required:
        - accountId
        - status
    ErrorDetailsACCOUNT_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `ACCOUNT_NOT_FOUND`: The account identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsADDRESS_SERVES_NO_CAPABILITY:
      type: object
      additionalProperties: false
      properties:
        accountId:
          type: string
          description: The account the payout address would belong to.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
        required:
          type: object
          additionalProperties: false
          description: The capability coverage the address requires.
          properties:
            grant:
              type: string
              description: The capability grant the address requires.
              example: RECEIVE_PAYOUTS
            currency:
              type: string
              description: The currency the address receives in.
              example: INR
            repatriability:
              type: string
              description: >-
                The repatriability axis the address requires, for an INR
                address.
              example: NON_REPATRIABLE
          required:
            - grant
            - currency
            - repatriability
      description: >-
        Structured context for `ADDRESS_SERVES_NO_CAPABILITY`: The account the
        payout address would belong to holds no capability able to receive at
        it, in any status.
      required:
        - accountId
        - required
    ErrorDetailsAGREEMENTS_NOT_ACTIVE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AGREEMENTS_NOT_ACTIVE`: An agreement the
        organization needs exists but is not active, expired, or revoked.
    ErrorDetailsAGREEMENTS_PENDING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AGREEMENTS_PENDING`: An agreement the
        organization must accept before this payout can settle is still awaiting
        acceptance.
    ErrorDetailsAMOUNT_OUT_OF_RANGE:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry per offending amount field.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /receiveAmount
        amount:
          type: string
          description: The first issue's violating amount.
          example: '50.00'
        minimum:
          type: string
          description: The bound the amount crossed, where it is a floor.
          example: '100.00'
        maximum:
          type: string
          description: The bound the amount crossed, where it is a ceiling.
          example: '1000000.00'
        currency:
          type: string
          description: The currency of the amount and bound.
          example: INR
      description: >-
        Structured context for `AMOUNT_OUT_OF_RANGE`: The amount is outside the
        permitted range for payouts to this destination.
      required:
        - issues
    ErrorDetailsAUTH_API_KEY_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_INVALID`: The referenced API key
        does not exist or is inactive.
    ErrorDetailsAUTH_API_KEY_LIVE_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_LIVE_REQUIRED`: Live traffic uses a
        Sandbox API key.
    ErrorDetailsAUTH_API_KEY_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_MISSING`: The bearer token does not
        reference an API key.
    ErrorDetailsAUTH_API_KEY_SANDBOX_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_API_KEY_SANDBOX_REQUIRED`: Sandbox traffic
        uses a Live API key.
    ErrorDetailsAUTH_FORBIDDEN_IP:
      type: object
      additionalProperties: false
      properties:
        ip:
          type: string
          description: >-
            The caller's IP, echoed for confirmation. Omitted where production
            policy suppresses the offending IP.
          example: 203.0.113.42
      description: >-
        Structured context for `AUTH_FORBIDDEN_IP`: The source IP address is
        outside the API key allowlist.
    ErrorDetailsAUTH_INSUFFICIENT_SCOPE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_INSUFFICIENT_SCOPE`: The API key lacks a
        scope required by the operation.
    ErrorDetailsAUTH_TOKEN_EXPIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_TOKEN_EXPIRED`: The bearer token expiry
        time is in the past.
    ErrorDetailsAUTH_TOKEN_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_TOKEN_INVALID`: The bearer token or request
        signature is malformed or fails verification.
    ErrorDetailsAUTH_TOKEN_INVALID_CONFIG:
      type: object
      additionalProperties: false
      properties:
        reason:
          type: string
          description: Stable reason for the invalid token configuration.
      description: >-
        Structured context for `AUTH_TOKEN_INVALID_CONFIG`: The bearer token
        claims or validity window violate the authentication contract.
    ErrorDetailsAUTH_TOKEN_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `AUTH_TOKEN_MISSING`: The Authorization header is
        missing.
    ErrorDetailsBANK_ACCOUNT_NOT_FOUND:
      type: object
      additionalProperties: false
      properties:
        reason:
          type: string
          enum:
            - INVALID
            - NOT_FOUND
            - NOT_SUPPORTED
          description: Why no usable account was found at the submitted identifiers.
          example: NOT_FOUND
      description: >-
        Structured context for `BANK_ACCOUNT_NOT_FOUND`: No usable account
        exists at the submitted identifiers.
      required:
        - reason
    ErrorDetailsBENEFICIARY_DETAILS_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `BENEFICIARY_DETAILS_MISSING`: A detail the
        receiving institution requires for this payout is missing from the
        destination payout address.
    ErrorDetailsCAPABILITY_DUPLICATE:
      type: object
      additionalProperties: false
      properties:
        duplicates:
          type: array
          items:
            type: string
          description: The capability ids already held or repeated in the request.
          example:
            - cap_R8mRkY9V6dXFFpFrff3mDw
      description: >-
        Structured context for `CAPABILITY_DUPLICATE`: The account already holds
        a cell for a requested capability, or the request names the same
        capability twice.
      required:
        - duplicates
    ErrorDetailsCAPABILITY_NOT_ACTIVE:
      type: object
      additionalProperties: false
      properties:
        accountId:
          type: string
          description: The account named for this activity.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
        required:
          type: object
          additionalProperties: false
          description: The capability coverage this request needs.
          properties:
            grant:
              type: string
              description: The capability grant required.
              example: RECEIVE_PAYOUTS
            currency:
              type: string
              description: The currency the required capability must cover.
              example: INR
            repatriability:
              type: string
              description: >-
                The repatriability axis the required capability must cover, for
                an INR destination.
              example: NON_REPATRIABLE
          required:
            - grant
            - currency
            - repatriability
        capabilityId:
          type:
            - string
            - 'null'
          description: The closest matching capability cell's id, null when none exists.
          example: cap_R8mRkY9V6dXFFpFrff3mDw
        status:
          type:
            - string
            - 'null'
          description: >-
            The closest matching capability cell's status, null when none
            exists.
          example: PENDING
      description: >-
        Structured context for `CAPABILITY_NOT_ACTIVE`: The account named for
        this activity holds no ACTIVE capability covering what the request
        needs.
      required:
        - accountId
        - required
        - capabilityId
        - status
    ErrorDetailsCURRENCY_NOT_SUPPORTED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `CURRENCY_NOT_SUPPORTED`: No rail can deliver the
        requested receiveCurrency to this destination country.
    ErrorDetailsFEATURE_NOT_ENABLED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `FEATURE_NOT_ENABLED`: The caller's organization
        is not enabled for this feature.
    ErrorDetailsFINANCIAL_ACCOUNT_CURRENCY_MISMATCH:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `FINANCIAL_ACCOUNT_CURRENCY_MISMATCH`: The
        currency of the named financial account is not the sendCurrency the
        request states.
    ErrorDetailsFINANCIAL_ACCOUNT_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `FINANCIAL_ACCOUNT_NOT_FOUND`: The financial
        account identifier is unknown or inaccessible to the caller.
    ErrorDetailsIDEMPOTENCY_IN_FLIGHT:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_IN_FLIGHT`: Another request with the
        same idempotency key is still processing.
    ErrorDetailsIDEMPOTENCY_KEY_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_KEY_INVALID`: The Idempotency-Key
        value does not match ^[a-zA-Z0-9_-]{1,255}$.
    ErrorDetailsIDEMPOTENCY_KEY_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_KEY_MISSING`: A write request omits
        the Idempotency-Key header.
    ErrorDetailsIDEMPOTENCY_MISMATCH:
      type: object
      additionalProperties: false
      properties:
        originalRequestHash:
          type: string
          description: >-
            Hash identifying the conflicting original request body; the upstream
            service owns this shape.
          example: >-
            sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
      description: >-
        Structured context for `IDEMPOTENCY_MISMATCH`: An idempotency key is
        reused with a different request body.
      required:
        - originalRequestHash
    ErrorDetailsIDEMPOTENCY_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `IDEMPOTENCY_UNAVAILABLE`: The idempotency
        service is temporarily unreachable, so the request's Idempotency-Key
        could not be checked.
    ErrorDetailsIDENTITY_REQUIREMENT_UNMET:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: >-
            One entry per missing identity field, each path a JSON Pointer into
            the identity object.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /identity/individual/nationality
      description: >-
        Structured context for `IDENTITY_REQUIREMENT_UNMET`: The request
        exercises a capability the account's supplied identity information does
        not support.
      required:
        - issues
    ErrorDetailsINTERNAL_ERROR:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `INTERNAL_ERROR`: An unclassified server-side
        failure occurs.
    ErrorDetailsINVALID_ORGANIZATION:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `INVALID_ORGANIZATION`: The organization
        identifier on the request is malformed.
    ErrorDetailsKYC_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `KYC_REQUIRED`: A know-your-customer check the
        receiving side requires has not cleared.
    ErrorDetailsMETHOD_NOT_ALLOWED:
      type: object
      additionalProperties: false
      properties:
        method:
          type: string
          description: The HTTP method that was used.
          example: PUT
        allowed:
          type: array
          items:
            type: string
          description: The HTTP methods the path supports.
          example:
            - GET
      description: >-
        Structured context for `METHOD_NOT_ALLOWED`: The HTTP method is not
        supported on the request path.
      required:
        - method
        - allowed
    ErrorDetailsMISSING_REQUEST_CONTEXT:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `MISSING_REQUEST_CONTEXT`: The organization,
        user, or idempotency context every request carries was absent or
        unreadable.
    ErrorDetailsPAYOUT_ADDRESS_ARCHIVED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_ADDRESS_ARCHIVED`: The destination payout
        address is archived, a one-way retirement.
    ErrorDetailsPAYOUT_ADDRESS_CONFLICT:
      type: object
      additionalProperties: false
      properties:
        payoutAddressId:
          type: string
          description: The existing payout address backed by these bank details.
          example: pytadd_PbDQ126YUAbkNrNX6XbGL
        status:
          type: string
          description: The existing payout address's current standing.
          example: ACTIVE
      description: >-
        Structured context for `PAYOUT_ADDRESS_CONFLICT`: The bank details in
        the request already back a payout address on the same account.
      required:
        - payoutAddressId
        - status
    ErrorDetailsPAYOUT_ADDRESS_FIELD_MISSING:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_ADDRESS_FIELD_MISSING`: A field required
        by the selected routingFamily is missing.
    ErrorDetailsPAYOUT_ADDRESS_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_ADDRESS_NOT_FOUND`: The payout address
        identifier is unknown or inaccessible to the caller.
    ErrorDetailsPAYOUT_ADDRESS_REJECTED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_ADDRESS_REJECTED`: The destination payout
        address is REJECTED and cannot back a payout.
    ErrorDetailsPAYOUT_ADDRESS_VERIFICATION_FAILED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_ADDRESS_VERIFICATION_FAILED`: A
        verification check on the destination payout address could not be
        completed.
    ErrorDetailsPAYOUT_CANCELLATION_NOT_ALLOWED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_CANCELLATION_NOT_ALLOWED`: The payout
        isn't in REQUIRES_CONFIRMATION.
    ErrorDetailsPAYOUT_CONFIRMATION_NOT_ALLOWED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_CONFIRMATION_NOT_ALLOWED`: The payout
        isn't in REQUIRES_CONFIRMATION.
    ErrorDetailsPAYOUT_CURRENCY_NOT_ENABLED:
      type: object
      additionalProperties: false
      properties:
        receiveCurrency:
          type: string
          description: The currency the organization is not enabled for.
          example: INR
      description: >-
        Structured context for `PAYOUT_CURRENCY_NOT_ENABLED`: The organization
        isn't enabled for payouts in the requested receiveCurrency.
      required:
        - receiveCurrency
    ErrorDetailsPAYOUT_INSUFFICIENT_FUNDS:
      type: object
      additionalProperties: false
      properties:
        financialAccountId:
          type: string
          description: The underfunded financial account.
          example: finacc_AmKC5dMVXUbiAW8VzKBfqz
      description: >-
        Structured context for `PAYOUT_INSUFFICIENT_FUNDS`: The financial
        account named by financialAccountId cannot cover this payout's debit.
      required:
        - financialAccountId
    ErrorDetailsPAYOUT_NOT_ENABLED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_NOT_ENABLED`: The organization has no
        active provider configuration for this destination and receiveCurrency.
    ErrorDetailsPAYOUT_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_NOT_FOUND`: The payout identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsPAYOUT_TEMPORARILY_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `PAYOUT_TEMPORARILY_UNAVAILABLE`: Payout
        processing is temporarily unavailable because of a provider outage or a
        platform pause.
    ErrorDetailsPURPOSE_INVALID:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: >-
            One entry naming `purpose`, with `code` `purpose_required` where it
            is missing and `purpose_not_supported` where the currency refuses
            the value given. Absent where the currency takes no purpose at all.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /purpose
      description: >-
        Structured context for `PURPOSE_INVALID`: The payout's purpose is
        missing where its receiveCurrency requires one, refused for that
        receiveCurrency, or given where the receiveCurrency takes none.
    ErrorDetailsQUOTE_ALREADY_CONSUMED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_ALREADY_CONSUMED`: The quote is already
        bound to another payout.
    ErrorDetailsQUOTE_EXPIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: 'Structured context for `QUOTE_EXPIRED`: The applied quote has expired.'
    ErrorDetailsQUOTE_NOT_FOUND:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_NOT_FOUND`: The quote identifier is
        unknown or inaccessible to the caller.
    ErrorDetailsQUOTE_RAIL_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_RAIL_UNAVAILABLE`: No settlement rail
        serves the requested receiveCurrency to this payout address.
    ErrorDetailsQUOTE_REJECTED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: 'Structured context for `QUOTE_REJECTED`: Pricing declined the request.'
    ErrorDetailsQUOTE_SEND_CURRENCY_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_SEND_CURRENCY_UNAVAILABLE`: The
        sendCurrency of the named financial account cannot fund the requested
        receiveCurrency.
    ErrorDetailsQUOTE_TEMPORARILY_UNAVAILABLE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `QUOTE_TEMPORARILY_UNAVAILABLE`: Quoting is
        temporarily halted for reasons independent of the request.
    ErrorDetailsRATE_LIMIT_EXCEEDED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `RATE_LIMIT_EXCEEDED`: The organization exceeds
        its request limit.
    ErrorDetailsRECEIVER_MEMO_INVALID:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `RECEIVER_MEMO_INVALID`: receiverMemo violates
        the character set or length the bound rail's own grammar allows.
    ErrorDetailsROUTE_NOT_FOUND:
      type: object
      additionalProperties: false
      properties:
        path:
          type: string
          description: The unmatched request path.
          example: /v3/payments/example
      description: >-
        Structured context for `ROUTE_NOT_FOUND`: The request path does not
        match a v3 route.
      required:
        - path
    ErrorDetailsSANDBOX_MODE_REQUIRED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `SANDBOX_MODE_REQUIRED`: A request reaches the
        Sandbox environment with an `X-App-Mode` other than `SANDBOX`, for
        example `LIVE`.
    ErrorDetailsINVALID_APP_MODE:
      type: object
      additionalProperties: false
      properties:
        received:
          type: string
          description: The `X-App-Mode` value the request sent.
          example: PRODUCTION
        allowed:
          type: array
          description: The values `X-App-Mode` accepts.
          minItems: 1
          maxItems: 2
          uniqueItems: true
          items:
            type: string
            enum:
              - LIVE
              - SANDBOX
            description: An accepted `X-App-Mode` value.
          example:
            - LIVE
            - SANDBOX
      required:
        - received
        - allowed
      description: >-
        Structured context for `INVALID_APP_MODE`: The `X-App-Mode` header is
        present with a value other than `LIVE` or `SANDBOX`. Matching ignores
        case, and an empty value is also rejected.
    ErrorDetailsSENDER_ACCOUNT_REQUIRED:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry naming the missing sender field.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /sender
      description: >-
        Structured context for `SENDER_ACCOUNT_REQUIRED`: The payout needs a
        sender account named on sender and none was supplied.
      required:
        - issues
    ErrorDetailsSENDER_NOT_SUPPORTED:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry naming the sender field to remove.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /sender
      description: >-
        Structured context for `SENDER_NOT_SUPPORTED`: The payout names a
        sender, and a payout in this receiveCurrency cannot carry one.
      required:
        - issues
    ErrorDetailsVALIDATION_BODY_FAILED:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry per offending field.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /identity/individual/lastName
      description: >-
        Structured context for `VALIDATION_BODY_FAILED`: The request body fails
        schema validation.
      required:
        - issues
    ErrorDetailsVALIDATION_PATH_FAILED:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry per offending path parameter.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /payoutId
      description: >-
        Structured context for `VALIDATION_PATH_FAILED`: One or more path
        parameters fail schema validation.
      required:
        - issues
    ErrorDetailsVALIDATION_QUERY_FAILED:
      type: object
      additionalProperties: false
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
          description: One entry per offending query parameter.
        firstIssuePath:
          type: string
          description: The path of the first entry in issues.
          example: /receiveCurrency
      description: >-
        Structured context for `VALIDATION_QUERY_FAILED`: One or more query
        parameters fail schema validation.
      required:
        - issues
    ErrorDetailsVERIFICATION_EXECUTION_FAILED:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `VERIFICATION_EXECUTION_FAILED`: The verification
        could not be performed because of a technical failure on the platform's
        or the scheme's side.
    ErrorDetailsUNSUPPORTED_MEDIA_TYPE:
      $ref: '#/components/schemas/EmptyErrorDetails'
      description: >-
        Structured context for `UNSUPPORTED_MEDIA_TYPE`: The request's
        Content-Type is not application/json.
    ErrorDetailsVALIDATION_HEADER_FAILED:
      type: object
      additionalProperties: false
      required:
        - issues
        - firstIssuePath
      properties:
        issues:
          type: array
          items:
            $ref: '#/components/schemas/HeaderValidationIssue'
          description: Header validation issues.
        firstIssuePath:
          type: string
          description: Name of the first invalid HTTP header.
          example: X-Request-Id
      description: Structured issues describing an invalid X-Request-Id header.
    ErrorDetailsVALIDATION_PAYLOAD_TOO_LARGE:
      type: object
      required:
        - reason
        - limitBytes
      properties:
        reason:
          type: string
          example: payload_too_large
          description: Machine-readable reason the request body exceeded the payload limit.
        receivedBytes:
          type: integer
          minimum: 0
          example: 9000
          description: >-
            Number of bytes declared in Content-Length, when the gateway has
            that value.
        limitBytes:
          type: integer
          const: 8192
          example: 8192
          description: Maximum request-body size in bytes.
      additionalProperties: false
      description: >-
        Structured context for a request body that exceeds the maximum payload
        size.
    FinancialAccountId:
      type: string
      pattern: ^finacc_[1-9A-HJ-NP-Za-km-z]{21,22}$
      description: >-
        A typed-prefix Base58 identifier, matching
        `^finacc_[1-9A-HJ-NP-Za-km-z]{21,22}$`: the 3 to 6

        letter lowercase type prefix `finacc_` followed by the Base58 encoding
        of a UUID.


        See [Identifiers](/v3/resource-ids) for the prefix table, the case
        rules, and the three

        places a pattern is deliberately not enforced.
    PlatformAmount:
      type: string
      pattern: ^-?[0-9]+\.[0-9]{6}$
      description: >-
        An amount at OpenFX's fixed 6-decimal precision, as a decimal JSON
        string, never a number.


        Matches `^-?[0-9]+\.[0-9]{6}$`: an optional leading `-`, digits, a
        single `.`, then

        exactly 6 decimal places, always. A leading zero is required
        (`0.000000`, not `.000000`),

        with no thousands separators and no scientific notation. A whole value
        still carries the six

        places, so 5 is `5.000000`. A negative value is a figure in debit: a
        component that reduces

        a total, such as a fee discount, or a balance the account owes rather
        than holds.


        Every amount OpenFX prices or holds is presented this way, so the
        send-side, fee, converted and

        balance figures all line up at one scale. Two figures sit outside it:
        `receiveAmount`, which

        carries the destination rail's own precision, and the FX rate, which
        carries `ExchangeRate`'s

        wider precision.
    EmptyErrorDetails:
      type: object
      description: Closed details object for errors that expose no additional context.
      additionalProperties: false
      maxProperties: 0
    ValidationIssue:
      type: object
      properties:
        path:
          type: string
          format: json-pointer
          description: >-
            JSON Pointer to the offending field, resolved against the request:
            the JSON body for body validation, the query parameters read as one
            object for query validation. An array element is addressed by its
            zero-based index (`/identity/individual/documents/0/type`). An empty
            string names the whole body, for a cross-field issue no single field
            owns.
          example: /identity/individual/nationality
        code:
          type: string
          description: >-
            Machine-readable issue kind, lowercase snake_case.


            An open, deliberately non-exhaustive set. The values worth knowing,
            an illustration

            rather than a catalog:


            - invalid_type: the value has the wrong JSON type, or a required
            leaf is absent; `expected` and `received` carry the type names, and
            an absent leaf reads received undefined.

            - invalid_string: the value fails the field's pattern; `expected`
            carries the pattern.

            - invalid_enum_value: the value is not a member of the field's enum;
            `expected` carries the members, pipe-separated.

            - unrecognized_keys: an object carries a key that is not part of the
            schema, rejected rather than silently dropped; `path` names the
            object holding the key and `message` names the keys, the one issue
            whose `path` is not a leaf.

            - custom: the value is well-formed but not accepted, the case for an
            externally governed space such as an ISO country or currency code;
            the `message` names the standard.

            - append_conflict: the identity leaf is already set, and identity is
            append-only.

            - amount_below_minimum / amount_exceeds_limit: the amount is outside
            the permitted range for the payout destination; `details` carries
            the violating amount and the single bound it crossed.

            - sepa_iban_required / sepa_iban_unreachable: the `SEPA` arm was
            given an account it cannot pay, either one with no IBAN at all or an
            IBAN whose country the SEPA scheme does not cover; register it on
            the `SWIFT` arm instead.

            - swift_country_unsupported: the `bic` names a bank in a country the
            platform cannot pay SWIFT into; `details` carries that country.

            - bank_account_type_not_accepted: the `bankAccountType` is not a
            kind of account the bank named by `bankCode` accepts; `expected`
            carries the kinds it does, pipe-separated.

            - date_of_incorporation_mismatch: `dateOfIncorporation` is not the
            date the Mexican RFC in `taxInformation` encodes; correct whichever
            is wrong.

            - account_holder_name_invalid: the `accountHolderName` a payout
            address would carry, supplied or inherited from the account, breaks
            the name rules of its `routingFamily`; `message` names the rule.
            Supply a name that keeps to them.

            - purpose_required: the payout's `receiveCurrency` requires a
            `purpose` and none was given.

            - purpose_not_supported: the payout's `receiveCurrency` refuses the
            `purpose` given; pick another.


            Values not listed here appear without notice, so keep a default
            branch and fall back to

            rendering `message`.
          example: invalid_type
        message:
          type: string
          description: >-
            Human-readable statement of the issue. Not a stability contract;
            branch on `code`.
          example: Required
        expected:
          description: >-
            What the field accepts, when stating it helps the fix: a type name
            or a pattern.
          example: string
          type: string
        received:
          description: What the request carried, when echoing it back is safe.
          example: number
          type: string
      required:
        - path
        - code
        - message
      additionalProperties: false
      description: A single field-level validation failure.
    HeaderValidationIssue:
      type: object
      additionalProperties: false
      required:
        - path
        - code
        - message
      properties:
        path:
          type: string
          description: Name of the rejected HTTP header.
          example: X-Request-Id
        code:
          type: string
          description: Machine-readable header validation issue code.
          example: invalid_format
        message:
          type: string
          description: Human-readable description of the header validation failure.
          example: The X-Request-Id header is invalid.
      description: A single header validation issue.
  headers:
    XTraceId:
      description: >-
        Server-generated OpenTelemetry trace id, present on every response and
        regenerated per attempt (including idempotency replays). Quote it to
        OpenFX support to locate a request.
      schema:
        type: string
      example: 1f9e4c2a7b3d4e5f6a7b8c9d0e1f2a3b
    XRequestTimestamp:
      description: >-
        RFC 3339 UTC timestamp, millisecond precision, of when the request
        reached the API.
      schema:
        $ref: '#/components/schemas/Timestamp'
      example: '2026-06-04T10:30:00.000Z'
    RateLimitLimit:
      description: >-
        Maximum requests allowed in the current window. See the Rate limiting
        page.
      schema:
        type: integer
      example: 300
    RateLimitReset:
      description: >-
        Seconds until the current rate-limit window resets (a duration, counted
        from the response time — not an absolute Unix timestamp).
      schema:
        type: integer
      example: 8
    RetryAfter:
      description: >-
        Seconds to wait before retrying. Present on `429 RATE_LIMIT_EXCEEDED`
        and `409 IDEMPOTENCY_IN_FLIGHT` responses only.
      schema:
        type: integer
      example: 10
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        ES256 JWT bearer token, minted fresh per request.


        See [Authentication](/v3/authentication) for the claims, including the
        nonce, the

        request signature, the two scopes, and which status means what.
    requestSignature:
      type: apiKey
      in: header
      name: X-Request-Signature
      description: >-
        Body-bound ES256 signature over the request, required alongside the
        bearer token on

        every call. Base64url of an IEEE P-1363 fixed 64-byte `r‖s` signature.


        See [Authentication](/v3/authentication) for the canonical string it
        signs, including

        the JWT nonce that binds it to the bearer token.

````