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

# Register a card

> Register a debit card as a customer-owned External Account. Card numbers are accepted only on this dedicated endpoint; reads, lists and deletes stay unified on the other External Account routes. `details.brand` is derived server-side from the card number. Only `debit` cards are supported; other card types are rejected at provisioning. `billingAddress` is optional and falls back to the customer's address. A per-customer velocity guard returns 429 `TooManyCardAttempts` (with a `Retry-After` header) against card-testing abuse.

**Card input depends on the environment.** Production live requires VGS-enabled card registration: `details.cardNumber` and `details.cvv` must be VGS aliases, and raw values are rejected with `CardNumberInvalid` or `CVVInvalid`. Collect real card data with the Polygon SDK's hosted card form. The server-to-server VGS path for this endpoint is not available yet; do not send real card data directly to the API.

In sandbox environments with VGS disabled, send only test card data: `details.cardNumber` must contain 12–19 digits and `details.cvv` must contain 3–4 digits. Those environments reject VGS aliases. A VGS-enabled sandbox instead requires aliases, as in the example below. Confirm the sandbox's input mode before integrating.

**Uniqueness.** A card already registered with the card provider returns `409 externalAccountAlreadyRegistered`, WITHOUT `details`: the provider's dedupe is global (it spans customers and partners), so the blocking registration is frequently not an account in this project and cannot be named.

**Country screening.** A billing country, or the owner's KYC country, on the compliance prohibited-jurisdictions list is not a 4xx: the create returns `201` with `status=rejected` and `failure.code=countryProhibited`, and the card is never sent to the provider. If the owning customer's address country is not a recognised country (so it cannot be screened), the create returns `422 billingAddressInvalid`; correct the customer's address.

**Billing address lines.** `line1` and `line2` must each be at most 35 UTF-16 code units (a supplementary character counts as two), must not be digits only or a PO Box, and must not contain any of `!@#$%^&*()+=<>.,;:?"/\|}{[]~_`. A supplied address that breaks a line rule returns `422 billingAddressInvalid` naming `billingAddress.line1` or `line2`. When `billingAddress` is omitted and the customer's own address breaks one, the create returns `422 billingAddressInvalid` naming the customer's address (not `missingBillingAddress`); supply `billingAddress` or correct the customer's address. Supplied nonblank lines are sent as given, including leading and trailing whitespace, which counts toward the limit. A `line2` of only whitespace is treated as absent and not sent. The line rules apply only to an address that passes country screening: a prohibited country is still `201` with `status=rejected`.

**Cardholder name.** The card is registered under the owning customer's `firstName` and `lastName`; any name in `billingAddress` is ignored. Latin letters are folded to ASCII (José and Yıldız become Jose and Yildiz), hyphens become spaces and apostrophes are dropped; a name that still cannot be used returns `422 cardholderNameInvalid` (correct the customer's name). An owning customer that is not an individual returns `422 accountTypeRequirementsNotMet`.



## OpenAPI

````yaml /api-reference/openapi.yaml post /external-accounts/cards
openapi: 3.0.3
info:
  title: Polygon OMS Public API
  version: v26.11.3-0001
  description: >-
    Unified API for moving money between crypto and fiat. Three ways to move
    money: Transactions (instant, wallet or card funded, including Cash-In for
    in-person cash deposits), Deposit Addresses (reusable crypto deposit
    configurations), and Virtual Accounts (dedicated bank accounts that
    auto-convert fiat to crypto). Standard transactions follow a two-step flow:
    create a Quote (pricing), then create a Transaction (execution). Cash-in
    codes generate a one-time deposit code for in-person cash deposits at retail
    locations.
  contact:
    name: Polygon OMS
    url: https://oms.polygon.technology
servers:
  - url: https://sandbox-api.polygon.technology/v0.13
    description: Sandbox
  - url: https://api.polygon.technology/v0.13
    description: Production
security:
  - BearerAuth: []
tags:
  - name: Auth
    description: Authentication via OMS API key and secret
  - name: Customers
    description: Customer management and KYC
  - name: Customer
  - name: Wallet
  - name: Quote
  - name: Transaction
  - name: Transfer
  - name: CashIns
  - name: CashLocation
  - name: Sandbox
  - name: VirtualAccount
  - name: Counterparty
  - name: ExternalAccount
  - name: Reference
  - name: DepositAddress
  - name: Indexer
    description: >-
      Read token balances, prices, and transaction history across EVM networks,
      Solana, and Tron. Indexer methods are webRPC calls: each is a `POST` with
      a JSON body, served at `/v1/{Service}/{Method}` on the API host rather
      than under the `/v0.13` base path. Authenticate with a publishable key in
      the `Api-Key` header, or with a bearer token from `POST /auth/token`.
