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

# Add a card to a digital wallet

> Exchange the values your app received from Apple Pay, Google Pay, or Samsung Pay for the encrypted provisioning payload that completes adding the card to that wallet (in-app push provisioning). Call it from your backend inside the wallet SDK's credentials callback and hand the response straight back to the SDK.

The payload is encrypted to the wallet provider's keys, so neither your app nor your servers ever see card data. Do not store or log it; it is valid for one provisioning attempt.

Cardholders can always add a card to a wallet by typing its details in manually — that path needs nothing from you. This endpoint is for the in-app "Add to Wallet" button, which additionally requires approval from each wallet provider. See [Digital wallet tokenization](/cards/card-management/digital-wallet-tokenization).

Only `ACTIVE` cards can be added. Every call is audit-logged with the requesting actor and the target wallet.



## OpenAPI

````yaml https://app.stainless.com/api/spec/documented/grid/openapi.documented.yml post /cards/{id}/tokenize
openapi: 3.1.0
info:
  title: Grid API
  description: >
    API for managing global payments on the open Money Grid. Built by
    Lightspark. See the full documentation at https://docs.lightspark.com/.
  version: '2025-10-13'
  contact:
    name: Lightspark Support
    email: support@lightspark.com
  license:
    name: Proprietary
    url: https://lightspark.com/terms
servers:
  - url: https://api.lightspark.com/grid/2025-10-13
    description: Production server
security:
  - BasicAuth: []
  - AgentAuth: []
tags:
  - name: Platform Configuration
    description: >-
      Platform configuration endpoints for managing global settings. You can
      also configure these settings in the Grid dashboard.
  - name: Customers
    description: >-
      Customer management endpoints for creating and updating customer
      information
  - name: Contact Verification
    description: >-
      Endpoints for verifying a customer's email and phone via one-time codes.
      Required only for customers whose payment provider mandates contact
      verification (e.g. EU customers); other providers return 409.
  - name: Strong Customer Authentication
    description: >-
      Endpoints for authorizing money-movement operations that require Strong
      Customer Authentication. Relevant only for customers in a region where SCA
      is required (e.g. EU); customers outside SCA-regulated regions never see
      an SCA challenge and these endpoints return 409.
  - name: KYC/KYB Verifications
    description: >-
      Endpoints for Know Your Customer (KYC) and Know Your Business (KYB)
      verification, including managing beneficial owners and triggering
      verification for customers.
  - name: Documents
    description: >-
      Endpoints for uploading and managing verification documents for customers
      and beneficial owners. Supports KYC and KYB document requirements.
  - name: Internal Accounts
    description: >-
      Internal account management endpoints for creating and managing internal
      accounts
  - name: External Accounts
    description: >-
      External account management endpoints for creating and managing external
      bank accounts
  - name: Same-Currency Transfers
    description: >-
      Deprecated endpoints for transferring funds between internal and external
      accounts with the same currency. Use the quote endpoints under
      Cross-Currency Transfers instead, which now serve same-currency transfers
      as well.
  - name: Cross-Currency Transfers
    description: >-
      Endpoints for creating and confirming quotes for transfers, both
      same-currency and cross-currency
  - name: Transactions
    description: Endpoints for retrieving transaction information
  - name: Webhooks
    description: Webhook endpoints and configuration for receiving notifications
  - name: Invitations
    description: Endpoints for creating, claiming and managing UMA invitations
  - name: Sandbox
    description: Endpoints to trigger test cases in sandbox
  - name: API Tokens
    description: Endpoints to programmatically manage API tokens
  - name: Exchange Rates
    description: >-
      Endpoints for retrieving cached foreign exchange rates. Rates are cached
      for approximately 5 minutes and include platform-specific fees.
  - name: Discoveries
    description: >-
      Endpoints for discovering available payment rails, banks, and providers
      for a given country and currency corridor.
  - name: Embedded Wallet Auth
    description: >-
      Endpoints for registering and verifying end-user authentication
      credentials (email OTP, OAuth, passkey) used to sign Embedded Wallet
      actions.
  - name: Agent Management
    description: >-
      Endpoints for creating and managing agents (experimental), called by the
      partner's backend using platform credentials. Covers the full agent
      lifecycle: creation, policy configuration, pausing, deletion, the device
      code installation flow, and approving or rejecting transactions initiated
      by agents.
  - name: Agent Operations
    description: >-
      Endpoints called by the agent itself using its own credentials (obtained
      via device code redemption). Scoped to the agent's associated customer —
      all requests automatically operate on behalf of that customer and are
      subject to the agent's policy. When an action requires approval, the
      resulting transaction enters a pending state and must be approved by the
      platform via `POST /transactions/{transactionId}/approve`.
  - name: Cards
    description: >-
      Card management endpoints. Issue debit cards against an internal account,
      freeze / unfreeze, close, manage a card's funding source, and list card
      transactions.
  - name: Stablecoins
    description: >-
      Stablecoin issuance endpoints. Link provider accounts, register
      provider-created stablecoins, create direct mint/burn issuer operations,
      and track operation status.
