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

# Create a payout address

> Register a destination `accountId` can be paid at.



## OpenAPI

````yaml api-reference/openapi-v3-payments.json POST /v3/payments/payout-addresses
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/payments/payout-addresses:
    post:
      tags:
        - Addresses
      summary: Create a payout address
      description: >-
        Register a destination `accountId` can be paid at.


        The body is discriminated on `payoutAddressType` and carries
        `bankAccount`, itself

        discriminated on `routingFamily`. See `CreatePayoutAddress`.


        Creating the address does not wait on the covering capability's
        activation; address

        setup and capability setup run in parallel. The capability gate is POST

        /v3/payments/payouts.


        The response reports `status` as it stands when it is written, `PENDING`
        while

        initial setup is still running, with `verifications[]` empty or partly
        filled

        likewise. Setup drives `status` to its settled value and fires that
        event however

        fast it settles; subscribe to `payments.payout_address.activated`,
        `payments.payout_address.rejected`,

        `payments.payout_address.requires_information` and
        `payments.payout_address.verification_resolved`

        rather than polling.
      operationId: createPayoutAddress
      parameters:
        - $ref: '#/components/parameters/XAppMode'
        - $ref: '#/components/parameters/XRequestId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePayoutAddress'
            examples:
              sepaIbanOnly:
                summary: SEPA bank account
                description: >-
                  A German bank account, routed by IBAN. `accountHolderName` is
                  omitted, so it defaults to the linked account's own name;
                  `supportedRails` comes back as SEPA alone.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                  bankAccount:
                    routingFamily: SEPA
                    accountNumber: DE89370400440532013000
              swiftBankAccount:
                summary: SWIFT bank account
                description: >-
                  An account no SEPA scheme reaches, registered by account
                  number and BIC with the holder's postal address.
                  `supportedRails` comes back as SWIFT alone, and no name check
                  runs against it.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                  bankAccount:
                    routingFamily: SWIFT
                    accountNumber: '8801234567'
                    bic: PAVEGE22XXX
                    accountHolderAddress:
                      country: DE
                      city: Berlin
                      line1: Friedrichstrasse 100
                      postalCode: '10117'
              inrBankAccount:
                summary: Indian bank account (IFSC)
                description: >-
                  An Indian account, routed by `ifsc` and `accountNumber`, with
                  the repatriability flag `isNre`. `supportedRails` comes back
                  as IMPS, NEFT and RTGS.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                  bankAccount:
                    routingFamily: IN_LOCAL
                    accountHolderName: Nadia Mehta
                    ifsc: HDFC0001234
                    accountNumber: '50100234567890'
                    isNre: false
                    bankAccountType: SAVINGS
              mxClabe:
                summary: Mexican bank account (CLABE)
                description: >-
                  A Mexican account, routed by its CLABE in `accountNumber`.
                  `supportedRails` comes back as SPEI.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_3rt8nW9q7ZR7nwp7EyQEBV
                  bankAccount:
                    routingFamily: MX_LOCAL
                    accountNumber: '012180001234567899'
              coBankAccount:
                summary: Colombian bank account
                description: >-
                  A Colombian account, routed by `bankCode`, `accountNumber` and
                  `bankAccountType`. `supportedRails` comes back as CO_ACH.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_LxWQiP5o7Zo56ix44VVXHd
                  bankAccount:
                    routingFamily: CO_LOCAL
                    bankCode: '1007'
                    accountNumber: '24512345678'
                    bankAccountType: SAVINGS
              coBrebKey:
                summary: Bre-B key
                description: >-
                  A Colombian account reached through the Bre-B key its holder
                  registered. `supportedRails` comes back as BREB.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_LxWQiP5o7Zo56ix44VVXHd
                  bankAccount:
                    routingFamily: CO_BREB
                    brebKey: '@camilarestrepo'
              aeIban:
                summary: UAE bank account (IBAN)
                description: >-
                  A UAE account, routed by its IBAN in `accountNumber` alone.
                  `supportedRails` comes back as AE_LOCAL.
                value:
                  payoutAddressType: BANK_ACCOUNT
                  accountId: acc_QygvWFFEQj5k9EVjuw386x
                  bankAccount:
                    routingFamily: AE_LOCAL
                    accountNumber: AE070331234567890123456
      responses:
        '200':
          description: The created payout address.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PayoutAddress'
                required:
                  - data
                additionalProperties: false
              examples:
                sepaIbanOnly:
                  summary: SEPA bank account, no BIC
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_PbDQ126YUAbkNrNX6XbGL
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                      bankAccount:
                        routingFamily: SEPA
                        accountHolderName: Novalia Handels GmbH
                        accountNumber: DE89370400440532013000
                        country: DE
                      supportedCurrencies:
                        - EUR
                      supportedRails:
                        - SEPA
                      status: PENDING
                      verifications:
                        - kind: NAME_MATCH
                          mode: SEPA_VOP
                          result: PENDING
                          providedName: Novalia Handels GmbH
                          registeredName: null
                          createdAt: '2026-06-04T10:30:00.000Z'
                          verifiedAt: null
                          expiresAt: null
                      archivedAt: null
                      createdAt: '2026-06-04T10:30:00.000Z'
                      updatedAt: '2026-06-04T10:30:00.000Z'
                swiftBankAccount:
                  summary: SWIFT bank account
                  description: >-
                    `verifications[]` is empty: no scheme offers a name check on
                    this account, so the `PENDING` rollup reflects the
                    platform's own setup alone.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_jHcLJsDRYZdDYJAhQWtbn
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                      bankAccount:
                        routingFamily: SWIFT
                        accountHolderName: Novalia Handels GmbH
                        accountNumber: '8801234567'
                        bic: PAVEGE22XXX
                        accountHolderAddress:
                          country: DE
                          city: Berlin
                          line1: Friedrichstrasse 100
                          postalCode: '10117'
                        country: GE
                      supportedCurrencies:
                        - EUR
                      supportedRails:
                        - SWIFT
                      status: PENDING
                      verifications: []
                      archivedAt: null
                      createdAt: '2026-06-04T10:30:00.000Z'
                      updatedAt: '2026-06-04T10:30:00.000Z'
                inrBankAccount:
                  summary: Indian bank account (IFSC)
                  description: >-
                    An Indian account's `IMPS_PENNY_DROP` name match runs
                    synchronously, once, here at setup, so the response already
                    carries the settled act in `verifications[]` and the
                    `ACTIVE` rollup; its result later reaches a payout's caller
                    as a confirmation.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_PbDQ126YUAbkNrNX6XbGL
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                      bankAccount:
                        routingFamily: IN_LOCAL
                        accountHolderName: Nadia Mehta
                        ifsc: HDFC0001234
                        accountNumber: '50100234567890'
                        isNre: false
                        bankAccountType: SAVINGS
                        country: IN
                      supportedCurrencies:
                        - INR
                      supportedRails:
                        - IMPS
                        - NEFT
                        - RTGS
                      status: ACTIVE
                      verifications:
                        - kind: NAME_MATCH
                          mode: IMPS_PENNY_DROP
                          result: MATCH
                          providedName: Nadia Mehta
                          registeredName: Nadia Mehta
                          createdAt: '2026-06-04T10:31:30.000Z'
                          verifiedAt: '2026-06-04T10:31:32.000Z'
                          expiresAt: null
                      archivedAt: null
                      createdAt: '2026-06-04T10:31:30.000Z'
                      updatedAt: '2026-06-04T10:31:32.000Z'
                mxClabe:
                  summary: Mexican bank account (CLABE)
                  description: >-
                    The `SPEI_ACCOUNT_OWNERSHIP` check reads `PENDING`. It
                    resolves later, during Mexican banking hours, and the
                    address does not wait for it to become `ACTIVE`.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_7TWd3GN9tc3SCW6zEgCi5U
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_3rt8nW9q7ZR7nwp7EyQEBV
                      bankAccount:
                        routingFamily: MX_LOCAL
                        accountHolderName: Novalia Comercial SA de CV
                        accountNumber: '012180001234567899'
                        country: MX
                      supportedCurrencies:
                        - MXN
                      supportedRails:
                        - SPEI
                      status: PENDING
                      verifications:
                        - kind: NAME_MATCH
                          mode: SPEI_ACCOUNT_OWNERSHIP
                          result: PENDING
                          providedName: Novalia Comercial SA de CV
                          registeredName: null
                          createdAt: '2026-06-04T12:05:00.000Z'
                          verifiedAt: null
                          expiresAt: null
                      archivedAt: null
                      createdAt: '2026-06-04T12:05:00.000Z'
                      updatedAt: '2026-06-04T12:05:00.000Z'
                coBankAccount:
                  summary: Colombian bank account
                  description: >-
                    `verifications[]` is empty: no name check runs on a
                    Colombian bank account.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_8QCsAUtge3MGbu5cahouYX
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_LxWQiP5o7Zo56ix44VVXHd
                      bankAccount:
                        routingFamily: CO_LOCAL
                        accountHolderName: Camila Restrepo
                        bankCode: '1007'
                        accountNumber: '24512345678'
                        bankAccountType: SAVINGS
                        country: CO
                      supportedCurrencies:
                        - COP
                      supportedRails:
                        - CO_ACH
                      status: PENDING
                      verifications: []
                      archivedAt: null
                      createdAt: '2026-06-04T12:06:00.000Z'
                      updatedAt: '2026-06-04T12:06:00.000Z'
                coBrebKey:
                  summary: Bre-B key
                  description: >-
                    The `BREB_KEY_LOOKUP` answers in real time, so the response
                    already carries the settled act and the `ACTIVE` rollup.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_4fRBTmfo4anLsQwkKhMEo3
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_LxWQiP5o7Zo56ix44VVXHd
                      bankAccount:
                        routingFamily: CO_BREB
                        accountHolderName: Camila Restrepo
                        brebKey: '@camilarestrepo'
                        country: CO
                      supportedCurrencies:
                        - COP
                      supportedRails:
                        - BREB
                      status: ACTIVE
                      verifications:
                        - kind: NAME_MATCH
                          mode: BREB_KEY_LOOKUP
                          result: MATCH
                          providedName: Camila Restrepo
                          registeredName: Camila Restrepo
                          createdAt: '2026-06-04T12:07:00.000Z'
                          verifiedAt: '2026-06-04T12:07:01.000Z'
                          expiresAt: null
                      archivedAt: null
                      createdAt: '2026-06-04T12:07:00.000Z'
                      updatedAt: '2026-06-04T12:07:01.000Z'
                aeIban:
                  summary: UAE bank account (IBAN)
                  description: >-
                    `verifications[]` is empty: no name check runs on a UAE bank
                    account. `accountHolderName` is inherited from the account's
                    `legalName`.
                  value:
                    data:
                      object: payoutAddress
                      id: pytadd_5SUGxBoim4maZy6aCTePoH
                      payoutAddressType: BANK_ACCOUNT
                      accountId: acc_QygvWFFEQj5k9EVjuw386x
                      bankAccount:
                        routingFamily: AE_LOCAL
                        accountHolderName: Falcon Trading LLC
                        accountNumber: AE070331234567890123456
                        country: AE
                      supportedCurrencies:
                        - AED
                      supportedRails:
                        - AE_LOCAL
                      status: PENDING
                      verifications: []
                      archivedAt: null
                      createdAt: '2026-06-04T12:08:00.000Z'
                      updatedAt: '2026-06-04T12:08:00.000Z'
          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'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
        '400':
          description: >-
            The request body failed validation, or the Idempotency-Key header is
            malformed: PAYOUT_ADDRESS_FIELD_MISSING / VALIDATION_BODY_FAILED
            (extraneous or mismatched field for the selected `routingFamily`, an
            account the `SEPA` arm cannot pay, a `bic` naming a country the
            platform cannot pay SWIFT into, a CLABE whose check digit fails, a
            `bankAccountType` the bank does not accept, a `brebKey` carrying
            whitespace, an `AE_LOCAL` `accountNumber` that is not a valid UAE
            IBAN, or an `AE_LOCAL` `accountHolderName`, supplied or inherited,
            outside that arm's name rules; `details.issues[]` says which) /
            IDEMPOTENCY_KEY_INVALID: the Idempotency-Key doesn't match the
            required grammar. 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:
                PAYOUT_ADDRESS_FIELD_MISSING:
                  value:
                    error:
                      code: PAYOUT_ADDRESS_FIELD_MISSING
                      type: VALIDATION_ERROR
                      message: >-
                        A field required by the selected routingFamily is
                        missing.
                      retryStrategy: FIX_AND_RESUBMIT
                      details: {}
                VALIDATION_BODY_FAILED:
                  value:
                    error:
                      code: VALIDATION_BODY_FAILED
                      type: VALIDATION_ERROR
                      message: >-
                        Request body failed validation. See details.issues for
                        field-level errors; details.firstIssuePath points at the
                        first failing field.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        issues:
                          - path: /identity/individual/lastName
                            code: invalid_type
                            message: Required
                            expected: string
                            received: undefined
                          - path: /identity/individual/documents/0/type
                            code: invalid_enum_value
                            message: is not a supported document type
                            expected: >-
                              PASSPORT|NATIONAL_ID|DRIVERS_LICENSE|SSN|RESIDENCE_PERMIT
                            received: LIBRARY_CARD
                          - path: /identity/individual/residentialAddress/country
                            code: custom
                            message: >-
                              is not an ISO 3166-1 alpha-2 country code (the
                              United Kingdom is GB)
                            received: UK
                        firstIssuePath: /identity/individual/lastName
                IDEMPOTENCY_KEY_INVALID:
                  value:
                    error:
                      code: IDEMPOTENCY_KEY_INVALID
                      type: VALIDATION_ERROR
                      message: >-
                        Idempotency-Key must match ^[a-zA-Z0-9_-]{1,255}$ (UUID
                        SHOULD be used).
                      retryStrategy: FIX_AND_RESUBMIT
                      details: {}
                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'
        '404':
          description: >-
            No account with this id is visible to your organization:
            ACCOUNT_NOT_FOUND.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                ACCOUNT_NOT_FOUND:
                  value:
                    error:
                      code: ACCOUNT_NOT_FOUND
                      type: NOT_FOUND
                      message: No account with that id in this organization.
                      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'
        '409':
          description: >-
            The request conflicts with the resource's current state, or repeats
            an Idempotency-Key that is still in flight: ACCOUNT_NOT_ACTIVE (the
            owning account's standing with OpenFX is `REJECTED`, so no payout
            address can be created for it, and `details` names the account and
            its current `status`. A `PENDING` or `REQUIRES_INFORMATION` account
            still takes new addresses, so setting up an address and settling the
            account's standing run in parallel) / ACCOUNT_ARCHIVED (the account
            this request names is archived, and archival is one-way, so it can
            no longer be named for new activity; `details` names it. A different
            subject from ACCOUNT_NOT_ACTIVE, which reports a standing that is
            not yet `ACTIVE` and may still change, whereas an archived account
            is frozen whatever standing it held) / ADDRESS_SERVES_NO_CAPABILITY
            (the account the address would belong to holds no capability able to
            receive at it, in any status, so there is nothing for the address to
            serve. `details` names the account and the required coverage:
            `grants` including `RECEIVE_PAYOUTS`, an axis covering the currency
            the address receives in and, for an `INR` address, its `isNre` (true
            covered by `REPATRIABLE`, false by `NON_REPATRIABLE`). A covering
            capability that merely isn't `ACTIVE` yet still takes the address,
            because address setup and capability setup run in parallel; only an
            account holding no covering capability at all is refused, so the fix
            is an account whose creation requested one) /
            PAYOUT_ADDRESS_CONFLICT (the bank details in this request already
            back a payout address on the same `accountId`, matched on the
            routing identifiers of the `routingFamily`: the `ifsc` and
            `accountNumber` for an `IN_LOCAL` account, the `accountNumber` for a
            `SEPA`, `SWIFT` or `MX_LOCAL` one, the `bankCode` and
            `accountNumber` for a `CO_LOCAL` one, and the `brebKey` for a
            `CO_BREB` one. `details` names the existing payout address and
            reports its `status`; pay it rather than registering a duplicate) /
            IDEMPOTENCY_IN_FLIGHT: a request with the same Idempotency-Key is
            still being processed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                ACCOUNT_NOT_ACTIVE:
                  value:
                    error:
                      code: ACCOUNT_NOT_ACTIVE
                      type: CONFLICT
                      message: >-
                        The account's standing with OpenFX is not ACTIVE;
                        details names the account and its current status.
                      retryStrategy: CHECK_STATE_THEN_RETRY
                      details:
                        accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                        status: REJECTED
                ACCOUNT_ARCHIVED:
                  value:
                    error:
                      code: ACCOUNT_ARCHIVED
                      type: CONFLICT
                      message: >-
                        The account named by this request is archived. Archival
                        is one-way, so the account can no longer be named for
                        new activity, and details names it. Distinct from
                        ACCOUNT_NOT_ACTIVE, which reports a standing that is not
                        yet ACTIVE and may still change.
                      retryStrategy: TERMINAL
                      details:
                        accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                ADDRESS_SERVES_NO_CAPABILITY:
                  value:
                    error:
                      code: ADDRESS_SERVES_NO_CAPABILITY
                      type: CONFLICT
                      message: >-
                        The account this payout address would belong to holds no
                        capability able to receive at it; details names the
                        account and the coverage the address requires.
                      retryStrategy: CHECK_STATE_THEN_RETRY
                      details:
                        accountId: acc_BMY3UenpGBn8ZQ8hio4BgE
                        required:
                          grant: RECEIVE_PAYOUTS
                          currency: INR
                          repatriability: NON_REPATRIABLE
                PAYOUT_ADDRESS_CONFLICT:
                  value:
                    error:
                      code: PAYOUT_ADDRESS_CONFLICT
                      type: CONFLICT
                      message: >-
                        These bank details are already registered as a payout
                        address on this account; details names the existing one,
                        and details.status reports its current standing. Pay it
                        rather than registering a duplicate.
                      retryStrategy: TERMINAL
                      details:
                        payoutAddressId: pytadd_PbDQ126YUAbkNrNX6XbGL
                        status: ACTIVE
                IDEMPOTENCY_IN_FLIGHT:
                  value:
                    error:
                      code: IDEMPOTENCY_IN_FLIGHT
                      type: CONFLICT
                      message: >-
                        A request with this Idempotency-Key is still being
                        processed.
                      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'
        '413':
          description: 413 VALIDATION_ERROR.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                validation_payload_too_large:
                  summary: VALIDATION_PAYLOAD_TOO_LARGE
                  value:
                    error:
                      code: VALIDATION_PAYLOAD_TOO_LARGE
                      type: VALIDATION_ERROR
                      message: Request body exceeds the maximum allowed payload size.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        reason: payload_too_large
                        limitBytes: 8192
                        receivedBytes: 9000
        '415':
          description: >-
            The request Content-Type is not application/json:
            UNSUPPORTED_MEDIA_TYPE.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                UNSUPPORTED_MEDIA_TYPE:
                  value:
                    error:
                      code: UNSUPPORTED_MEDIA_TYPE
                      type: VALIDATION_ERROR
                      message: >-
                        The request Content-Type is not application/json. Send
                        the body as application/json.
                      retryStrategy: FIX_AND_RESUBMIT
                      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'
        '422':
          description: >-
            The request is well-formed but a business rule rejects the values it
            carries, or it reuses an Idempotency-Key with a different body:
            IDEMPOTENCY_MISMATCH: same key, different body;
            `details.originalRequestHash` identifies the conflicting original
            request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                IDEMPOTENCY_MISMATCH:
                  value:
                    error:
                      code: IDEMPOTENCY_MISMATCH
                      type: CONFLICT
                      message: Same Idempotency-Key, different request body.
                      retryStrategy: FIX_AND_RESUBMIT
                      details:
                        originalRequestHash: >-
                          sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
          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'
        '428':
          description: >-
            Every write requires an Idempotency-Key header, and this request
            omitted it: IDEMPOTENCY_KEY_MISSING.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                IDEMPOTENCY_KEY_MISSING:
                  value:
                    error:
                      code: IDEMPOTENCY_KEY_MISSING
                      type: VALIDATION_ERROR
                      message: >-
                        The Idempotency-Key header is required on every write
                        and was omitted.
                      retryStrategy: FIX_AND_RESUBMIT
                      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'
        '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'
        '503':
          description: >-
            The idempotency service is temporarily unreachable, so the request's
            Idempotency-Key could not be checked: IDEMPOTENCY_UNAVAILABLE.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              examples:
                IDEMPOTENCY_UNAVAILABLE:
                  value:
                    error:
                      code: IDEMPOTENCY_UNAVAILABLE
                      type: INTERNAL_ERROR
                      message: >-
                        The idempotency service is temporarily unavailable.
                        Retry the request.
                      retryStrategy: WAIT_THEN_RETRY_SAME_KEY
                      details: {}
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.
    IdempotencyKey:
      in: header
      name: Idempotency-Key
      schema:
        type: string
        pattern: ^[a-zA-Z0-9_-]{1,255}$
        example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        description: >-
          Unique client-generated key identifying this request.


          A request that timed out or failed can be replayed safely under the
          same key. See

          [Idempotency keys](/v3/idempotency).
      required: true
      description: >-
        Unique client-generated key identifying this request.


        A request that timed out or failed can be replayed safely under the same
        key. See

        [Idempotency keys](/v3/idempotency).
  schemas:
    CreatePayoutAddress:
      type: object
      properties:
        payoutAddressType:
          type: string
          const: BANK_ACCOUNT
        accountId:
          $ref: '#/components/schemas/AccountId'
          description: >-
            The account this payout address belongs to.


            Immutable once set, and an id rather than an inlined record: fetch

            GET /v3/common/accounts/{accountId} for the account's own identity
            data.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
        label:
          description: Human-friendly label. Cosmetic.
          example: Operating account
          type: string
        metadata:
          $ref: '#/components/schemas/Metadata'
        bankAccount:
          $ref: '#/components/schemas/CreateBankAccount'
          description: Where this bank account is, and how a payout is routed to it.
      required:
        - payoutAddressType
        - accountId
        - bankAccount
      additionalProperties: false
      description: >-
        Payload for creating a payout address. Carries `bankAccount`, the
        routable identifiers of the destination. See `createPayoutAddress` for
        the setup and status lifecycle that follows.
    PayoutAddress:
      type: object
      properties:
        object:
          type: string
          const: payoutAddress
          description: >-
            The type of object represented, a fixed discriminator. Always
            `"payoutAddress"` for this resource, and identical across every
            object of the type.
          example: payoutAddress
        id:
          $ref: '#/components/schemas/PayoutAddressId'
          description: Payout address identifier.
          example: pytadd_PbDQ126YUAbkNrNX6XbGL
        supportedCurrencies:
          type: array
          items:
            $ref: '#/components/schemas/CurrencyCode'
          description: >-
            The currencies and tokens this destination can receive.


            New entries may be added additively, so tolerate an unrecognized
            value.
          example:
            - USD
        supportedRails:
          type: array
          items:
            $ref: '#/components/schemas/Rail'
          description: >-
            The rails this destination can be paid over, following
            `routingFamily` and the

            identifiers supplied with it.


            New rails may be added additively, so tolerate an unrecognized
            value.
          example:
            - SEPA
        status:
          $ref: '#/components/schemas/PayoutAddressStatus'
        verifications:
          type: array
          items:
            $ref: '#/components/schemas/Verification'
          description: >-
            What the platform has established about this destination.


            Holds the current act for each verification kind and mode, not a
            history: a repeat act

            replaces the entry it supersedes on the wire, while the full history
            is retained

            internally. At most one entry today: a name match, where a scheme
            runs one at setup, and

            it is the itemized input to `status`.


            A new verification kind would ship as a new variant, so tolerate an
            unrecognized `kind`.

            See `Verification`.
        archivedAt:
          anyOf:
            - $ref: '#/components/schemas/Timestamp'
            - type: 'null'
          description: >-
            When the client retired this payout address, or null while it is
            live.


            Set by POST /v3/payments/payout-addresses/{payoutAddressId}/archive
            and terminal once set: a repeat

            call leaves the timestamp unchanged. Archiving deletes nothing, so
            the address and every

            reference to it stay retrievable by id, but an archived address is
            hidden from

            `listPayoutAddresses` by default and cannot back new payouts.
          example: '2026-06-04T10:30:00.000Z'
        createdAt:
          $ref: '#/components/schemas/Timestamp'
          description: Creation timestamp.
          example: '2026-06-04T10:30:00.000Z'
        updatedAt:
          $ref: '#/components/schemas/Timestamp'
          description: Last-update timestamp.
          example: '2026-06-04T10:30:00.000Z'
        payoutAddressType:
          type: string
          const: BANK_ACCOUNT
        accountId:
          $ref: '#/components/schemas/AccountId'
          description: >-
            The account this payout address belongs to.


            Immutable once set, and an id rather than an inlined record: fetch

            GET /v3/common/accounts/{accountId} for the account's own identity
            data.
          example: acc_BMY3UenpGBn8ZQ8hio4BgE
        label:
          description: Human-friendly label. Cosmetic.
          example: Operating account
          type: string
        metadata:
          $ref: '#/components/schemas/Metadata'
        bankAccount:
          $ref: '#/components/schemas/BankAccount'
          description: Where this bank account is, and how a payout is routed to it.
      required:
        - object
        - id
        - supportedCurrencies
        - supportedRails
        - status
        - verifications
        - archivedAt
        - createdAt
        - updatedAt
        - payoutAddressType
        - accountId
        - bankAccount
      additionalProperties: false
      description: >-
        A registered destination an account can be paid at. Carries
        `bankAccount`, the routable

        identifiers of the destination.


        The record is immutable apart from archiving. There is no update
        operation, so correcting

        anything on it means creating a replacement and archiving this one.
    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.
    AccountId:
      type: string
      pattern: ^acc_[1-9A-HJ-NP-Za-km-z]{21,22}$
      description: >-
        A typed-prefix Base58 identifier, matching
        `^acc_[1-9A-HJ-NP-Za-km-z]{21,22}$`: the 3 to 6

        letter lowercase type prefix `acc_` 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.
    Metadata:
      type: object
      propertyNames:
        type: string
        pattern: ^[a-zA-Z0-9_]{1,40}$
      additionalProperties:
        type: string
        maxLength: 500
      maxProperties: 50
      description: >-
        Your own key/value pairs, kept on the record and returned with it.


        See [Metadata](/v3/metadata-and-tracing#withdrawal-metadata) for what
        belongs in a metadata object, the limits, and where it comes back.
        Metadata is visible in the OpenFX platform, API, and MCP server
        (including connected AI tools), so don't include sensitive or personal
        data.
      example:
        invoiceId: INV-2026-0412
        costCenter: AP_INTL
    CreateBankAccount:
      oneOf:
        - $ref: '#/components/schemas/CreateSepaBankAccount'
        - $ref: '#/components/schemas/CreateSwiftBankAccount'
        - $ref: '#/components/schemas/CreateInLocalBankAccount'
        - $ref: '#/components/schemas/CreateMxLocalBankAccount'
        - $ref: '#/components/schemas/CreateCoLocalBankAccount'
        - $ref: '#/components/schemas/CreateCoBrebBankAccount'
        - $ref: '#/components/schemas/CreateAeLocalBankAccount'
      title: Bank account routing
      description: >-
        The routable identifiers of a bank account, discriminated on
        `routingFamily`; exactly one

        variant is ever present.


        Extraneous or mismatched fields for the selected member are rejected
        outright, never

        silently dropped. A new supported rail family ships as a new member, so
        tolerate an

        unrecognized `routingFamily`.
      type: object
      discriminator:
        propertyName: routingFamily
        mapping:
          SEPA: '#/components/schemas/CreateSepaBankAccount'
          SWIFT: '#/components/schemas/CreateSwiftBankAccount'
          IN_LOCAL: '#/components/schemas/CreateInLocalBankAccount'
          MX_LOCAL: '#/components/schemas/CreateMxLocalBankAccount'
          CO_LOCAL: '#/components/schemas/CreateCoLocalBankAccount'
          CO_BREB: '#/components/schemas/CreateCoBrebBankAccount'
          AE_LOCAL: '#/components/schemas/CreateAeLocalBankAccount'
    PayoutAddressId:
      type: string
      pattern: ^pytadd_[1-9A-HJ-NP-Za-km-z]{21,22}$
      description: >-
        A typed-prefix Base58 identifier, matching
        `^pytadd_[1-9A-HJ-NP-Za-km-z]{21,22}$`: the 3 to 6

        letter lowercase type prefix `pytadd_` 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.
    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.
    Rail:
      type: string
      enum:
        - SEPA
        - SWIFT
        - IMPS
        - NEFT
        - RTGS
        - SPEI
        - CO_ACH
        - BREB
        - AE_LOCAL
      x-enum-descriptions:
        SEPA: >-
          Euro-area credit transfer, EUR only. Selected by a roster check on the
          destination IBAN's country at creation, then a per-IBAN reachability
          check during setup; see `SepaBankAccount`.
        SWIFT: >-
          Correspondent banking for euro destinations the SEPA scheme does not
          reach, EUR only. Banks along the path may deduct their own charges
          from the amount in transit, so what the destination receives can fall
          short of `receiveAmount`. Where a destination is reachable both ways,
          SEPA carries the payout; see `SwiftBankAccount`.
        IMPS: India immediate retail transfer, INR. Available around the clock.
        NEFT: India deferred net settlement, INR. Settles in scheduled batches.
        RTGS: >-
          India real-time gross settlement, INR. High value, settled
          individually on receipt.
        SPEI: >-
          Mexico's interbank transfer system, MXN, settled individually in real
          time and routed by CLABE; see `MxLocalBankAccount`. A `receiverMemo`
          is at most 40 letters, digits and spaces, and a longer one or one
          carrying any other character is refused rather than truncated.
        CO_ACH: >-
          Colombian domestic bank transfer, COP, routed by bank code, account
          number and account type; see `CoLocalBankAccount`. The platform
          decides whether a payout settles same-day or in the next clearing
          batch, and the caller cannot choose. The `receiverMemo` rule is the
          one `SPEI` states.
        BREB: >-
          Colombia's instant transfer system, COP, routed by a key the account
          holder registered rather than by account number; see
          `CoBrebBankAccount`. Each payout is capped, so a `receiveAmount` above
          the cap is refused when the quote is priced. The `receiverMemo` rule
          is the one `SPEI` states.
        AE_LOCAL: >-
          The United Arab Emirates' domestic bank transfer, AED, routed by IBAN;
          see `AeLocalBankAccount`. A `receiverMemo` is at most 100 letters,
          digits and spaces, and a longer one or one carrying any other
          character is refused rather than truncated. A `receiveAmount` outside
          the AED per-payout limits is refused when the quote is priced.
      description: >-
        The scheme that physically moves the money, and the source of the
        settlement mechanics and

        the settlement identifiers reported back.


        Omit to auto-route, the platform picks a rail based on the destination
        country and the

        send and receive currencies, and reports the chosen rail back on the
        resulting Payout.


        A member of this list is a scheme OpenFX can route over, not a scheme
        available for a

        given destination: what a specific destination supports is
        `supportedRails` on the

        payout address.


        It also fixes the kind of trace reference reported back for the payout,
        which

        `SettlementTraceIdKey` names.
    PayoutAddressStatus:
      type: string
      enum:
        - PENDING
        - ACTIVE
        - REJECTED
        - REQUIRES_INFORMATION
      x-enum-descriptions:
        PENDING: >-
          Initial setup has not completed: not every setup act it waits on has
          returned. Cannot back a payout yet. A name match that resolves after
          creation, as on a `MX_LOCAL` account, is not waited on, so an address
          can leave this status while that check still reads `PENDING`.
        ACTIVE: >-
          May back a payout. A `CLOSE_MATCH` name result leaves an address here,
          since only a blocking result prevents payout.
        REJECTED: >-
          A setup act returned a blocking result or failed outright, and no
          cause is given beyond what `verifications[]` shows. Cannot back a
          payout while this stands, and the remedy is a replacement address
          rather than a correction, because the record is immutable.
        REQUIRES_INFORMATION: >-
          OpenFX has requested information for this address's setup. The request
          and its fulfillment travel through your operational channel with
          OpenFX, not through the API; the address cannot back a payout while it
          stands, and the status returns to `PENDING` once the information is
          provided.
      description: >-
        Whether the platform's setup of this payout address allows it to back a
        payout.


        It combines a rollup over the address's setup acts with an internal
        platform status. The

        setup acts are the verification acts itemized in `verifications[]`, plus
        further checks and

        setup the platform performs that the address does not itemize. A
        blocking or failed act

        drives `REJECTED`, and which verification results block is stated on
        `NameMatchResult`.


        `PENDING` means initial setup has not completed, never a re-check
        running against an

        already-`ACTIVE` address. Setup runs for the life of the address, so
        `ACTIVE` is not

        terminal: a later blocking or failed act moves the address to
        `REJECTED`, and an

        information request moves it to `REQUIRES_INFORMATION`, but neither
        returns it to

        `PENDING`.


        Orthogonal to `archivedAt`, which is the separate lifecycle axis:
        archiving is the client

        voluntarily retiring the address, REJECTED is an outcome the platform
        recorded.
      example: ACTIVE
    Verification:
      oneOf:
        - $ref: '#/components/schemas/NameMatchVerification'
      type: object
      discriminator:
        propertyName: kind
        mapping:
          NAME_MATCH: '#/components/schemas/NameMatchVerification'
    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'
    BankAccount:
      oneOf:
        - $ref: '#/components/schemas/SepaBankAccount'
        - $ref: '#/components/schemas/SwiftBankAccount'
        - $ref: '#/components/schemas/InLocalBankAccount'
        - $ref: '#/components/schemas/MxLocalBankAccount'
        - $ref: '#/components/schemas/CoLocalBankAccount'
        - $ref: '#/components/schemas/CoBrebBankAccount'
        - $ref: '#/components/schemas/AeLocalBankAccount'
      title: Bank account routing
      description: >-
        The routable identifiers of a bank account, discriminated on
        `routingFamily`; exactly one

        variant is ever present.


        Extraneous or mismatched fields for the selected member are rejected
        outright, never

        silently dropped. A new supported rail family ships as a new member, so
        tolerate an

        unrecognized `routingFamily`.
      type: object
      discriminator:
        propertyName: routingFamily
        mapping:
          SEPA: '#/components/schemas/SepaBankAccount'
          SWIFT: '#/components/schemas/SwiftBankAccount'
          IN_LOCAL: '#/components/schemas/InLocalBankAccount'
          MX_LOCAL: '#/components/schemas/MxLocalBankAccount'
          CO_LOCAL: '#/components/schemas/CoLocalBankAccount'
          CO_BREB: '#/components/schemas/CoBrebBankAccount'
          AE_LOCAL: '#/components/schemas/AeLocalBankAccount'
    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.
    CreateSepaBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: SEPA
          description: >-
            SEPA-reachable: the platform can pay this account over the SEPA
            scheme.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or
            `identity.individual.firstName`

            and `identity.individual.lastName` joined for an individual.
          example: Nadia Holdings Pvt Ltd
          type: string
        accountNumber:
          type: string
          pattern: ^[\sA-Za-z0-9]+$
          description: >-
            The IBAN, ISO 13616.


            Surrounding and internal whitespace is stripped and the value
            uppercased before

            validation, so nl91 abna 0417 1643 00 and NL91ABNA0417164300 are the
            same input. The

            mod-97 checksum and per-country length are checked on the normalized
            value.
          example: DE89 3704 0044 0532 0130 00
        bic:
          description: >-
            The bank's BIC, ISO 9362, where the account has one.


            Optional here. Supplying it also makes the account payable over
            SWIFT, which

            `supportedRails` reports.
          example: COBADEFFXXX
          type: string
          pattern: ^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$
      required:
        - routingFamily
        - accountNumber
      additionalProperties: false
      title: SEPA bank account
      description: >-
        An account the platform can pay over SEPA.


        The IBAN's country must sit in the SEPA scheme roster, checked at
        creation and rejected as

        a validation error. A euro account the SEPA scheme does not reach, and
        one with no IBAN at

        all, belong on the SWIFT arm instead. Reachability of the specific IBAN
        is verified

        synchronously as the address is set up, and an unreachable account is
        rejected in that call

        rather than settling later through the address lifecycle.
    CreateSwiftBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: SWIFT
          description: >-
            Correspondent banking: the platform can pay this account through the
            banks between it and us.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account, up to 140
            characters.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or

            `identity.individual.firstName` and `identity.individual.lastName`
            joined for an

            individual.
          example: Novalia Handels GmbH
          type: string
          maxLength: 140
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
        accountNumber:
          type: string
          pattern: ^[\sA-Za-z0-9]+$
          description: >-
            The account number at the bank, an IBAN or the bank's own, up to 34
            characters.


            Surrounding and internal whitespace is stripped and the value
            uppercased before

            validation. A value shaped like an IBAN is then validated as one, so
            a mistyped IBAN is

            rejected rather than accepted as an ordinary account number.
          example: 8801 234567
        bic:
          type: string
          pattern: ^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$
          description: >-
            The bank's BIC, ISO 9362.


            Eight or eleven characters. Its fifth and sixth name the bank's
            country, which must be one

            the platform can pay SWIFT into, checked when the address is
            created.
          example: PAVEGE22XXX
        accountHolderAddress:
          $ref: '#/components/schemas/AccountHolderAddress'
      required:
        - routingFamily
        - accountNumber
        - bic
        - accountHolderAddress
      additionalProperties: false
      title: SWIFT bank account
      description: >-
        A euro account the platform can pay by correspondent banking, for
        destinations the SEPA

        scheme does not reach.


        An IBAN whose country sits in the SEPA scheme roster is accepted here
        too, and an account

        that has one is paid over SEPA. Where it has none, the BIC's country
        must be one the platform

        can pay SWIFT into, and no name check runs against the account.
    CreateInLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: IN_LOCAL
          description: >-
            The Indian domestic bundle: IMPS, NEFT and RTGS, routed by IFSC and
            account number.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or
            `identity.individual.firstName`

            and `identity.individual.lastName` joined for an individual.
          example: Nadia Holdings Pvt Ltd
          type: string
        ifsc:
          type: string
          pattern: ^[A-Z]{4}0[A-Z0-9]{6}$
          description: >-
            The 11-character IFSC identifying the branch: four bank letters, a
            zero, then six branch characters.
          example: HDFC0001234
        accountNumber:
          type: string
          pattern: ^[\s0-9]+$
          description: >-
            The account number at that branch, 9 to 18 digits.


            Surrounding and internal whitespace is stripped before validation,
            so a space-grouped

            account number is accepted as written. No other separator is: a
            dash, slash or dot is

            left in place and fails the digits-only check.
          example: 5010 0234 5678 90
        isNre:
          description: >-
            Whether this is a repatriable NRE account, funded from abroad, with
            the balance freely

            repatriable, principal and interest both.


            Optional, and defaults to false when omitted, covering an NRO
            account (a non-resident's

            account for income arising in India, where repatriation is capped
            per financial year and

            needs tax certification) and an ordinary account held by an Indian
            resident alike.
          example: false
          type: boolean
        bankAccountType:
          x-enum-descriptions:
            SAVINGS: A personal deposit account.
            CURRENT: A business transaction account.
          description: |-
            Which kind of account this is at the institution.

            Optional, and defaults to `SAVINGS` when omitted.
          example: SAVINGS
          type: string
          enum:
            - SAVINGS
            - CURRENT
      required:
        - routingFamily
        - ifsc
        - accountNumber
      additionalProperties: false
      title: Indian bank account
      description: |-
        An Indian account, routed by IFSC and account number.

        Derived rails: IMPS, NEFT and RTGS.
    CreateMxLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: MX_LOCAL
          description: 'The Mexican domestic system: SPEI, routed by CLABE.'
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or
            `identity.individual.firstName`

            and `identity.individual.lastName` joined for an individual.
          example: Nadia Holdings Pvt Ltd
          type: string
        accountNumber:
          type: string
          pattern: ^[\s0-9]+$
          description: >-
            The CLABE, Mexico's 18-digit standardized account number.


            Surrounding and internal whitespace is stripped before validation.
            The stripped value

            must be 18 digits whose last digit is the CLABE check digit, so a
            mistyped CLABE is

            rejected as a validation error rather than accepted.
          example: 012 180 00123456789 9
      required:
        - routingFamily
        - accountNumber
      additionalProperties: false
      title: Mexican bank account
      description: >-
        A Mexican account, routed by CLABE. Derived rail: SPEI, in MXN.


        The account holder is checked after creation, usually within minutes and
        only during Mexican

        banking hours. The address does not wait for that check: it can be
        `ACTIVE` while the check is

        still `PENDING`, and only a `NO_MATCH` result rejects it. The account
        holder sees

        your organization as the payer.
    CreateCoLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: CO_LOCAL
          description: >-
            The Colombian domestic bank transfer, routed by bank code, account
            number and account type.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or
            `identity.individual.firstName`

            and `identity.individual.lastName` joined for an individual.
          example: Nadia Holdings Pvt Ltd
          type: string
        bankCode:
          type: string
          pattern: ^[0-9]{4}$
          description: The four-digit code of the bank holding the account.
          example: '1007'
        accountNumber:
          type: string
          pattern: ^[\s0-9]+$
          description: >-
            The account number at that bank, 4 to 20 digits.


            Surrounding and internal whitespace is stripped before validation,
            so a space-grouped

            account number is accepted as written. No other separator is: a
            dash, slash or dot is

            left in place and fails the digits-only check.
          example: 245 1234 5678
        bankAccountType:
          type: string
          enum:
            - CHECKING
            - SAVINGS
            - ELECTRONIC_DEPOSIT
          x-enum-descriptions:
            CHECKING: >-
              A current account, cuenta corriente, which carries a checkbook and
              is the usual business account.
            SAVINGS: >-
              A savings account, cuenta de ahorros, the account most individuals
              hold.
            ELECTRONIC_DEPOSIT: >-
              A low-value electronic deposit account, depósito electrónico,
              opened through a phone rather than at a branch. Not every bank
              offers one.
          description: >-
            Which kind of account this is at the bank.


            Checked when the address is created against the kinds the bank named
            by `bankCode`

            accepts, and a kind it does not accept is rejected as a validation
            error.
          example: SAVINGS
      required:
        - routingFamily
        - bankCode
        - accountNumber
        - bankAccountType
      additionalProperties: false
      title: Colombian bank account
      description: >-
        A Colombian bank account, routed by bank code, account number and
        account type. Derived rail:

        CO_ACH, in COP.


        No name check runs against the account, so `verifications[]` stays
        empty. The account holder

        sees Pexto Colombia SAS as the payer, whoever the payout is for, and
        `receiverMemo` is the only

        other text that reaches them.
    CreateCoBrebBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: CO_BREB
          description: >-
            Colombia's instant transfer system, Bre-B, routed by a key the
            account holder registered.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its

            `identity.organization.legalName` for an organization, or
            `identity.individual.firstName`

            and `identity.individual.lastName` joined for an individual.
          example: Nadia Holdings Pvt Ltd
          type: string
        brebKey:
          type: string
          minLength: 1
          maxLength: 255
          pattern: ^\S+$
          description: >-
            The Bre-B key the account holder registered, written exactly as they
            gave it: a mobile

            number, an email address, an identity document number, or a handle
            with its leading

            `@`.


            The kind of key is not supplied and not needed. The key is looked up
            as the address is

            set up, and that lookup, not a format check, is what establishes the
            key reaches the

            named account holder.
          example: '@camilarestrepo'
      required:
        - routingFamily
        - brebKey
      additionalProperties: false
      title: Bre-B key
      description: >-
        A Colombian account reached through a Bre-B key rather than an account
        number. Derived rail:

        BREB, in COP.


        The key is looked up as the address is set up, and only a `NO_MATCH`
        result rejects the

        address: a lookup that cannot be completed leaves it payable. The
        account holder sees the payer

        as PXT followed by your organization's name.
    CreateAeLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: AE_LOCAL
          description: The UAE domestic bank transfer, routed by IBAN.
        accountHolderName:
          description: >-
            The name the receiving institution holds for this account.


            Optional, and inherits the linked account's own name when omitted:
            its `identity.organization.legalName` for an organization, or
            `identity.individual.firstName` and `identity.individual.lastName`
            joined for an individual.


            Supplied or inherited, the name must be at most 75 bytes in UTF-8
            and use only the letters A to Z, digits, spaces and / – ? : - ( ) .
            , ' + &, and an individual's name carries no digits. A name outside
            these rules is rejected as a validation error, so an account whose
            own name breaks them needs `accountHolderName` supplied explicitly.
          example: Falcon Trading LLC
          type: string
        accountNumber:
          type: string
          pattern: ^[\sA-Za-z0-9]+$
          description: >-
            The IBAN, ISO 13616, of an account held in the United Arab Emirates.


            Surrounding and internal whitespace is stripped and the value
            uppercased before validation, so ae07 0331 2345 6789 0123 456 and
            AE070331234567890123456 are the same input. The normalized value
            must start AE, be 23 characters long and pass the mod-97 checksum.
            An IBAN from any other country is rejected as a validation error,
            however valid it is.
          example: AE07 0331 2345 6789 0123 456
      required:
        - routingFamily
        - accountNumber
      additionalProperties: false
      title: UAE bank account
      description: >-
        An account held in the United Arab Emirates, routed by IBAN. Derived
        rail: AE_LOCAL, in AED.


        The IBAN carries the bank, so no BIC, bank code or account type is
        taken. No name check runs against the account, so `verifications[]`
        stays empty. The account holder sees your organization as the payer,
        whoever the payout is for, and `receiverMemo` is the only other text
        that reaches them.
    NameMatchVerification:
      type: object
      properties:
        kind:
          type: string
          const: NAME_MATCH
        mode:
          $ref: '#/components/schemas/NameMatchMode'
        result:
          $ref: '#/components/schemas/NameMatchResult'
        providedName:
          type: string
          description: >-
            The name that was submitted for comparison, frozen as it stood when
            the act ran.


            On a payout address this is the `accountHolderName` supplied at
            create. On a payout it

            is the same string as it stood when that act ran: a fresh check at
            payout create, or the

            reused setup act.
          example: Nadia Holdings Pvt Ltd
        registeredName:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The name the receiving institution holds, as it was returned.


            Null where the scheme returned no name, which every result other
            than `MATCH`,

            `CLOSE_MATCH` and `ACCOUNT_TYPE_MISMATCH` may do. Where it is
            present and differs, it

            is the exact string to use as `accountHolderName` on a replacement
            payout address.
          example: Nadia Holdings Private Limited
        createdAt:
          $ref: '#/components/schemas/Timestamp'
          description: When this act was started.
          example: '2026-06-04T10:30:00.000Z'
        verifiedAt:
          anyOf:
            - $ref: '#/components/schemas/Timestamp'
            - type: 'null'
          description: >-
            When this act resolved. Null while `result` is PENDING, never a
            placeholder value.
          example: '2026-06-04T10:35:12.000Z'
        expiresAt:
          anyOf:
            - $ref: '#/components/schemas/Timestamp'
            - type: 'null'
          description: >-
            When this result goes stale, or null when it does not expire.


            No mode this API supports populates it today, and a caller has no
            way to trigger a

            re-check.
          example: '2026-12-04T10:35:12.000Z'
      required:
        - kind
        - mode
        - result
        - providedName
        - registeredName
        - createdAt
        - verifiedAt
        - expiresAt
      additionalProperties: false
      title: Name match
      description: >-
        A name match: the account holder name the caller supplied, compared
        against the name the

        receiving institution holds.


        Always run when the payout address is created. At payout create the same
        comparison runs

        again only when regulation requires a fresh check; otherwise the
        address's existing

        verification is reused, and it reaches the caller as an entry in that
        payout's

        `confirmations[]` rather than as a verification.


        Both names are frozen on the act, so the record stays readable after the
        payout address it

        describes has been replaced.
    SepaBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: SEPA
          description: >-
            SEPA-reachable: the platform can pay this account over the SEPA
            scheme.
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it: a name match
            runs this string

            against the name the receiving institution holds for the account. An
            account registered as

            `N. Mehta` for `Nadia Mehta` is correct here. Inherited from the
            linked account's own

            `identity` where the create request omitted it.
          example: Nadia Holdings Pvt Ltd
        country:
          $ref: '#/components/schemas/CountryCode'
          description: Where the account is held, read from the IBAN prefix.
          example: DE
        accountNumber:
          type: string
          pattern: ^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$
          description: >-
            The IBAN, ISO 13616.


            Two country letters, two check digits, then up to 30 alphanumeric
            characters. The

            mod-97 checksum and the per-country length are checked too, so a
            well-formed IBAN

            failing either is rejected as a validation error.
          example: DE89370400440532013000
        bic:
          description: >-
            The bank's BIC, ISO 9362, where the account has one.


            Optional here. Supplying it also makes the account payable over
            SWIFT, which

            `supportedRails` reports.
          example: COBADEFFXXX
          type: string
          pattern: ^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$
      required:
        - routingFamily
        - accountHolderName
        - accountNumber
        - country
      additionalProperties: false
      title: SEPA bank account
      description: >-
        An account the platform can pay over SEPA.


        The IBAN's country must sit in the SEPA scheme roster, checked at
        creation and rejected as

        a validation error. A euro account the SEPA scheme does not reach, and
        one with no IBAN at

        all, belong on the SWIFT arm instead. Reachability of the specific IBAN
        is verified

        synchronously as the address is set up, and an unreachable account is
        rejected in that call

        rather than settling later through the address lifecycle.
    SwiftBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: SWIFT
          description: >-
            Correspondent banking: the platform can pay this account through the
            banks between it and us.
        accountHolderName:
          type: string
          maxLength: 140
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
          description: >-
            The name the receiving institution holds for this account, up to 140
            characters.


            Not the identity's name and not compared against it: an account
            registered as `N. Mehta`

            for `Nadia Mehta` is correct here. Inherited from the linked
            account's own `identity`

            where the create request omitted it.
          example: Novalia Handels GmbH
        accountNumber:
          type: string
          pattern: ^[A-Z0-9]{1,34}$
          description: >-
            The account number at the bank, an IBAN or the bank's own, up to 34
            characters.


            Uppercase and contiguous, whatever grouping it was supplied in.
          example: '8801234567'
        bic:
          type: string
          pattern: ^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$
          description: >-
            The bank's BIC, ISO 9362.


            Eight or eleven characters. Its fifth and sixth name the bank's
            country, which must be one

            the platform can pay SWIFT into, checked when the address is
            created.
          example: PAVEGE22XXX
        accountHolderAddress:
          $ref: '#/components/schemas/AccountHolderAddress'
        country:
          $ref: '#/components/schemas/CountryCode'
          description: Where the account is held, read from the BIC's country characters.
          example: GE
      required:
        - routingFamily
        - accountHolderName
        - accountNumber
        - bic
        - accountHolderAddress
        - country
      additionalProperties: false
      title: SWIFT bank account
      description: >-
        A euro account the platform can pay by correspondent banking, for
        destinations the SEPA

        scheme does not reach.


        An IBAN whose country sits in the SEPA scheme roster is accepted here
        too, and an account

        that has one is paid over SEPA. Where it has none, the BIC's country
        must be one the platform

        can pay SWIFT into, and no name check runs against the account.
    InLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: IN_LOCAL
          description: >-
            The Indian domestic bundle: IMPS, NEFT and RTGS, routed by IFSC and
            account number.
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it: a name match
            runs this string

            against the name the receiving institution holds for the account. An
            account registered as

            `N. Mehta` for `Nadia Mehta` is correct here. Inherited from the
            linked account's own

            `identity` where the create request omitted it.
          example: Nadia Holdings Pvt Ltd
        ifsc:
          type: string
          pattern: ^[A-Z]{4}0[A-Z0-9]{6}$
          description: >-
            The 11-character IFSC identifying the branch: four bank letters, a
            zero, then six branch characters.
          example: HDFC0001234
        accountNumber:
          type: string
          pattern: ^[0-9]{9,18}$
          description: The account number at that branch, 9 to 18 digits.
          example: '50100234567890'
        isNre:
          type: boolean
          description: >-
            Whether this is a repatriable NRE account, funded from abroad, with
            the balance freely

            repatriable, principal and interest both.


            False covers an NRO account (a non-resident's account for income
            arising in India, where

            repatriation is capped per financial year and needs tax
            certification) and an ordinary

            account held by an Indian resident alike, and is also what an
            omitted create request

            resolves to.
          example: false
        bankAccountType:
          x-enum-descriptions:
            SAVINGS: A personal deposit account.
            CURRENT: A business transaction account.
          description: |-
            Which kind of account this is at the institution.

            Optional, and defaults to `SAVINGS` when omitted.
          example: SAVINGS
          type: string
          enum:
            - SAVINGS
            - CURRENT
        country:
          $ref: '#/components/schemas/CountryCode'
          description: >-
            Where the account is held. Constant: this arm routes exclusively
            within India.
          example: IN
      required:
        - routingFamily
        - accountHolderName
        - ifsc
        - accountNumber
        - isNre
        - country
      additionalProperties: false
      title: Indian bank account
      description: |-
        An Indian account, routed by IFSC and account number.

        Derived rails: IMPS, NEFT and RTGS.
    MxLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: MX_LOCAL
          description: 'The Mexican domestic system: SPEI, routed by CLABE.'
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it: a name match
            runs this string

            against the name the receiving institution holds for the account. An
            account registered as

            `N. Mehta` for `Nadia Mehta` is correct here. Inherited from the
            linked account's own

            `identity` where the create request omitted it.
          example: Nadia Holdings Pvt Ltd
        accountNumber:
          type: string
          pattern: ^[0-9]{18}$
          description: >-
            The CLABE, Mexico's 18-digit standardized account number.


            Three digits name the bank, three the city, eleven the account, and
            the last is a check

            digit computed from the other seventeen.
          example: '012180001234567899'
        country:
          $ref: '#/components/schemas/CountryCode'
          description: >-
            Where the account is held. Constant: this arm routes exclusively
            within Mexico.
          example: MX
      required:
        - routingFamily
        - accountHolderName
        - accountNumber
        - country
      additionalProperties: false
      title: Mexican bank account
      description: >-
        A Mexican account, routed by CLABE. Derived rail: SPEI, in MXN.


        The account holder is checked after creation, usually within minutes and
        only during Mexican

        banking hours. The address does not wait for that check: it can be
        `ACTIVE` while the check is

        still `PENDING`, and only a `NO_MATCH` result rejects it. The account
        holder sees

        your organization as the payer.
    CoLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: CO_LOCAL
          description: >-
            The Colombian domestic bank transfer, routed by bank code, account
            number and account type.
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it. Inherited from
            the linked account's own

            `identity` where the create request omitted it.
          example: Camila Restrepo
        bankCode:
          type: string
          pattern: ^[0-9]{4}$
          description: The four-digit code of the bank holding the account.
          example: '1007'
        accountNumber:
          type: string
          pattern: ^[0-9]{4,20}$
          description: The account number at that bank, 4 to 20 digits.
          example: '24512345678'
        bankAccountType:
          type: string
          enum:
            - CHECKING
            - SAVINGS
            - ELECTRONIC_DEPOSIT
          x-enum-descriptions:
            CHECKING: >-
              A current account, cuenta corriente, which carries a checkbook and
              is the usual business account.
            SAVINGS: >-
              A savings account, cuenta de ahorros, the account most individuals
              hold.
            ELECTRONIC_DEPOSIT: >-
              A low-value electronic deposit account, depósito electrónico,
              opened through a phone rather than at a branch. Not every bank
              offers one.
          description: >-
            Which kind of account this is at the bank.


            Checked when the address is created against the kinds the bank named
            by `bankCode`

            accepts, and a kind it does not accept is rejected as a validation
            error.
          example: SAVINGS
        country:
          $ref: '#/components/schemas/CountryCode'
          description: >-
            Where the account is held. Constant: this arm routes exclusively
            within Colombia.
          example: CO
      required:
        - routingFamily
        - accountHolderName
        - bankCode
        - accountNumber
        - bankAccountType
        - country
      additionalProperties: false
      title: Colombian bank account
      description: >-
        A Colombian bank account, routed by bank code, account number and
        account type. Derived rail:

        CO_ACH, in COP.


        No name check runs against the account, so `verifications[]` stays
        empty. The account holder

        sees Pexto Colombia SAS as the payer, whoever the payout is for, and
        `receiverMemo` is the only

        other text that reaches them.
    CoBrebBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: CO_BREB
          description: >-
            Colombia's instant transfer system, Bre-B, routed by a key the
            account holder registered.
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it: a name match
            runs this string

            against the name the receiving institution holds for the account. An
            account registered as

            `N. Mehta` for `Nadia Mehta` is correct here. Inherited from the
            linked account's own

            `identity` where the create request omitted it.
          example: Nadia Holdings Pvt Ltd
        brebKey:
          type: string
          minLength: 1
          maxLength: 255
          pattern: ^\S+$
          description: >-
            The Bre-B key the account holder registered, written exactly as they
            gave it: a mobile

            number, an email address, an identity document number, or a handle
            with its leading

            `@`.


            The kind of key is not supplied and not needed. The key is looked up
            as the address is

            set up, and that lookup, not a format check, is what establishes the
            key reaches the

            named account holder.
          example: '@camilarestrepo'
        country:
          $ref: '#/components/schemas/CountryCode'
          description: >-
            Where the account is held. Constant: this arm routes exclusively
            within Colombia.
          example: CO
      required:
        - routingFamily
        - accountHolderName
        - brebKey
        - country
      additionalProperties: false
      title: Bre-B key
      description: >-
        A Colombian account reached through a Bre-B key rather than an account
        number. Derived rail:

        BREB, in COP.


        The key is looked up as the address is set up, and only a `NO_MATCH`
        result rejects the

        address: a lookup that cannot be completed leaves it payable. The
        account holder sees the payer

        as PXT followed by your organization's name.
    AeLocalBankAccount:
      type: object
      properties:
        routingFamily:
          type: string
          const: AE_LOCAL
          description: The UAE domestic bank transfer, routed by IBAN.
        accountHolderName:
          type: string
          description: >-
            The name the receiving institution holds for this account.


            Not the identity's name and not compared against it. Inherited from
            the linked account's own `identity` where the create request omitted
            it.
          example: Falcon Trading LLC
        accountNumber:
          type: string
          pattern: ^AE[0-9]{21}$
          description: >-
            The IBAN, ISO 13616, in electronic format.


            AE, two check digits, a three-digit bank code and a sixteen-digit
            account number.
          example: AE070331234567890123456
        country:
          $ref: '#/components/schemas/CountryCode'
          description: >-
            Where the account is held. Constant: this arm routes exclusively
            within the United Arab Emirates.
          example: AE
      required:
        - routingFamily
        - accountHolderName
        - accountNumber
        - country
      additionalProperties: false
      title: UAE bank account
      description: >-
        An account held in the United Arab Emirates, routed by IBAN. Derived
        rail: AE_LOCAL, in AED.


        The IBAN carries the bank, so no BIC, bank code or account type is
        taken. No name check runs against the account, so `verifications[]`
        stays empty. The account holder sees your organization as the payer,
        whoever the payout is for, and `receiverMemo` is the only other text
        that reaches them.
    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.
    AccountHolderAddress:
      type: object
      properties:
        country:
          $ref: '#/components/schemas/CountryCode'
          description: The country the address is in.
          example: DE
        city:
          type: string
          maxLength: 35
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
          description: Town or city.
          example: Berlin
        line1:
          description: Street name and number.
          example: Friedrichstrasse 100
          type: string
          maxLength: 70
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
        line2:
          description: A second street line, for a floor, a unit or a care-of name.
          example: Floor 3
          type: string
          maxLength: 70
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
        postalCode:
          description: Postal or ZIP code.
          example: '10117'
          type: string
          maxLength: 16
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
        state:
          description: >-
            State, province or region. No format is claimed, so write it as the
            country's own post would.
          example: Berlin
          type: string
          maxLength: 35
          pattern: ^[A-Za-z0-9/\-?:().,'+ ]+$
      required:
        - country
        - city
      additionalProperties: false
      title: Account holder address
      description: >-
        The postal address the account holder is at.


        Its town and country travel with the payment, so both are required.
        Letters, digits,

        space and the punctuation `/ - ? : ( ) . , ' +` are accepted, and any
        other character

        is rejected.
    NameMatchMode:
      type: string
      enum:
        - SEPA_VOP
        - IMPS_PENNY_DROP
        - SPEI_ACCOUNT_OWNERSHIP
        - BREB_KEY_LOOKUP
      x-enum-descriptions:
        SEPA_VOP: >-
          The SEPA Verification of Payee scheme. Always run when the payout
          address is created, and again at payout create because SEPA regulation
          requires a fresh check; the confirmation is that second act, not a
          reuse of the setup one.
        IMPS_PENNY_DROP: >-
          A penny drop over India's IMPS rail: a micro-deposit the receiving
          bank returns the registered account holder name for. On the name it
          resolves to `MATCH`, `NO_MATCH` or `ACCOUNT_TYPE_MISMATCH`, never a
          middle result; it can also come back `UNAVAILABLE` when the scheme or
          network does not answer, which says nothing about the name and does
          not block the payout. Always run when the payout address is created.
          India does not require a fresh check per payout, so the existing
          verification is reused as the confirmation.
        SPEI_ACCOUNT_OWNERSHIP: >-
          A check that the CLABE is held by the named account holder, run over
          Mexico's SPEI system. Started when the payout address is created and
          resolved later, usually within minutes and only during Mexican banking
          hours. The address does not wait for it, so a payout can be created
          while it reads `PENDING`, and the confirmation reuses it as it stands
          then. A later `NO_MATCH` still rejects the address.
        BREB_KEY_LOOKUP: >-
          A real-time lookup of the Bre-B key, comparing the holder it is
          registered to against the named account holder. Run once when the
          payout address is created; an `UNAVAILABLE` result leaves the address
          payable, and the confirmation reuses the setup act.
      description: >-
        The scheme under which a name match was performed. A name match always
        runs when the payout address is created. At payout create it runs again
        only when regulation requires a fresh check; otherwise the address's
        existing verification is reused.
      example: SEPA_VOP
    NameMatchResult:
      type: string
      enum:
        - PENDING
        - MATCH
        - CLOSE_MATCH
        - NO_MATCH
        - ACCOUNT_TYPE_MISMATCH
        - UNAVAILABLE
        - DEFERRED_TO_RECEIVING_FI
      x-enum-descriptions:
        PENDING: >-
          The check has not returned yet. Not blocking, and `verifiedAt` is null
          while it stands.
        MATCH: >-
          The two names agree exactly, which is what separates this from
          `CLOSE_MATCH`. Not blocking.
        CLOSE_MATCH: >-
          The names differ in a way consistent with the same holder, such as
          initials against a full given name, or a trading name against a
          registered one. Not blocking: a payout address carrying one stays
          payable, and a payout carrying one is sent.
        NO_MATCH: >-
          The names are not the same holder. Blocking on a payout address, which
          cannot back a payout while it stands. On a payout it blocks nothing by
          itself: it is the result the caller is shown before confirming, and
          confirming proceeds anyway.
        ACCOUNT_TYPE_MISMATCH: >-
          The name agrees, but the account kind does not: the `isNre` the payout
          address declared disagrees with what the receiving bank holds for the
          account. Blocking on a payout address exactly as `NO_MATCH` is, and
          the remedy is a replacement address declaring the kind the bank holds.
        UNAVAILABLE: >-
          The check could not be completed, because the scheme, the institution
          or the network did not answer. Not blocking, and says nothing about
          the name.
        DEFERRED_TO_RECEIVING_FI: >-
          The scheme returned no verdict and left the decision to the receiving
          institution at settlement. Not blocking here, and the payout may still
          be returned later.
      description: >-
        How the supplied account holder name compared against the name the
        receiving institution

        holds.


        On a payout address a `NO_MATCH` leaves the address unable to back a
        payout, and the

        remedy is a replacement address carrying the name the institution holds,
        which is what

        `registeredName` records. On a payout the result reaches the caller as a

        `Confirmation` entry before any funds move, and confirming accepts
        whatever it says.
      example: MATCH
    CountryCode:
      type: string
      pattern: ^[A-Z]{2}$
      description: >-
        ISO 3166-1 alpha-2 country code, matching `^[A-Z]{2}$`.


        Uppercase and case-sensitive: a lowercase code is rejected rather than
        normalized.
  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
    IdempotencyReplayed:
      description: >-
        Whether this response was replayed from a stored idempotent result
        (true) or freshly executed (false). Present on the idempotent writes.
      schema:
        type: boolean
      example: false
    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.

````