paths:
  /external-accounts/cards:
    post:
      tags:
        - ExternalAccount
      summary: Register a card
      description: >-
        Register a debit card as a customer-owned External Account. Card numbers
        are accepted only on this dedicated endpoint; reads, lists and deletes
        stay unified on the other External Account routes. `details.brand` is
        derived server-side from the card number. Only `debit` cards are
        supported; other card types are rejected at provisioning.
        `billingAddress` is optional and falls back to the customer's address. A
        per-customer velocity guard returns 429 `TooManyCardAttempts` (with a
        `Retry-After` header) against card-testing abuse.


        **Card input depends on the environment.** Production live requires
        VGS-enabled card registration: `details.cardNumber` and `details.cvv`
        must be VGS aliases, and raw values are rejected with
        `CardNumberInvalid` or `CVVInvalid`. Collect real card data with the
        Polygon SDK's hosted card form. The server-to-server VGS path for this
        endpoint is not available yet; do not send real card data directly to
        the API.


        In sandbox environments with VGS disabled, send only test card data:
        `details.cardNumber` must contain 12–19 digits and `details.cvv` must
        contain 3–4 digits. Those environments reject VGS aliases. A VGS-enabled
        sandbox instead requires aliases, as in the example below. Confirm the
        sandbox's input mode before integrating.


        **Uniqueness.** A card already registered with the card provider returns
        `409 externalAccountAlreadyRegistered`, WITHOUT `details`: the
        provider's dedupe is global (it spans customers and partners), so the
        blocking registration is frequently not an account in this project and
        cannot be named.


        **Country screening.** A billing country, or the owner's KYC country, on
        the compliance prohibited-jurisdictions list is not a 4xx: the create
        returns `201` with `status=rejected` and
        `failure.code=countryProhibited`, and the card is never sent to the
        provider. If the owning customer's address country is not a recognised
        country (so it cannot be screened), the create returns `422
        billingAddressInvalid`; correct the customer's address.


        **Billing address lines.** `line1` and `line2` must each be at most 35
        UTF-16 code units (a supplementary character counts as two), must not be
        digits only or a PO Box, and must not contain any of
        `!@#$%^&*()+=<>.,;:?"/\|}{[]~_`. A supplied address that breaks a line
        rule returns `422 billingAddressInvalid` naming `billingAddress.line1`
        or `line2`. When `billingAddress` is omitted and the customer's own
        address breaks one, the create returns `422 billingAddressInvalid`
        naming the customer's address (not `missingBillingAddress`); supply
        `billingAddress` or correct the customer's address. Supplied nonblank
        lines are sent as given, including leading and trailing whitespace,
        which counts toward the limit. A `line2` of only whitespace is treated
        as absent and not sent. The line rules apply only to an address that
        passes country screening: a prohibited country is still `201` with
        `status=rejected`.


        **Cardholder name.** The card is registered under the owning customer's
        `firstName` and `lastName`; any name in `billingAddress` is ignored.
        Latin letters are folded to ASCII (José and Yıldız become Jose and
        Yildiz), hyphens become spaces and apostrophes are dropped; a name that
        still cannot be used returns `422 cardholderNameInvalid` (correct the
        customer's name). An owning customer that is not an individual returns
        `422 accountTypeRequirementsNotMet`.
      operationId: createCardExternalAccount
      parameters:
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardRequest'
            examples:
              Debit card, VGS-aliased:
                summary: Debit card, VGS-aliased
                value:
                  customerId: cst_vfa0nxw6zvyws9g237jrxn4y7k
                  details:
                    cardNumber: 424242Xk9bT24242
                    cvv: tok_live_7d2Hq9xVb3
                    expiryMonth: 12
                    expiryYear: 2029
                  billingAddress:
                    firstName: Alice
                    lastName: Smith
                    line1: 100 Main St
                    city: Seattle
                    state: WA
                    country: US
                    zipCode: '98101'
                  webSessionId: ws_7f3c9a1e2b4d
                  deviceFingerprint: fp_5e8a2c7d9b1f
                  label: Alice debit card
      responses:
        '201':
          description: >-
            The request has succeeded and a new resource has been created as a
            result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalAccount'
              examples:
                Debit card, VGS-aliased:
                  summary: Debit card, VGS-aliased
                  value:
                    id: ext_7n2k4m8p1q3r5s9t0v6w2x4yzb
                    type: card
                    customer:
                      id: cst_vfa0nxw6zvyws9g237jrxn4y7k
                    asset: usd
                    details:
                      brand: visa
                      last4: '4242'
                      cardType: debit
                      expiryMonth: 12
                      expiryYear: 2029
                      billingAddressSource: provided
                    status: pending
                    label: Alice debit card
                    createdAt: '2026-05-14T10:00:00Z'
                    updatedAt: '2026-05-14T10:00:00Z'
        '400':
          description: The server could not understand the request due to invalid syntax.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/InvalidRequestBodyErrorResponse'
                  - $ref: '#/components/schemas/CardLegacyBadRequestErrorResponse'
                  - $ref: '#/components/schemas/InvalidMetadataErrorResponse'
                  - $ref: '#/components/schemas/MetadataKeyTooLongErrorResponse'
                  - $ref: '#/components/schemas/MetadataTooManyKeysErrorResponse'
                  - $ref: '#/components/schemas/MetadataValueTooLongErrorResponse'
        '401':
          description: Access is unauthorized.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/UnauthorizedErrorResponse'
                  - $ref: '#/components/schemas/CardLegacyProjectMissingErrorResponse'
        '404':
          description: The customer does not exist on this project.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardCustomerNotFoundErrorResponse'
        '409':
          description: >-
            This owner, or for a `bankUs` account with a custodial provider this
            customer, has already registered this external account. Returned as
            409 `externalAccountAlreadyRegistered`, and on this error `code`
            carries that same string rather than the numeric `code` of the
            standard error envelope; branch on it as a string here.


            `details` names the account that already holds the registration and
            is returned on the `walletExternal` and `bankUs` create paths. It is
            absent when the provider reports the duplicate itself: always on
            `POST /external-accounts/cards`, where card de-duplication spans the
            card provider's whole platform, so the blocking registration is not
            necessarily one of yours and cannot be named; and on `bankUs` when
            two registrations of the same number race.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/ExternalAccountAlreadyRegisteredErrorResponse
        '413':
          description: The request body exceeds the size limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardLegacyBodyTooLargeErrorResponse'
        '422':
          description: Client error
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/SSNNotVerifiedErrorResponse'
                  - $ref: '#/components/schemas/RiskRejectedErrorResponse'
                  - $ref: '#/components/schemas/UnsupportedCardTypeErrorResponse'
                  - $ref: '#/components/schemas/CardProviderErrorResponse'
                  - $ref: >-
                      #/components/schemas/AccountTypeRequirementsNotMetErrorResponse
                  - $ref: '#/components/schemas/BillingAddressInvalidErrorResponse'
                  - $ref: '#/components/schemas/CardholderNameInvalidErrorResponse'
                  - $ref: '#/components/schemas/CVVInvalidErrorResponse'
                  - $ref: '#/components/schemas/CardExpiredErrorResponse'
                  - $ref: '#/components/schemas/CardExpiryInvalidErrorResponse'
                  - $ref: '#/components/schemas/CardNumberInvalidErrorResponse'
                  - $ref: '#/components/schemas/CardLimitReachedErrorResponse'
                  - $ref: '#/components/schemas/CardNotEnabledForProjectErrorResponse'
                  - $ref: '#/components/schemas/TypeUnsupportedErrorResponse'
                  - $ref: '#/components/schemas/MissingBillingAddressErrorResponse'
                  - $ref: '#/components/schemas/OwnerNotActiveErrorResponse'
                  - $ref: '#/components/schemas/UnsupportedCardBrandErrorResponse'
        '429':
          description: Client error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TooManyCardAttemptsErrorResponse'
        '500':
          description: An internal error prevented registration.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/CardLegacyInternalErrorResponse'
                  - $ref: '#/components/schemas/InternalErrorResponse'
        '502':
          description: The card provider could not authenticate the request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardLegacyProviderErrorResponse'
        '503':
          description: Country screening is temporarily unavailable.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: >-
                      #/components/schemas/CardLegacyScreenUnavailableErrorResponse
                  - $ref: '#/components/schemas/ServiceUnavailableErrorResponse'
components:
  parameters:
    IdempotencyKeyHeader:
      name: Idempotency-Key
      in: header
      required: true
      description: >-
        Required on POST and PUT requests. Use a unique value per logical
        mutation attempt, for example a UUID.
      schema:
        type: string
  schemas:
    CardRequest:
      type: object
      required:
        - customerId
        - details
        - webSessionId
        - deviceFingerprint
      properties:
        customerId:
          type: string
          description: Owning customer ID (`cst_` prefix). Cards must be customer-owned.
        details:
          allOf:
            - $ref: '#/components/schemas/CardCreateDetails'
          description: >-
            Card number and CVV plus expiry (write-only); see
            `CardCreateDetails` for VGS-enabled and sandbox test-input
            requirements.
        billingAddress:
          allOf:
            - $ref: '#/components/schemas/ExternalAccountCardBillingAddress'
          description: >-
            Card billing address (issuer AVS / fraud). Optional: when omitted,
            the owning customer's address is used (see `billingAddressSource`).
        webSessionId:
          type: string
          minLength: 1
          maxLength: 1024
          pattern: ^[!-~]+$
          description: >-
            SDK risk session paired with deviceFingerprint. Required, 1–1024
            printable non-space ASCII characters in every environment, including
            sandbox. Forwarded unchanged; write-only, never returned.
        deviceFingerprint:
          type: string
          minLength: 1
          maxLength: 1024
          pattern: ^[!-~]+$
          description: >-
            SDK device fingerprint paired with webSessionId. Required, 1–1024
            printable non-space ASCII characters in every environment, including
            sandbox. Forwarded unchanged; write-only, never returned.
        label:
          type: string
        metadata:
          type: object
          additionalProperties:
            type: string
      description: >-
        Register a card as a customer-owned External Account, via the dedicated
        `POST /external-accounts/cards` endpoint. Cards are always
        customer-owned, so `customerId` is supplied directly here (no owner
        discriminator). The owner must be an individual customer, and the
        cardholder name is always that customer's `firstName` and `lastName` (a
        name the card issuer cannot accept fails with `422
        cardholderNameInvalid`). The card number and CVV live under `details`,
        using aliases in VGS-enabled environments or test digits in sandbox
        environments with VGS disabled. `brand` and `cardType` are derived
        server-side from the card number and are not accepted on the request.
    ExternalAccount:
      type: object
      required:
        - customer
        - details
      properties:
        id:
          allOf:
            - $ref: '#/components/schemas/typeId'
          description: External Account ID (`ext_` prefix).
        type:
          allOf:
            - $ref: '#/components/schemas/ExternalAccountType'
          description: The account type; decides which `details` keys are present.
        customer:
          allOf:
            - $ref: '#/components/schemas/CustomerRef'
          description: >-
            The customer the account is registered for, also when one of their
            counterparties owns it.
        owner:
          allOf:
            - $ref: '#/components/schemas/InstrumentOwner'
          description: >-
            The counterparty that owns the account. Left out when the account is
            the customer's own.
        asset:
          type: string
          description: >-
            `usd` on bank accounts and cards. Left out on wallets, which list
            their assets in `supportedDestinations`.
        supportedDestinations:
          type: array
          items:
            $ref: '#/components/schemas/ExternalAccountSupportedDestination'
          description: >-
            Where this account can be paid, computed per account. A US bank
            account lists the rails it can receive on, narrowed by what your
            project and the platform enable; an account Erebor Bank, N.A.
            provisions reports `ach`, `achSameDay` and `wire`, so a missing
            `rtp` there means unverified, not refused. A wallet lists `usdc` and
            `usdt` on each network its family serves. Left out for IBAN and
            Canadian bank accounts and cards.
        unavailableDestinations:
          type: array
          items:
            $ref: '#/components/schemas/UnavailableBankDestination'
          description: >-
            US bank accounts: rails the project has turned on that this account
            cannot be paid over, each with its reason.
        details:
          allOf:
            - $ref: '#/components/schemas/ExternalAccountDetails'
          description: The account's type-specific values.
        status:
          allOf:
            - $ref: '#/components/schemas/ExternalAccountStatus'
          description: >-
            Current lifecycle status. A transition to `invalid` always fires the
            `externalAccount.statusChanged` webhook.
        failure:
          allOf:
            - $ref: '#/components/schemas/Reason'
          description: >-
            Why the account failed, was rejected or became invalid. Present only
            when `status` is `failed`, `rejected` or `invalid`.
        label:
          type: string
          description: Optional display label.
        metadata:
          type: object
          additionalProperties:
            type: string
          description: Free-form key-value pairs supplied at creation or update.
        createdAt:
          type: string
          format: date-time
          description: When the external account was registered.
        updatedAt:
          type: string
          format: date-time
          description: When the external account was last updated.
      description: >-
        A saved payment destination registered for a customer or one of their
        counterparties. Write-only secrets (full account number, full IBAN) are
        never present on reads, only their last-4 renderings.
    InvalidRequestBodyErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - InvalidRequestBody
        code:
          type: number
          enum:
            - 10091
        msg:
          type: string
          enum:
            - invalid request body
        cause:
          type: string
    CardLegacyBadRequestErrorResponse:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
        code:
          type: string
          enum:
            - invalidRequestBody
            - unknownField
            - invalidCustomerId
        details:
          type: object
          additionalProperties: {}
      description: A malformed request body, unknown field, or invalid customer ID.
    InvalidMetadataErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - InvalidMetadata
        code:
          type: number
          enum:
            - 10133
        msg:
          type: string
          enum:
            - invalid metadata
        cause:
          type: string
    MetadataKeyTooLongErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - MetadataKeyTooLong
        code:
          type: number
          enum:
            - 10075
        msg:
          type: string
          enum:
            - metadata key must be 64 characters or fewer
        cause:
          type: string
    MetadataTooManyKeysErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - MetadataTooManyKeys
        code:
          type: number
          enum:
            - 10074
        msg:
          type: string
          enum:
            - metadata may have at most 20 keys
        cause:
          type: string
    MetadataValueTooLongErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - MetadataValueTooLong
        code:
          type: number
          enum:
            - 10076
        msg:
          type: string
          enum:
            - metadata value must be 500 characters or fewer
        cause:
          type: string
    UnauthorizedErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - Unauthorized
        code:
          type: number
          enum:
            - 1000
        msg:
          type: string
          enum:
            - unauthorized access
        cause:
          type: string
    CardLegacyProjectMissingErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          enum:
            - missing project context
      description: The request has no project context.
    CardCustomerNotFoundErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CustomerNotFound
        code:
          type: number
          enum:
            - 10001
        msg:
          type: string
          enum:
            - customer not found
        cause:
          type: string
      description: The customer does not exist on this project.
    ExternalAccountAlreadyRegisteredErrorResponse:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
        code:
          type: string
          enum:
            - externalAccountAlreadyRegistered
        details:
          $ref: '#/components/schemas/ExternalAccountAlreadyRegisteredDetails'
      description: >-
        This owner, or for a `bankUs` account with a custodial provider this
        customer, has already registered this external account. Returned as 409
        `externalAccountAlreadyRegistered`, and on this error `code` carries
        that same string rather than the numeric `code` of the standard error
        envelope; branch on it as a string here.


        `details` names the account that already holds the registration and is
        returned on the `walletExternal` and `bankUs` create paths. It is absent
        when the provider reports the duplicate itself: always on `POST
        /external-accounts/cards`, where card de-duplication spans the card
        provider's whole platform, so the blocking registration is not
        necessarily one of yours and cannot be named; and on `bankUs` when two
        registrations of the same number race.
    CardLegacyBodyTooLargeErrorResponse:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
        code:
          type: string
          enum:
            - requestBodyTooLarge
      description: The request body exceeds the size limit.
    SSNNotVerifiedErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - SSNNotVerified
        code:
          type: number
          enum:
            - 10032
        msg:
          type: string
          enum:
            - card provider could not verify the customer's SSN
        cause:
          type: string
    RiskRejectedErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - RiskRejected
        code:
          type: number
          enum:
            - 10033
        msg:
          type: string
          enum:
            - card provider rejected the card on risk review
        cause:
          type: string
    UnsupportedCardTypeErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - UnsupportedCardType
        code:
          type: number
          enum:
            - 10064
        msg:
          type: string
          enum:
            - only debit cards are supported
        cause:
          type: string
    CardProviderErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardProvider
        code:
          type: number
          enum:
            - 10034
        msg:
          type: string
          enum:
            - card provider rejected the card
        cause:
          type: string
    AccountTypeRequirementsNotMetErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - AccountTypeRequirementsNotMet
        code:
          type: number
          enum:
            - 10048
        msg:
          type: string
          enum:
            - account type requirements not met for this request
        cause:
          type: string
    BillingAddressInvalidErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - BillingAddressInvalid
        code:
          type: number
          enum:
            - 10063
        msg:
          type: string
          enum:
            - billingAddress.city is required
        cause:
          type: string
    CardholderNameInvalidErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardholderNameInvalid
        code:
          type: number
          enum:
            - 10380
        msg:
          type: string
          enum:
            - the owning customer's name cannot be used as a cardholder name
        cause:
          type: string
    CVVInvalidErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CVVInvalid
        code:
          type: number
          enum:
            - 10058
        msg:
          type: string
          enum:
            - cvv must be 3-4 digits
        cause:
          type: string
    CardExpiredErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardExpired
        code:
          type: number
          enum:
            - 10060
        msg:
          type: string
          enum:
            - card has expired
        cause:
          type: string
    CardExpiryInvalidErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardExpiryInvalid
        code:
          type: number
          enum:
            - 10059
        msg:
          type: string
          enum:
            - expiryMonth must be between 1 and 12
        cause:
          type: string
    CardNumberInvalidErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardNumberInvalid
        code:
          type: number
          enum:
            - 10057
        msg:
          type: string
          enum:
            - cardNumber must be 12-19 digits
        cause:
          type: string
    CardLimitReachedErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardLimitReached
        code:
          type: number
          enum:
            - 10055
        msg:
          type: string
          enum:
            - >-
              customer has reached the maximum number of cards; delete an
              existing card before adding another
        cause:
          type: string
    CardNotEnabledForProjectErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - CardNotEnabledForProject
        code:
          type: number
          enum:
            - 10336
        msg:
          type: string
          enum:
            - cards are not enabled for this project
        cause:
          type: string
    TypeUnsupportedErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - TypeUnsupported
        code:
          type: number
          enum:
            - 10020
        msg:
          type: string
          enum:
            - type is not supported
        cause:
          type: string
    MissingBillingAddressErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - MissingBillingAddress
        code:
          type: number
          enum:
            - 10062
        msg:
          type: string
          enum:
            - billingAddress.line1 is required
        cause:
          type: string
    OwnerNotActiveErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - OwnerNotActive
        code:
          type: number
          enum:
            - 10070
        msg:
          type: string
          enum:
            - counterparty owner is not active
        cause:
          type: string
    UnsupportedCardBrandErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - UnsupportedCardBrand
        code:
          type: number
          enum:
            - 10061
        msg:
          type: string
          enum:
            - card brand is unsupported
        cause:
          type: string
    TooManyCardAttemptsErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - TooManyCardAttempts
        code:
          type: number
          enum:
            - 10065
        msg:
          type: string
          enum:
            - >-
              too many card registration attempts for this customer; please
              retry later
        cause:
          type: string
    CardLegacyInternalErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
        code:
          type: string
      description: An internal error prevented registration.
    InternalErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - Internal
        code:
          type: number
          enum:
            - 10124
        msg:
          type: string
          enum:
            - internal error
        cause:
          type: string
    CardLegacyProviderErrorResponse:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
        code:
          type: string
          enum:
            - providerError
      description: The card provider could not authenticate the request.
    CardLegacyScreenUnavailableErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          enum:
            - country screen unavailable
      description: Country screening is temporarily unavailable.
    ServiceUnavailableErrorResponse:
      type: object
      required:
        - error
        - code
        - msg
      properties:
        error:
          type: string
          enum:
            - ServiceUnavailable
        code:
          type: number
          enum:
            - 5003
        msg:
          type: string
          enum:
            - service unavailable
        cause:
          type: string
    CardCreateDetails:
      type: object
      required:
        - cardNumber
        - cvv
        - expiryMonth
        - expiryYear
      properties:
        cardNumber:
          type: string
          description: >-
            Write-only card number. VGS-enabled environments require a VGS alias
            and reject raw values with `CardNumberInvalid`. Sandbox environments
            with VGS disabled require a 12–19 digit test card number and reject
            aliases. Never returned; the response carries `details.last4`.
        cvv:
          type: string
          description: >-
            Write-only CVV. VGS-enabled environments require a VGS alias and
            reject raw values with `CVVInvalid`. Sandbox environments with VGS
            disabled require a 3–4 digit test CVV and reject aliases. Never
            returned.
        expiryMonth:
          type: integer
          format: int32
          description: 1-12.
        expiryYear:
          type: integer
          format: int32
          description: Four-digit calendar year.
      description: >-
        Card number, CVV and expiry. VGS-enabled environments require aliases
        for `cardNumber` and `cvv`; sandbox environments with VGS disabled
        require raw digits from test cards and reject aliases. Never send real
        card data directly to the API. Both fields are write-only and never
        returned or stored; only the last four digits, brand and expiry are
        kept.
    ExternalAccountCardBillingAddress:
      type: object
      properties:
        firstName:
          type: string
          description: >-
            Ignored. Accepted for compatibility only: the cardholder name is
            always the owning customer's `firstName` and `lastName`.
          deprecated: true
        lastName:
          type: string
          description: >-
            Ignored. Accepted for compatibility only: the cardholder name is
            always the owning customer's `firstName` and `lastName`.
          deprecated: true
        line1:
          type: string
          description: Street address, line 1.
        line2:
          type: string
          description: Street address, line 2.
        city:
          type: string
          description: City.
        state:
          type: string
          description: State / province / region.
        country:
          type: string
          description: ISO 3166-1 alpha-2
        zipCode:
          type: string
          description: ZIP / postal code.
      description: >-
        Card billing address — the address the card issuer has on file for the
        payment instrument, used for issuer AVS / fraud screening. A customer
        may hold cards with differing billing addresses, so it is supplied per
        card by the partner. It is optional: when omitted, the owning customer's
        address is used and the response reports `billingAddressSource =
        customerDefault`.
    typeId:
      type: string
      pattern: >-
        ^[a-z]+_([0-9a-hjkmnp-tv-z]{26}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$
      description: Public TypeID, e.g. `txn_01h455vb4pex5vsknk084sn02q`.
      x-go-type: string
    ExternalAccountType:
      type: string
      enum:
        - bankUs
        - bankIban
        - bankCanada
        - card
        - walletExternal
      description: >-
        External Account type. `card` accounts are registered with `POST
        /external-accounts/cards`.
    CustomerRef:
      type: object
      required:
        - id
      properties:
        id:
          allOf:
            - $ref: '#/components/schemas/typeId'
          description: The customer id (`cst_` prefix).
      description: >-
        The customer, referenced by id; its name and details are on the customer
        resource.
    InstrumentOwner:
      type: object
      required:
        - kind
        - id
      properties:
        kind:
          type: string
          enum:
            - counterparty
            - customer
          description: '`counterparty`, or `customer` for another customer''s account.'
        id:
          allOf:
            - $ref: '#/components/schemas/typeId'
          description: The counterparty (`ctp_`) or customer (`cst_`).
        name:
          type: string
          description: >-
            The counterparty's name. A customer's name is on the customer
            resource.
      description: Who owns an account that is not the resource's customer's.
    ExternalAccountSupportedDestination:
      type: object
      required:
        - asset
      properties:
        asset:
          type: string
          description: Lowercase asset, e.g. `usd` or `usdc`.
        network:
          allOf:
            - $ref: '#/components/schemas/CryptoNetwork'
          description: 'Wallets: the network the asset can be delivered on.'
        rail:
          type: string
          enum:
            - ach
            - achSameDay
            - wire
            - rtp
            - instant
            - intraBank
          description: 'US bank accounts: the rail the account can be paid over.'
        minimumAmount:
          allOf:
            - $ref: '#/components/schemas/decimalString'
          description: >-
            US bank accounts: the minimum transfer amount on this rail. Absent
            when no limit is published for it.
        maximumAmount:
          allOf:
            - $ref: '#/components/schemas/decimalString'
          description: >-
            US bank accounts: the maximum transfer amount on this rail. Absent
            on the same terms as `minimumAmount`.
        default:
          type: boolean
          description: >-
            US bank accounts: true on the rail to pre-select. The client still
            names the rail on every request: OMS never picks one.
        defaultInstantRail:
          allOf:
            - $ref: '#/components/schemas/InstantRail'
          description: 'US bank accounts, instant rail: the instant rail to pre-select.'
        intraBankRail:
          allOf:
            - $ref: '#/components/schemas/IntraBankRail'
          description: 'US bank accounts, intraBank rail: which same-bank rail applies.'
      description: >-
        A destination an external account can be paid to: an (asset, rail) pair
        with its limits for a US bank account, or an (asset, network) pair for a
        wallet.
    UnavailableBankDestination:
      type: object
      required:
        - asset
        - network
        - reason
      properties:
        asset:
          type: string
          description: Fiat currency, e.g. `usd`.
        network:
          type: string
          enum:
            - ach
            - achSameDay
            - wire
            - rtp
            - instant
            - intraBank
          description: The rail that cannot be used.
        reason:
          type: string
          enum:
            - notOnInstantRail
            - notWhitelisted
            - useIntraBank
          description: >-
            Why: the bank is not on the instant rails, the account is not on the
            CRNOW whitelist, or the payment stays inside the bank so another
            rail applies.
      description: >-
        A rail the project has turned on that this account cannot be paid over,
        with the reason. A rail the project has not turned on is not listed.
    ExternalAccountDetails:
      type: object
      properties:
        bankName:
          type: string
          description: Bank accounts.
        accountNumberLast4:
          type: string
          description: '`bankUs` and `bankCanada`.'
        routingNumber:
          type: string
          description: '`bankUs`.'
        accountType:
          allOf:
            - $ref: '#/components/schemas/BankAccountType'
          description: '`bankUs`.'
        holderName:
          type: string
          description: >-
            Bank accounts: the counterparty's name on a counterparty's account,
            the customer's name on the customer's own. Left out when the
            counterparty has no name or the customer's name cannot be read.
        ibanLast4:
          type: string
          description: '`bankIban`.'
        bic:
          type: string
          description: '`bankIban`.'
        countryCode:
          type: string
          description: '`bankIban`: ISO 3166-1 alpha-2 country of the bank.'
        bankAddress:
          allOf:
            - $ref: '#/components/schemas/Address'
          description: '`bankIban`.'
        institutionNumber:
          type: string
          description: '`bankCanada`.'
        transitNumber:
          type: string
          description: '`bankCanada`.'
        brand:
          allOf:
            - $ref: '#/components/schemas/CardBrand'
          description: '`card`.'
        last4:
          type: string
          description: '`card`.'
        cardType:
          allOf:
            - $ref: '#/components/schemas/CardType'
          description: '`card`.'
        expiryMonth:
          type: integer
          format: int32
          description: '`card`.'
        expiryYear:
          type: integer
          format: int32
          description: '`card`.'
        billingAddressSource:
          allOf:
            - $ref: '#/components/schemas/BillingAddressSource'
          description: '`card`.'
        address:
          type: string
          description: '`walletExternal`: the on-chain address, as submitted.'
        custodian:
          type: string
          description: '`walletExternal`: who custodies the wallet, in lowerCamelCase.'
        otherCustodian:
          type: string
          description: '`walletExternal`: the custodian''s name when `custodian` is `other`.'
        networkFamily:
          allOf:
            - $ref: '#/components/schemas/NetworkFamily'
          description: '`walletExternal`.'
      description: >-
        An external account's type-specific values. The keys present depend on
        `type`, and a value OMS does not hold is left out.
    ExternalAccountStatus:
      type: string
      enum:
        - active
        - pending
        - rejected
        - invalid
        - deleted
        - failed
      description: >-
        `pending`: being validated with the provider. `active`: usable.
        `failed`: the account could not be provisioned — the provider declined
        it, provisioning timed out, or an internal error stopped it (see
        `failure`). `rejected`: failed validation at creation (see `failure`).
        `invalid`: became unusable after activation (see `failure`). `deleted`:
        soft-deleted by the developer.
    Reason:
      type: object
      required:
        - code
        - message
        - retryable
      properties:
        code:
          allOf:
            - $ref: '#/components/schemas/ReasonCode'
          description: What went wrong.
        message:
          type: string
          description: A fixed, vendor-neutral sentence for `code`.
        retryable:
          type: boolean
          description: Whether trying the same thing again can succeed.
        bankCode:
          type: string
          description: >-
            The bank's own return code, only on an external account a bank
            return made invalid.
      description: >-
        Why a resource failed, was rejected or became invalid. `message` and
        `retryable` are fixed for each `code`.
    ExternalAccountAlreadyRegisteredDetails:
      type: object
      required:
        - existingAccountId
        - existingAccountStatus
        - matchedOn
      properties:
        existingAccountId:
          allOf:
            - $ref: '#/components/schemas/typeId'
          description: Public id (`ext_…`) of the live account that already holds the key.
        existingAccountStatus:
          allOf:
            - $ref: '#/components/schemas/ExternalAccountStatus'
          description: >-
            Lifecycle status of that account. `failed` and `rejected` never
            appear here — re-registering such an account re-drives it and
            returns `201`.
        matchedOn:
          type: string
          description: >-
            Which uniqueness rule the request collided with:
            `blockchainAddressNetworkFamilyOwner` for `walletExternal` (owner,
            normalised blockchain address and network family), or
            `routingNumberAccountNumberCustomer` for `bankUs` with a custodial
            provider (customer, routing and account number, across every owner).
            Open vocabulary — tolerate a value you do not recognise.
      description: >-
        Machine-readable context for a `409 externalAccountAlreadyRegistered`:
        which account already holds the registration, what state it is in, and
        which uniqueness rule the request collided with.
    CryptoNetwork:
      type: string
      enum:
        - ethereum
        - polygon
        - base
        - solana
        - tron
        - bnb
      description: >-
        Blockchain network identifier: `ethereum`, `polygon`, `base`, `solana`,
        `tron`, `bnb`. Pass the lowercase name — numeric EVM chain IDs (`1`,
        `137`, `8453`, `56`) are not accepted, and responses always return the
        name. This is the wire vocabulary, not an availability list. A
        `walletExternal` can be registered on `tron` (networkFamily `tron`)
        where the project's provider serves it. Availability is per provider
        rather than per project, so a network your project holds through one
        provider can still be refused for a customer on another. `GET /networks`
        lists the networks your project can route, as the union across every
        provider it holds.
    decimalString:
      type: string
      description: >-
        Wire-safe decimal string for financial float values (USD amounts,
        percentages).
      x-go-type-import:
        path: github.com/shopspring/decimal
      x-go-type: decimal.Decimal
    InstantRail:
      type: string
      enum:
        - rtp
        - fednow
      description: >-
        The rail an `instant` payment rides: `rtp` (RTP over The Clearing House)
        or `fednow`.
    IntraBankRail:
      type: string
      enum:
        - bookTransfer
        - crnow
        - ereborRail
      description: >-
        The rail an `intraBank` payment rides between two accounts at the same
        bank: `bookTransfer`, `crnow` or `ereborRail`.
    BankAccountType:
      type: string
      enum:
        - checking
        - savings
      description: Bank account sub-type for US accounts.
    Address:
      type: object
      properties:
        line1:
          type: string
          description: Street address, line 1.
        line2:
          type: string
          description: Street address, line 2.
        city:
          type: string
          description: City.
        state:
          type: string
          description: State / province / region.
        country:
          type: string
          description: ISO 3166-1 alpha-2
        zipCode:
          type: string
          description: ZIP / postal code.
      description: A postal address. country is an ISO 3166-1 alpha-2 country code.
    CardBrand:
      type: string
      enum:
        - visa
        - mastercard
        - amex
        - discover
      description: >-
        Card network/brand. Derived server-side from the PAN; never accepted on
        a request.
    CardType:
      type: string
      enum:
        - debit
        - credit
        - prepaid
      description: >-
        Card funding type, derived server-side from the PAN. Only `debit` is
        supported today; `credit` and `prepaid` are reserved for future
        push-to-card / pull-from-card support.
    BillingAddressSource:
      type: string
      enum:
        - provided
        - customerDefault
      description: >-
        Where a card's billing address came from. `provided` = supplied on the
        request; `customerDefault` = filled from the owning customer's address
        because the request omitted it.
    NetworkFamily:
      type: string
      enum:
        - evm
        - solana
        - tron
      description: >-
        Crypto network family for a registered external wallet. A walletExternal
        is registered per family (an EVM address is valid across every EVM
        chain), and the registration covers every served network in that family.
        A create for a family the provider that provisions this project's
        walletExternal accounts does not serve is refused before anything is
        written, with 422 `NetworkFamilyNotServed`; depending on the provider,
        the refusal can be 403 `VendorConfigMissing` instead.
    ReasonCode:
      type: string
      enum:
        - providerError
        - providerRejected
        - providerTimeout
        - expired
        - systemError
        - provisioningTimeout
        - insufficientFunds
        - providerAmountBelowMinimum
        - limitExceeded
        - outsideSellBounds
        - outsideSellVelocityBounds
        - unusableAmount
        - unsupportedCorridor
        - outgoingRailNotEnabled
        - ssnNotVerified
        - riskRejected
        - cardDeclined
        - bankSellDeclined
        - payoutFailed
        - priceMoved
        - returningToSender
        - returnedToSender
        - returnFailed
        - depositFailed
        - attributionTimeout
        - assetMismatch
        - chainMismatch
        - misattributedArrival
        - depositAddressNotActive
        - virtualAccountNotActive
        - counterpartyArchived
        - destinationUnavailable
        - walletClaimed
        - walletBoundToCustodialFlow
        - projectSuspended
        - memoInvalid
        - cashDepositFailed
        - noMatchingNetwork
        - blockchainAddressInUse
        - bankAccountInUse
        - bankAccountRejected
        - deletePendingTimeout
        - providerAccountMissing
        - cardInUse
        - cardLimitReached
        - countryProhibited
        - countryNotSupported
        - cardVerificationDeclined
        - bankVerificationDeclined
        - accountClosed
        - accountFrozenByBank
        - routingOrAccountNumberInvalid
        - accountHolderDeceased
        - accountDoesNotSupportTransfers
        - payeeNameMismatch
        - walletUnreachableOnNetwork
        - billingAddressMismatch
        - cardExpired
        - cardClosedOrLostStolen
        - pushToCardUnsupported
        - cardDeclinedByIssuer
      description: The reasons a resource reports in `failure`.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Token from POST /auth/token

````