paths:
  /cards/{id}/tokenize:
    parameters:
      - name: id
        in: path
        description: System-generated unique card identifier
        required: true
        schema:
          type: string
    post:
      tags:
        - Cards
      summary: Add a card to a digital wallet
      description: >-
        Exchange the values your app received from Apple Pay, Google Pay, or
        Samsung Pay for the encrypted provisioning payload that completes adding
        the card to that wallet (in-app push provisioning). Call it from your
        backend inside the wallet SDK's credentials callback and hand the
        response straight back to the SDK.


        The payload is encrypted to the wallet provider's keys, so neither your
        app nor your servers ever see card data. Do not store or log it; it is
        valid for one provisioning attempt.


        Cardholders can always add a card to a wallet by typing its details in
        manually — that path needs nothing from you. This endpoint is for the
        in-app "Add to Wallet" button, which additionally requires approval from
        each wallet provider. See [Digital wallet
        tokenization](/cards/card-management/digital-wallet-tokenization).


        Only `ACTIVE` cards can be added. Every call is audit-logged with the
        requesting actor and the target wallet.
      operationId: tokenizeCard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardTokenizationRequestOneOf'
            examples:
              applePay:
                summary: Apple Pay
                value:
                  wallet: APPLE_PAY
                  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM=
                  nonce: MTIzNDU2Nzg=
                  nonceSignature: c2lnbmF0dXJl
              googlePay:
                summary: Google Pay (Unified Push Provisioning)
                value:
                  wallet: GOOGLE_PAY
                  walletAccountId: wallet-account-8f14e45f
                  serverSessionId: 8c3b8a7e-2a5d-4b7f-9c1e-6d2f0a1b3c4d
                  opaquePaymentCardRequested: false
              samsungPay:
                summary: Samsung Pay
                value:
                  wallet: SAMSUNG_PAY
                  walletAccountId: wallet-account-8f14e45f
                  deviceId: device-3c59dc04
      responses:
        '200':
          description: Provisioning payload minted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardTokenizationResponseOneOf'
              examples:
                applePay:
                  summary: Apple Pay
                  value:
                    wallet: APPLE_PAY
                    applePay:
                      activationData: YWN0aXZhdGlvbi1kYXRh
                      encryptedPassData: ZW5jcnlwdGVkLXBhc3MtZGF0YQ==
                      ephemeralPublicKey: ZXBoZW1lcmFsLXB1YmxpYy1rZXk=
                googlePay:
                  summary: Google Pay
                  value:
                    wallet: GOOGLE_PAY
                    provisioningPayload: eyJjYXJkIjoiLi4uIn0=
        '400':
          description: >-
            Invalid input. The body does not match the request shape for its
            `wallet` (a required field is missing, or a field from another
            wallet's shape was supplied), or the wallet provider rejected the
            values (for example, an expired Apple nonce). Restart the
            add-to-wallet flow in the app to obtain fresh values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401'
        '403':
          description: >-
            Forbidden. The session has no attributable actor to audit the
            request against (for example, an impersonated dashboard session).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error403'
        '404':
          description: Card not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error404'
        '409':
          description: >-
            Conflict. `CARD_NOT_MUTABLE` when the card is `CLOSED`; `CONFLICT`
            when the card's `cardCapabilities.supportsDigitalWalletTokenization`
            is false or the card is not `ACTIVE`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error409'
        '500':
          description: Internal service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error500'
        '501':
          description: >-
            Not implemented in this environment. Cards are not enabled for every
            Grid deployment; environments without a configured card issuer
            return `501 NOT_IMPLEMENTED`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error501'
      security:
        - BasicAuth: []
components:
  schemas:
    CardTokenizationRequestOneOf:
      oneOf:
        - $ref: '#/components/schemas/ApplePayTokenizationRequest'
        - $ref: '#/components/schemas/GooglePayTokenizationRequest'
        - $ref: '#/components/schemas/SamsungPayTokenizationRequest'
      discriminator:
        propertyName: wallet
        mapping:
          APPLE_PAY:
            $ref: '#/components/schemas/ApplePayTokenizationRequest'
          GOOGLE_PAY:
            $ref: '#/components/schemas/GooglePayTokenizationRequest'
          SAMSUNG_PAY:
            $ref: '#/components/schemas/SamsungPayTokenizationRequest'
    CardTokenizationResponseOneOf:
      oneOf:
        - $ref: '#/components/schemas/ApplePayTokenizationResponse'
        - $ref: '#/components/schemas/GooglePayTokenizationResponse'
        - $ref: '#/components/schemas/SamsungPayTokenizationResponse'
      discriminator:
        propertyName: wallet
        mapping:
          APPLE_PAY:
            $ref: '#/components/schemas/ApplePayTokenizationResponse'
          GOOGLE_PAY:
            $ref: '#/components/schemas/GooglePayTokenizationResponse'
          SAMSUNG_PAY:
            $ref: '#/components/schemas/SamsungPayTokenizationResponse'
    Error400:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | INVALID_INPUT | Invalid input provided |

            | END_USER_TERMS_VERSION_NOT_FOUND | The submitted End User Terms
            version is not supported |

            | MISSING_MANDATORY_USER_INFO | Required customer information is
            missing |

            | INVITATION_ALREADY_CLAIMED | Invitation has already been claimed |

            | INVITATIONS_NOT_CONFIGURED | Invitations are not configured |

            | INVALID_UMA_ADDRESS | UMA address format is invalid |

            | INVITATION_CANCELLED | Invitation has been cancelled |

            | QUOTE_REQUEST_FAILED | An issue occurred during the quote process;
            this is retryable |

            | INVALID_PAYREQ_RESPONSE | Counterparty Payreq response was invalid
            |

            | INVALID_RECEIVER | Receiver is invalid |

            | PARSE_PAYREQ_RESPONSE_ERROR | Error parsing receiver PayReq
            response |

            | CERT_CHAIN_INVALID | Counterparty certificate chain is invalid |

            | CERT_CHAIN_EXPIRED | Counterparty certificate chain has expired |

            | INVALID_PUBKEY_FORMAT | Counterparty Public key format is invalid
            |

            | MISSING_REQUIRED_UMA_PARAMETERS | Counterparty required UMA
            parameters are missing |

            | SENDER_NOT_ACCEPTED | Sender is not accepted |

            | AMOUNT_OUT_OF_RANGE | Amount is out of range |

            | INVALID_CURRENCY | Currency is invalid |

            | INVALID_TIMESTAMP | Timestamp is invalid |

            | INVALID_NONCE | Nonce is invalid |

            | INVALID_REQUEST_FORMAT | Request format is invalid |

            | INVALID_BANK_ACCOUNT | Bank account is invalid |

            | SELF_PAYMENT | Self payment not allowed |

            | LOOKUP_REQUEST_FAILED | Lookup request failed |

            | PARSE_LNURLP_RESPONSE_ERROR | Error parsing LNURLP response |

            | INVALID_AMOUNT | Amount is invalid |

            | WEBHOOK_ENDPOINT_NOT_SET | Webhook endpoint is not set |

            | WEBHOOK_DELIVERY_ERROR | Webhook delivery error |

            | LOW_QUALITY | Document quality too low to process |

            | DATA_MISMATCH | Document details don't match provided information
            |

            | EXPIRED | Document has expired |

            | SUSPECTED_FRAUD | Document suspected of being forged or edited |

            | UNSUITABLE_DOCUMENT | Document type is not accepted or not
            supported |

            | INCOMPLETE | Document is missing pages or sides |

            | EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is
            already registered on the target internal account; only one email
            OTP credential is supported per internal account at this time |

            | SMS_OTP_CREDENTIAL_ALREADY_EXISTS | An SMS_OTP credential is
            already registered on the target internal account; only one SMS OTP
            credential is supported per internal account at this time |

            | PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential with the
            same WebAuthn credentialId is already registered on the target
            internal account |

            | STABLECOIN_PROVIDER_ACCOUNT_INVALID | The stablecoin provider
            account link is not usable |

            | STABLECOIN_PROVIDER_ACCOUNT_REVOKED | The stablecoin provider
            account link has been revoked |

            | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active
            provider account links exist; pass `stablecoinProviderAccountId` to
            select one |

            | CARDHOLDER_KYC_NOT_APPROVED | The cardholder's KYC status is not
            `APPROVED`, so a card cannot be issued |

            | TRANSACTION_SIZE_LIMIT_EXCEEDED | The requested amount exceeds the
            configured maximum single-transaction amount for this trade corridor
            or withdrawal currency |

            | EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED | The destination account's
            ownership must be verified before this transfer can proceed |

            | INSUFFICIENT_FUNDS | Insufficient funds for this operation |

            | QUOTE_EXPIRED | The quote has expired; request a new quote |

            | QUOTE_RATE_UNAVAILABLE | No exchange rate is available for this
            corridor right now |

            | STABLECOIN_AMOUNT_NOT_REPRESENTABLE | The amount cannot be
            represented at the token's precision |

            | STABLECOIN_BURN_SOURCE_NOT_SUPPORTED | The burn source account
            cannot be used for this operation |

            | STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED | Linking the external
            account for stablecoin operations failed |

            | STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED | The external
            account needs a link method before it can be used |

            | STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED | The external account is
            not linked for stablecoin operations |

            | STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED | This external account
            type is not supported for stablecoin operations |

            | STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_FAILED | The provider
            could not link the external account |

            | STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_REQUIRED | The external
            account must be linked with the provider first |

            | STABLECOIN_GRID_OPERATIONS_NOT_ENABLED | The stablecoin is not
            enabled for Grid operations |

            | STABLECOIN_NOT_PROVISIONED | The stablecoin is not provisioned for
            issuer operations |

            | STABLECOIN_OPERATION_NOT_SUPPORTED | The stablecoin does not
            support this operation |

            | STABLECOIN_PROVIDER_ERROR | The stablecoin provider rejected the
            operation |

            | STABLECOIN_PROVIDER_SOURCE_NOT_LINKED | The provider source
            account is not linked |

            | STABLECOIN_VERIFICATION_FAILED | The stablecoin could not be
            verified with the provider |
          enum:
            - INVALID_INPUT
            - END_USER_TERMS_VERSION_NOT_FOUND
            - MISSING_MANDATORY_USER_INFO
            - INVITATION_ALREADY_CLAIMED
            - INVITATIONS_NOT_CONFIGURED
            - INVALID_UMA_ADDRESS
            - INVITATION_CANCELLED
            - QUOTE_REQUEST_FAILED
            - INVALID_PAYREQ_RESPONSE
            - INVALID_RECEIVER
            - PARSE_PAYREQ_RESPONSE_ERROR
            - CERT_CHAIN_INVALID
            - CERT_CHAIN_EXPIRED
            - INVALID_PUBKEY_FORMAT
            - MISSING_REQUIRED_UMA_PARAMETERS
            - SENDER_NOT_ACCEPTED
            - AMOUNT_OUT_OF_RANGE
            - INVALID_CURRENCY
            - INVALID_TIMESTAMP
            - INVALID_NONCE
            - INVALID_REQUEST_FORMAT
            - INVALID_BANK_ACCOUNT
            - SELF_PAYMENT
            - LOOKUP_REQUEST_FAILED
            - PARSE_LNURLP_RESPONSE_ERROR
            - INVALID_AMOUNT
            - WEBHOOK_ENDPOINT_NOT_SET
            - WEBHOOK_DELIVERY_ERROR
            - LOW_QUALITY
            - DATA_MISMATCH
            - EXPIRED
            - SUSPECTED_FRAUD
            - UNSUITABLE_DOCUMENT
            - INCOMPLETE
            - EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS
            - SMS_OTP_CREDENTIAL_ALREADY_EXISTS
            - PASSKEY_CREDENTIAL_ALREADY_EXISTS
            - STABLECOIN_PROVIDER_ACCOUNT_INVALID
            - STABLECOIN_PROVIDER_ACCOUNT_REVOKED
            - STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED
            - CARDHOLDER_KYC_NOT_APPROVED
            - TRANSACTION_SIZE_LIMIT_EXCEEDED
            - EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED
            - INSUFFICIENT_FUNDS
            - QUOTE_EXPIRED
            - QUOTE_RATE_UNAVAILABLE
            - STABLECOIN_AMOUNT_NOT_REPRESENTABLE
            - STABLECOIN_BURN_SOURCE_NOT_SUPPORTED
            - STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED
            - STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED
            - STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED
            - STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED
            - STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_FAILED
            - STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_REQUIRED
            - STABLECOIN_GRID_OPERATIONS_NOT_ENABLED
            - STABLECOIN_NOT_PROVISIONED
            - STABLECOIN_OPERATION_NOT_SUPPORTED
            - STABLECOIN_PROVIDER_ERROR
            - STABLECOIN_PROVIDER_SOURCE_NOT_LINKED
            - STABLECOIN_VERIFICATION_FAILED
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: >-
            Additional error details. Shape varies by `code`. For
            field-validation errors on submit endpoints (e.g. `POST /customers`,
            `PATCH /customers/{id}`), `details.errors[]` enumerates every
            invalid field so platforms can render form-field-level UX for the
            entire request in a single round-trip.
          properties:
            errors:
              type: array
              description: >-
                One entry per invalid field. Present on field-validation errors
                from submit endpoints.
              items:
                $ref: '#/components/schemas/FieldError'
          additionalProperties: true
    Error401:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | UNAUTHORIZED | Issue with API credentials |

            | INVALID_SIGNATURE | Signature header is invalid |

            | WALLET_SIGNATURE_MISSING | The `Grid-Wallet-Signature` header is
            required for this Embedded Wallet action but was not supplied |

            | WALLET_SIGNATURE_MALFORMED | The `Grid-Wallet-Signature` header
            could not be parsed (bad encoding, structure, or fields) |

            | WALLET_SIGNATURE_BODY_MISMATCH | The `Grid-Wallet-Signature` was
            computed over a different request body than the one received |

            | WALLET_SIGNATURE_INVALID | The `Grid-Wallet-Signature` failed
            cryptographic verification against the registered credential |

            | REQUEST_ID_MISSING | The `Request-Id` header is required on the
            signed retry but was not supplied (paired with
            `Grid-Wallet-Signature`) |
          enum:
            - UNAUTHORIZED
            - INVALID_SIGNATURE
            - WALLET_SIGNATURE_MISSING
            - WALLET_SIGNATURE_MALFORMED
            - WALLET_SIGNATURE_BODY_MISMATCH
            - WALLET_SIGNATURE_INVALID
            - REQUEST_ID_MISSING
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error403:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | FORBIDDEN | Insufficient permissions |

            | USER_NOT_READY | Customer exists but is not ready for operation |

            | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for
            your account |

            | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity
            limits |

            | END_USER_TERMS_NOT_ACCEPTED | Customer has not accepted the End
            User Terms |

            | CUSTOMER_NOT_VERIFIED | The customer is not verified and cannot
            perform this action |

            | SANCTION_BLOCKED | Blocked by sanction screening |
          enum:
            - FORBIDDEN
            - USER_NOT_READY
            - COUNTERPARTY_NOT_ALLOWED
            - VELOCITY_LIMIT_EXCEEDED
            - END_USER_TERMS_NOT_ACCEPTED
            - CUSTOMER_NOT_VERIFIED
            - SANCTION_BLOCKED
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error404:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | TRANSACTION_NOT_FOUND | Transaction not found |

            | INVITATION_NOT_FOUND | Invitation not found |

            | USER_NOT_FOUND | Customer not found |

            | QUOTE_NOT_FOUND | Quote not found |

            | LOOKUP_REQUEST_NOT_FOUND | Lookup request not found |

            | TOKEN_NOT_FOUND | Token not found |

            | BULK_UPLOAD_JOB_NOT_FOUND | Bulk upload job not found |

            | REFERENCE_NOT_FOUND | Reference not found |

            | UMA_NOT_FOUND | The UMA address is well-formed but no receiver
            exists at the counterparty VASP |

            | STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND | Stablecoin provider
            account link not found |

            | ACCOUNT_NOT_FOUND | Account not found |

            | AUTH_METHOD_NOT_FOUND | Authentication credential not found |

            | CUSTOMER_NOT_FOUND | Customer not found |

            | DOCUMENT_HOLDER_NOT_FOUND | Document holder not found |

            | NOT_FOUND | The requested resource was not found |

            | PAYMENT_URL_NOT_FOUND | Payment URL not found |

            | PLATFORM_NOT_FOUND | Platform not found |

            | REQUEST_NOT_FOUND | Pending request not found |

            | SESSION_NOT_FOUND | Session not found |

            | STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND | Stablecoin external
            account not found |

            | STABLECOIN_NOT_FOUND | Stablecoin not found |

            | STABLECOIN_OPERATION_NOT_FOUND | Stablecoin operation not found |

            | VERIFICATION_NOT_FOUND | Verification not found |
          enum:
            - TRANSACTION_NOT_FOUND
            - INVITATION_NOT_FOUND
            - USER_NOT_FOUND
            - QUOTE_NOT_FOUND
            - LOOKUP_REQUEST_NOT_FOUND
            - TOKEN_NOT_FOUND
            - BULK_UPLOAD_JOB_NOT_FOUND
            - REFERENCE_NOT_FOUND
            - UMA_NOT_FOUND
            - STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND
            - ACCOUNT_NOT_FOUND
            - AUTH_METHOD_NOT_FOUND
            - CUSTOMER_NOT_FOUND
            - DOCUMENT_HOLDER_NOT_FOUND
            - NOT_FOUND
            - PAYMENT_URL_NOT_FOUND
            - PLATFORM_NOT_FOUND
            - REQUEST_NOT_FOUND
            - SESSION_NOT_FOUND
            - STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND
            - STABLECOIN_NOT_FOUND
            - STABLECOIN_OPERATION_NOT_FOUND
            - VERIFICATION_NOT_FOUND
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error409:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | TRANSACTION_NOT_PENDING_PLATFORM_APPROVAL | Transaction is not
            pending platform approval |

            | TRANSACTION_NOT_CANCELLABLE | Transaction has already settled or
            is otherwise past the point where it can be cancelled |

            | UMA_ADDRESS_EXISTS | UMA address already exists |

            | EMAIL_OTP_EMAIL_ALREADY_EXISTS | Email address is already
            associated with an EMAIL_OTP credential |

            | EMAIL_OTP_CREDENTIAL_SET_CHANGED | Tied EMAIL_OTP credential set
            changed after the signed-retry challenge was issued |

            | PASSKEY_ALREADY_ENROLLED | The customer already has an enrolled
            passkey factor; only one passkey per customer is supported. Delete
            the existing one before enrolling another |

            | SCA_SESSION_REQUIRED | The customer's Strong Customer
            Authentication login session is missing or expired. Re-authenticate
            the customer, then retry the request. Distinct from a `401`, which
            means the platform's own API credentials were rejected |

            | BENEFICIARY_TRUSTED | The external account is currently a trusted
            beneficiary, so it cannot be deleted. Untrust it first via `POST
            /customers/external-accounts/{externalAccountId}/untrust` (and its
            `/confirm`), then delete |

            | BANK_ACCOUNT_VALIDATION_PENDING | The US bank account on this
            request is still being validated. Grid verifies a newly added ACH
            account by sending a micro-entry and waiting out the return window,
            which takes a few banking days. The account is not rejected; retry
            once validation completes. A permanently failed account returns `400
            INVALID_BANK_ACCOUNT` instead |

            | INVALID_STATE_TRANSITION | The requested card `status` transition
            is not one of `ACTIVE ⇄ FROZEN` or `ACTIVE \| FROZEN → CLOSED` |

            | CARD_ALREADY_CLOSED | `status: CLOSED` was requested for a card
            that is already `CLOSED` |

            | CARD_NOT_MUTABLE | The card is `CLOSED`, so it can no longer be
            mutated |

            | CARD_LIMIT_REACHED | The platform has reached the maximum number
            of live cards it may hold, or the cardholder already holds a card
            and the platform is limited to one per cardholder. Closing a card
            frees its slot; contact Lightspark to raise the limit |

            | STABLECOIN_GRID_ENABLEMENT_NOT_REQUESTABLE | Grid enablement can
            only be requested while the stablecoin is `NOT_ENABLED` (a repeat
            request while already `PENDING_APPROVAL` succeeds). `ENABLING`,
            `ENABLED` and `DISABLED` are driven by Lightspark and cannot be
            requested |

            | CONFLICT | Generic resource-state conflict. Returned, for example,
            when `platformCustomerId` on a customer create call collides with an
            existing active customer on the same platform |

            | DOCUMENT_ALREADY_EXISTS | A document of this type already exists
            for the holder; replace it with PUT |

            | DUPLICATE_EXTERNAL_ACCOUNT | An equivalent external account
            already exists |

            | DUPLICATE_PAY_REQUEST | A pay request with this idempotency key
            already exists |

            | SMS_OTP_CREDENTIAL_SET_CHANGED | The SMS_OTP credential set
            changed while the request was in flight |

            | SMS_OTP_PHONE_NUMBER_ALREADY_EXISTS | The phone number is already
            associated with an SMS_OTP credential |

            | STABLECOIN_SYMBOL_ALREADY_EXISTS | A stablecoin with this symbol
            is already registered |

            | STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS | A stablecoin with
            this token identifier is already registered |

            | WALLET_NOT_PROVISIONED | The embedded wallet has not been
            provisioned |
          enum:
            - TRANSACTION_NOT_PENDING_PLATFORM_APPROVAL
            - TRANSACTION_NOT_CANCELLABLE
            - UMA_ADDRESS_EXISTS
            - EMAIL_OTP_EMAIL_ALREADY_EXISTS
            - EMAIL_OTP_CREDENTIAL_SET_CHANGED
            - PASSKEY_ALREADY_ENROLLED
            - SCA_SESSION_REQUIRED
            - BENEFICIARY_TRUSTED
            - BANK_ACCOUNT_VALIDATION_PENDING
            - INVALID_STATE_TRANSITION
            - CARD_ALREADY_CLOSED
            - CARD_NOT_MUTABLE
            - CARD_LIMIT_REACHED
            - STABLECOIN_GRID_ENABLEMENT_NOT_REQUESTABLE
            - CONFLICT
            - DOCUMENT_ALREADY_EXISTS
            - DUPLICATE_EXTERNAL_ACCOUNT
            - DUPLICATE_PAY_REQUEST
            - SMS_OTP_CREDENTIAL_SET_CHANGED
            - SMS_OTP_PHONE_NUMBER_ALREADY_EXISTS
            - STABLECOIN_SYMBOL_ALREADY_EXISTS
            - STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS
            - WALLET_NOT_PROVISIONED
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error500:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: |
            | Error Code | Description |
            |------------|-------------|
            | GRID_SWITCH_ERROR | Grid switch error |
            | INTERNAL_ERROR | Internal server or UMA error |
          enum:
            - GRID_SWITCH_ERROR
            - INTERNAL_ERROR
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error501:
      type: object
      required:
        - reason
        - code
      properties:
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | UNRECOGNIZED_MANDATORY_PAYEE_DATA_KEY | Unrecognized mandatory
            payee data key |

            | NOT_IMPLEMENTED | Feature not implemented |

            | UNRECOGNIZED_MANDATORY_COUNTERPARTY_DATA_KEY | The counterparty
            requires a data key Grid does not recognise |
          enum:
            - UNRECOGNIZED_MANDATORY_PAYEE_DATA_KEY
            - NOT_IMPLEMENTED
            - UNRECOGNIZED_MANDATORY_COUNTERPARTY_DATA_KEY
        reason:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    ApplePayTokenizationRequest:
      title: Apple Pay Tokenization Request
      allOf:
        - $ref: '#/components/schemas/CardTokenizationRequest'
        - $ref: '#/components/schemas/ApplePayTokenizationRequestFields'
    GooglePayTokenizationRequest:
      title: Google Pay Tokenization Request
      allOf:
        - $ref: '#/components/schemas/CardTokenizationRequest'
        - $ref: '#/components/schemas/GooglePayTokenizationRequestFields'
    SamsungPayTokenizationRequest:
      title: Samsung Pay Tokenization Request
      allOf:
        - $ref: '#/components/schemas/CardTokenizationRequest'
        - $ref: '#/components/schemas/SamsungPayTokenizationRequestFields'
    ApplePayTokenizationResponse:
      title: Apple Pay Tokenization Response
      allOf:
        - $ref: '#/components/schemas/CardTokenizationResponse'
        - $ref: '#/components/schemas/ApplePayTokenizationResponseFields'
    GooglePayTokenizationResponse:
      title: Google Pay Tokenization Response
      allOf:
        - $ref: '#/components/schemas/CardTokenizationResponse'
        - $ref: '#/components/schemas/GooglePayTokenizationResponseFields'
    SamsungPayTokenizationResponse:
      title: Samsung Pay Tokenization Response
      allOf:
        - $ref: '#/components/schemas/CardTokenizationResponse'
        - $ref: '#/components/schemas/SamsungPayTokenizationResponseFields'
    FieldError:
      type: object
      required:
        - field
      description: >-
        One field-level validation failure. Field-validation errors on submit
        endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`) emit an
        array of these under `details.errors` so platforms can render
        form-field-level UX for every failure in a single round-trip.
      properties:
        field:
          type: string
          description: Dot-notation path to the offending field.
          example: identifier
        constraint:
          $ref: '#/components/schemas/FieldConstraint'
        message:
          type: string
          description: Human-readable explanation of what's wrong with this field.
          example: Value is not one of the allowed enum members.
    CardTokenizationRequest:
      type: object
      description: >-
        Fields shared by every add-to-wallet request. The wallet SDK hands your
        app a set of values when the cardholder taps "Add to Wallet"; pass them
        here unchanged in the request shape for that `wallet`.
      required:
        - wallet
      properties:
        wallet:
          $ref: '#/components/schemas/DigitalWallet'
    ApplePayTokenizationRequestFields:
      type: object
      required:
        - wallet
        - certificate
        - nonce
        - nonceSignature
      properties:
        wallet:
          type: string
          enum:
            - APPLE_PAY
          description: Discriminator value identifying an Apple Pay request.
          example: APPLE_PAY
        certificate:
          type: string
          description: >-
            The leaf certificate from the `certificates` array Apple passes to
            your `PKAddPaymentPassViewControllerDelegate`, base64-encoded in PEM
            form.
          example: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM=
        nonce:
          type: string
          description: The `nonce` Apple passes to your delegate, base64-encoded.
          example: MTIzNDU2Nzg=
        nonceSignature:
          type: string
          description: The `nonceSignature` Apple passes to your delegate, base64-encoded.
          example: c2lnbmF0dXJl
    GooglePayTokenizationRequestFields:
      type: object
      required:
        - wallet
        - walletAccountId
        - serverSessionId
      properties:
        wallet:
          type: string
          enum:
            - GOOGLE_PAY
          description: Discriminator value identifying a Google Pay request.
          example: GOOGLE_PAY
        walletAccountId:
          type: string
          description: >-
            The stable identifier of the Google Wallet account the card is being
            added to, as reported by the TapAndPay client.
          example: wallet-account-8f14e45f
        serverSessionId:
          type: string
          format: uuid
          description: >-
            The `serverSessionId` Google supplies in the TapAndPay
            payment-credentials callback under Unified Push Provisioning.
          example: 8c3b8a7e-2a5d-4b7f-9c1e-6d2f0a1b3c4d
        deviceId:
          type: string
          description: >-
            The stable device identifier from `getStableHardwareId`, when the
            SDK supplies one. Unified Push Provisioning does not always.
          example: device-3c59dc04
        opaquePaymentCardRequested:
          type: boolean
          default: false
          description: >-
            Set to the value Google supplies in the payment-credentials
            callback. When `true`, the response also carries
            `googleAccountPayload`, which saves the card to the cardholder's
            Google Account for online payments in addition to the device token.
          example: false
    SamsungPayTokenizationRequestFields:
      type: object
      required:
        - wallet
        - walletAccountId
        - deviceId
      properties:
        wallet:
          type: string
          enum:
            - SAMSUNG_PAY
          description: Discriminator value identifying a Samsung Pay request.
          example: SAMSUNG_PAY
        walletAccountId:
          type: string
          description: >-
            The cardholder's Samsung Wallet identifier (`walletUserId`) reported
            by the Samsung Pay SDK.
          example: wallet-account-8f14e45f
        deviceId:
          type: string
          description: The stable device identifier reported by the Samsung Pay SDK.
          example: device-3c59dc04
    CardTokenizationResponse:
      type: object
      description: >-
        Fields shared by every add-to-wallet response. The payload is encrypted
        to the wallet provider's keys: neither your app nor your servers can
        read the card data inside it. Hand it to the wallet SDK; it is valid for
        a single provisioning attempt.
      required:
        - wallet
      properties:
        wallet:
          $ref: '#/components/schemas/DigitalWallet'
    ApplePayTokenizationResponseFields:
      type: object
      required:
        - wallet
        - applePay
      properties:
        wallet:
          type: string
          enum:
            - APPLE_PAY
          description: Discriminator value identifying an Apple Pay response.
          example: APPLE_PAY
        applePay:
          $ref: '#/components/schemas/CardTokenizationApplePayPayload'
    GooglePayTokenizationResponseFields:
      type: object
      required:
        - wallet
        - provisioningPayload
      properties:
        wallet:
          type: string
          enum:
            - GOOGLE_PAY
          description: Discriminator value identifying a Google Pay response.
          example: GOOGLE_PAY
        provisioningPayload:
          type: string
          description: >-
            Base64-encoded opaque payload for the device token. Return it from
            the TapAndPay payment-credentials callback.
          example: eyJjYXJkIjoiLi4uIn0=
        googleAccountPayload:
          type: string
          description: >-
            Present when `opaquePaymentCardRequested` was `true`. Return it
            alongside `provisioningPayload` so Google also saves the card to the
            cardholder's Google Account.
          example: eyJmcGFuIjoiLi4uIn0=
    SamsungPayTokenizationResponseFields:
      type: object
      required:
        - wallet
        - provisioningPayload
      properties:
        wallet:
          type: string
          enum:
            - SAMSUNG_PAY
          description: Discriminator value identifying a Samsung Pay response.
          example: SAMSUNG_PAY
        provisioningPayload:
          type: string
          description: >-
            Base64-encoded opaque payload. Pass it to the Samsung Pay SDK's
            `addCard` call.
          example: eyJjYXJkIjoiLi4uIn0=
    FieldConstraint:
      type: object
      description: >-
        Machine-readable validator hint accompanying a 400 `INVALID_INPUT`
        error. Consumers use it to drive form UI (input types, dropdowns,
        masking, length limits) and to pre-validate the field client-side before
        re-submitting. Fields are additive.
      properties:
        format:
          type: string
          description: >-
            Named format the value must satisfy — HTML5 input type names
            (`email`, `tel`, `url`, `date`, ...) or semantic slugs
            (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`).
          example: email
        pattern:
          type: string
          description: Regular expression the value must match (JavaScript-flavor).
          example: ^\d{5}(-\d{4})?$
        enum:
          type: array
          items:
            type: string
          description: Allowed values when the field is drawn from a fixed set.
          example:
            - SSN
            - ITIN
            - NON_US_TAX_ID
        minLength:
          type: integer
          description: Minimum length in characters.
          example: 1
        maxLength:
          type: integer
          description: Maximum length in characters.
          example: 500
    DigitalWallet:
      type: string
      enum:
        - APPLE_PAY
        - GOOGLE_PAY
        - SAMSUNG_PAY
      description: The digital wallet a card is being added to.
      example: APPLE_PAY
    CardTokenizationApplePayPayload:
      type: object
      description: >-
        The encrypted pass data for Apple Wallet. Pass the three fields straight
        into the `PKAddPaymentPassRequest` your delegate's completion handler
        expects.
      required:
        - activationData
        - encryptedPassData
        - ephemeralPublicKey
      properties:
        activationData:
          type: string
          description: Base64 `activationData` for `PKAddPaymentPassRequest`.
          example: YWN0aXZhdGlvbi1kYXRh
        encryptedPassData:
          type: string
          description: Base64 `encryptedPassData` for `PKAddPaymentPassRequest`.
          example: ZW5jcnlwdGVkLXBhc3MtZGF0YQ==
        ephemeralPublicKey:
          type: string
          description: Base64 `ephemeralPublicKey` for `PKAddPaymentPassRequest`.
          example: ZXBoZW1lcmFsLXB1YmxpYy1rZXk=
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      description: >-
        API token authentication using format `<api token id>:<api client
        secret>`
    AgentAuth:
      type: http
      scheme: bearer
      description: >-
        Bearer token authentication for agent-scoped endpoints. The token is the
        `accessToken` returned when redeeming a device code via `POST
        /agents/device-codes/{code}/redeem`. Agent credentials are user-scoped:
        all requests are automatically bound to the agent's associated customer
        and subject to the agent's policy.

````