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

# Issue an agent card

> Issue a virtual card for the authenticated agent, as `POST /cards` with `agentId` does for the platform. The card belongs to the agent's customer, who must have KYC status `APPROVED` and have accepted the cardholder agreement where the platform requires one. Its spend is the customer's own and does not count against the agent's policy, and Grid's default agent merchant-category blocks apply. Requires the ISSUE_CARDS permission; reading the card afterwards needs MANAGE_CARDS. While any of the agent's cards is not `CLOSED`, including one the platform issued for it, the request is rejected with `AGENT_CARD_EXISTS`.

Card issuance is fee-bearing and cannot be reversed, so an `Idempotency-Key` header is required. Keys are scoped to the agent: a retry by the same agent with the same key returns the card the first request created, even though that card is now live, and another agent's key never matches.

New cards start in `status: "PROCESSING"` and follow the same status transitions and `card.status_change` webhooks as cards issued with `POST /cards`.




## OpenAPI

````yaml /openapi.yaml post /agents/me/cards
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: Periodic Statements
    description: >
      Build, deliver, and evidence a Regulation E periodic statement for a
      customer's internal account. A statement period is a calendar month in US
      Central time (`America/Chicago`).


      A statement is issued for each customer's own USD internal account and
      covers their whole balance. Money received through a rule-based account
      appears on its owner's statement; rule-based, bulk settlement and
      platform-owned accounts have no statement of their own.


      **1. The statement — `GET
      /internal-accounts/{id}/balance-changes?startDate=&endDate=`**


      One row per change to the balance, in the order the money moved, with the
      opening and closing balances for the window in the same response. Page
      until `hasMore` is false, then assert this identity across every page
      before you render anything:


      ```

      openingBalance + Σ(data[].amount) == closingBalance

      ```


      If it does not hold, do not send the statement; contact support instead.
      `startDate` and `endDate` bound a half-open window `[startDate, endDate)`:
      for a monthly statement, pass the first instant of the month and the first
      instant of the following month, both in US Central time (for August 2026,
      `2026-08-01T00:00:00-05:00` and `2026-09-01T00:00:00-05:00`). Grid records
      a statement as fetched only for a window that is exactly one such month.


      **2. The receipt — `POST /internal-accounts/{id}/confirm-statement`**


      Once a month, after you have pulled and issued a period's statement, send
      a receipt with the `statementMonth` it covers. Grid stores it as the
      delivery record for that account and period. Sending it again is harmless:
      the first receipt's time is kept.


      **Timing**


      A window whose card settlement has not closed is refused with `409
      NOT_YET_AVAILABLE` rather than answered with figures that could still
      change; retry once it has settled.
  - 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: >-
      Experimental 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.
  - name: Embedded Care
    description: |
      A support chat between the cardholder and Lightspark's care agent, driven
      from the partner's own app. The platform calls with its ordinary Grid
      credential, but the person typing is the cardholder rather than the
      caller, so reaching that cardholder's account takes a second proof: an
      SMS code they send into the chat, after which the partner carries a
      session token in the `X-Ls-Care-Session` header.

      **The surface is two routes, and verification happens inside the
      conversation.**

      1. **Open the chat.** `POST /care/chats/{chatId}/messages` with an empty
         `message`, addressed to the cardholder as `Customer:<uuid>`. Returns
         the chat's id and the agent's opening line in `reply`, which is what
         a chat window renders before anybody has typed. Sends no SMS, needs
         no `Idempotency-Key` and consumes none, and is safe to call again: a
         widget that reloaded gets the same chat back, this time without a
         `reply`.
      2. **Send the cardholder's first message.** The same route with their
         text and an `Idempotency-Key` header. One turn runs synchronously and
         the agent's answer comes back in `reply`. On a chat that cannot yet
         reach the account this call also texts the cardholder a code, and the
         agent's `reply` asks for it.
      3. **The cardholder sends the code as an ordinary message.** When it is
         correct, the response to that turn carries `sessionToken` and
         `expiresAt`. Send that token as the `X-Ls-Care-Session` header on
         every message from then on. A code that does not match is answered in
         `reply`, and the cardholder can simply send it again.
      4. **Close the chat** with `DELETE /care/chats/{chatId}` when the
         cardholder is done. Every response also carries `chatEnded`, and the
         agent can end the chat itself: when `chatEnded` is true, the closing
         line is in `reply` and the chat takes no further messages, so stop
         sending to it. An opening addressed to that `CareChat:<id>` answers
         `409 CARE_CHAT_ENDED`; address the cardholder as `Customer:<uuid>`
         to open a new chat.

      **Render `redactedCustomerMessage` if present, then `reply` if
      present.** That one rule covers an opening, a resume and a turn.

      **A cardholder whose code never arrived asks the agent for another
      one.** The agent sends a new code to the number on file and says so in
      its `reply`. There is no separate route for it.

      **The verification fields are optional hints.** `verificationRequired`
      and `codeLength` let an app show a dedicated one-time-code input of the
      right length, marked as a one-time code so iOS and Android offer to fill
      it from the SMS. A partner can ignore them, since the agent asks for the
      code in its reply and says where it went, and the app still sends the
      code as an ordinary message.

      Step 1 is optional. A message addressed to a `Customer:` id opens that
      cardholder's chat if they have none, so a partner whose cardholder has
      just typed something spends one call rather than two.

      A cardholder who has not verified yet is never a `401`, because the
      first message from every new cardholder is unverified and a `401` there
      would be indistinguishable from a bad credential. On these endpoints a
      `401` means the platform's Grid credential is wrong, the session token
      presented is malformed, or a replay lacks the session token its original
      request required.

      **Verification expires, and a lost session is recoverable in the
      chat.** A chat reaches the cardholder's account only while its
      verification is newer than the session lifetime, fifteen minutes in the
      default deployment, which is also how long a session token lives. Past
      that window a message gets a fresh code, and the agent asks the
      cardholder to send it back inside the conversation, which hands the
      partner the next session token. A new message sent with no
      `X-Ls-Care-Session` header, or with a token past its expiry, on a chat
      whose verification is still current is treated the same way: the
      verification is cancelled before the turn runs, a new code is sent, and
      the agent asks for it. So a client that lost its token, or held one too
      long, simply keeps sending messages. Only a token that is malformed, or
      that was minted for another platform, chat or cardholder, is refused.

      Two things an integration has to get right:

      - **Render `redactedCustomerMessage`, never your own copy of what was
        typed.** Grid masks card numbers and other sensitive digit strings in
        it. A UI that renders its own copy of the input instead puts a card
        number the cardholder pasted back on their screen unmasked, and into
        your logs.
      - **The session token is returned once and is never re-readable.** No
        endpoint hands it back, it cannot be revoked, and it is short-lived by
        design. Hold it for the life of the cardholder's session. It arrives
        on the message response to the turn in which the cardholder sent their
        code, and on no other. Losing it costs the cardholder a new code, never
        access to the chat.

      Some things are absent by construction, so no integration can come to
      depend on them: nothing returns a transcript or an earlier turn's reply
      (retrying under the original `Idempotency-Key` is how an answer that was
      produced but not delivered is recovered; a replay requires the same
      session token its original request required and never carries a
      `sessionToken`, so a lost token is recovered by sending the cardholder's
      next message as a new message, which verifies them again), nothing sets
      a verification state, and nothing changes the number a code is sent to.

      Errors from these endpoints carry `code` and `reason` only (see the
      `CareError` schema), unlike the `Error4xx` schemas used elsewhere in this
      specification.
paths:
  /agents/me/cards:
    post:
      tags:
        - Agent Operations
      summary: Issue an agent card
      description: >
        Issue a virtual card for the authenticated agent, as `POST /cards` with
        `agentId` does for the platform. The card belongs to the agent's
        customer, who must have KYC status `APPROVED` and have accepted the
        cardholder agreement where the platform requires one. Its spend is the
        customer's own and does not count against the agent's policy, and Grid's
        default agent merchant-category blocks apply. Requires the ISSUE_CARDS
        permission; reading the card afterwards needs MANAGE_CARDS. While any of
        the agent's cards is not `CLOSED`, including one the platform issued for
        it, the request is rejected with `AGENT_CARD_EXISTS`.


        Card issuance is fee-bearing and cannot be reversed, so an
        `Idempotency-Key` header is required. Keys are scoped to the agent: a
        retry by the same agent with the same key returns the card the first
        request created, even though that card is now live, and another agent's
        key never matches.


        New cards start in `status: "PROCESSING"` and follow the same status
        transitions and `card.status_change` webhooks as cards issued with `POST
        /cards`.
      operationId: agentCreateCard
      parameters:
        - name: Idempotency-Key
          in: header
          description: >
            A unique identifier for the request, up to 255 characters, scoped to
            the agent. A retry carrying the same key returns the card created by
            the first request; reusing a key for a different card request is
            rejected with `409`.
          required: true
          schema:
            type: string
            maxLength: 255
            example: 550e8400-e29b-41d4-a716-446655440000
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentCardCreateRequest'
            examples:
              virtualCard:
                summary: Issue a virtual card funded by the customer's wallet
                value:
                  fundingSource: InternalAccount:019542f5-b3e7-1d02-0000-000000000002
      responses:
        '201':
          description: >-
            Card created. It starts in `PROCESSING` while the issuer provisions
            it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentCard'
        '400':
          description: >-
            Bad request. Returned with `CARDHOLDER_KYC_NOT_APPROVED` when the
            customer's KYC status is not `APPROVED`, with
            `CARDHOLDER_AGREEMENT_NOT_ACCEPTED` when the platform requires a
            cardholder agreement the customer has not accepted, and with
            `INVALID_INPUT` when the `Idempotency-Key` header is missing or too
            long, when the funding source does not belong to the customer or is
            not denominated in a card-eligible currency, and for general invalid
            parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401'
        '403':
          description: >-
            Forbidden - Agents API or agent cards are not enabled for the
            platform, or the agent does not have the ISSUE_CARDS permission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error403'
        '409':
          description: >-
            Conflict. Returned with `AGENT_CARD_EXISTS` when the agent already
            holds a card that is not `CLOSED`, with `CARD_LIMIT_REACHED` when
            the platform has reached the maximum number of live cards it may
            hold, and with `CONFLICT` when the agent already used the
            `Idempotency-Key` for a different card request.
          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. Environments without a
            configured card issuer return `501 NOT_IMPLEMENTED`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error501'
      security:
        - AgentAuth: []
components:
  schemas:
    AgentCardCreateRequest:
      type: object
      required:
        - fundingSource
      properties:
        fundingSource:
          type: string
          description: >-
            Internal account id that funds the card. The account must belong to
            the agent's customer and be denominated in a card-eligible currency;
            otherwise the request is rejected with `INVALID_INPUT`.
          example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002
    AgentCard:
      title: Agent Card
      type: object
      description: >-
        A card that belongs to the authenticated agent: the card itself and how
        the agent may use it.
      required:
        - card
        - agentId
        - agentCardKind
        - effectiveBlockedMccs
      properties:
        card:
          $ref: '#/components/schemas/Card'
        agentId:
          type: string
          description: The agent the card belongs to.
          example: Agent:019542f5-b3e7-1d02-0000-000000000042
        agentCardKind:
          $ref: '#/components/schemas/AgentCardKind'
        effectiveBlockedMccs:
          type: array
          description: >-
            Every merchant category code the card declines: `blockedMccs` plus
            the categories Grid blocks for agent cards, unless the platform
            lifted those defaults (`defaultMccBlocksLifted`).
          items:
            type: string
            pattern: ^[0-9]{4}$
          example:
            - '7995'
            - '6051'
    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 version is not
            supported for the agreement it was sent for |

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

            | 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 | The receiving institution declined this
            sender. Final; a retry returns the same answer |

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

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

            | AUTH_CREDENTIAL_VERIFICATION_REQUIRED | The new email or phone
            number has no verified replacement credential |

            | AUTH_CREDENTIAL_VERIFICATION_EXPIRED | The replacement
            credential's verification has expired |

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

            | ACCOUNTHOLDER_AGREEMENT_NOT_ACCEPTED | The customer create request
            omits an accountholder agreement its accounts require |

            | CARDHOLDER_AGREEMENT_NOT_ACCEPTED | The customer has not accepted
            the cardholder agreement the platform requires before a card is
            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 |

            | DOCUMENTS_REQUIRED | The destination requires supporting documents
            for the quote's `purposeOfPayment` that the request did not supply.
            `details.missingRequirements` lists the requirement ID of each one |
          enum:
            - INVALID_INPUT
            - END_USER_TERMS_VERSION_NOT_FOUND
            - MISSING_MANDATORY_USER_INFO
            - INVITATION_ALREADY_CLAIMED
            - INVITATIONS_NOT_CONFIGURED
            - INVALID_UMA_ADDRESS
            - INVITATION_CANCELLED
            - 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
            - 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
            - AUTH_CREDENTIAL_VERIFICATION_REQUIRED
            - AUTH_CREDENTIAL_VERIFICATION_EXPIRED
            - STABLECOIN_PROVIDER_ACCOUNT_INVALID
            - STABLECOIN_PROVIDER_ACCOUNT_REVOKED
            - STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED
            - CARDHOLDER_KYC_NOT_APPROVED
            - ACCOUNTHOLDER_AGREEMENT_NOT_ACCEPTED
            - CARDHOLDER_AGREEMENT_NOT_ACCEPTED
            - 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
            - DOCUMENTS_REQUIRED
        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'
            missingRequirements:
              type: array
              description: >-
                The requirement ID of each required document that the quote
                request did not supply. Present on `DOCUMENTS_REQUIRED`.
              items:
                $ref: '#/components/schemas/PaymentDocumentRequirementId'
          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 |

            | DESTINATION_NOT_ALLOWED | The agent may not pay this destination |
          enum:
            - FORBIDDEN
            - USER_NOT_READY
            - COUNTERPARTY_NOT_ALLOWED
            - VELOCITY_LIMIT_EXCEEDED
            - END_USER_TERMS_NOT_ACCEPTED
            - CUSTOMER_NOT_VERIFIED
            - SANCTION_BLOCKED
            - DESTINATION_NOT_ALLOWED
        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`, or
            the card cannot be unfrozen by the platform because Grid froze it
            for review, it was frozen as `COMPROMISED`, or its customer is not
            `ACTIVE` |

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

            | PIN_CHANGE_REQUIRED | The card's PIN unblock allowance is consumed
            for seven days. Change the PIN to recover sooner.
            `details.pinUnblockAvailableAt` gives the next allowed unblock time
            |

            | AGENT_CARD_EXISTS | The agent already holds a card that is not
            `CLOSED`, so it cannot issue another. Close that card first |

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

            | NOT_YET_AVAILABLE | The request is valid, but its result is not
            available yet because the data it depends on could still change.
            Retry later. `reason` says what is outstanding. For balance changes,
            card settlement for a window boundary has not closed |

            | 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. When the conflicting account belongs to your
            platform, `details.externalAccountId` and
            `details.platformAccountId` identify it; otherwise `details` is
            omitted |

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

            | OPERATION_IN_PROGRESS | A conflicting Embedded Wallet operation is
            still in progress |

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

            | PAYMENT_DOCUMENT_ALREADY_USED | The payment document is already
            attached to a quote. A document can be used on one quote only, so
            upload the file again to use it on another quote |
          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
            - PIN_CHANGE_REQUIRED
            - AGENT_CARD_EXISTS
            - CARD_LIMIT_REACHED
            - STABLECOIN_GRID_ENABLEMENT_NOT_REQUESTABLE
            - NOT_YET_AVAILABLE
            - CONFLICT
            - DOCUMENT_ALREADY_EXISTS
            - DUPLICATE_EXTERNAL_ACCOUNT
            - DUPLICATE_PAY_REQUEST
            - OPERATION_IN_PROGRESS
            - SMS_OTP_CREDENTIAL_SET_CHANGED
            - SMS_OTP_PHONE_NUMBER_ALREADY_EXISTS
            - STABLECOIN_SYMBOL_ALREADY_EXISTS
            - STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS
            - WALLET_NOT_PROVISIONED
            - PAYMENT_DOCUMENT_ALREADY_USED
        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
    Card:
      type: object
      required:
        - id
        - customerId
        - status
        - form
        - fundingSource
        - maxSpendPerTransaction
        - maxSpendPerDay
        - maxTransactionsPerDay
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          description: System-generated unique card identifier
          example: Card:019542f5-b3e7-1d02-0000-000000000010
        customerId:
          type: string
          description: The id of the `Customer` who holds this card.
          example: Customer:019542f5-b3e7-1d02-0000-000000000001
        platformCardId:
          type: string
          description: Platform-specific card identifier generated by the server.
          example: card-emp-001
        status:
          $ref: '#/components/schemas/CardStatus'
        statusReason:
          $ref: '#/components/schemas/CardStatusReason'
          description: >-
            Reason associated with the current `status`. Present when the card
            is `PENDING_AUTH`, `CLOSED`, or when provisioning was rejected;
            absent otherwise.
        brand:
          $ref: '#/components/schemas/CardBrand'
        form:
          $ref: '#/components/schemas/CardForm'
        pinStatus:
          $ref: '#/components/schemas/CardPinStatus'
        pinUnblockAvailableAt:
          type: string
          format: date-time
          readOnly: true
          description: >-
            Earliest time another PIN unblock attempt is allowed. Absent until
            the unblock allowance is used. Changing the PIN does not reset this
            time.
          example: '2026-10-15T15:00:00Z'
        last4:
          type: string
          description: Last four digits of the card PAN.
          example: '4242'
        expMonth:
          type: integer
          minimum: 1
          maximum: 12
          description: Card expiration month (1–12).
          example: 12
        expYear:
          type: integer
          description: Card expiration year (four digits).
          example: 2029
        fundingSource:
          type: string
          description: Internal account id that funds this card.
          example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002
        cardCapabilities:
          $ref: '#/components/schemas/CardCapabilities'
          description: >-
            Actions supported for this card by the issuer selected at issuance.
            Present for cards whose program has been resolved; absent otherwise.
            These capabilities are fixed at issuance for the card's lifetime.
        maxSpendPerTransaction:
          anyOf:
            - type: integer
              format: int64
              minimum: 1
              maximum: 9007199254740991
            - type: 'null'
          description: >-
            The largest amount this card can authorize on a single transaction,
            in the smallest unit of its `currency` (cents for USD). An
            authorization for exactly the limit is allowed. A later clearing can
            still settle above it — a restaurant tip, for example — so this caps
            the authorization, not the final settled amount. `null` means the
            card sets no limit of its own. If your platform config also sets
            `cardConfigs.maxSpendPerTransaction` (the platform-level limit), the
            lower of the two applies and this value stays as you set it.
          example: 5000
        maxSpendPerDay:
          anyOf:
            - type: integer
              format: int64
              minimum: 1
              maximum: 9007199254740991
            - type: 'null'
          description: >-
            Card-specific cap on cumulative new spend during one UTC calendar
            day, in the smallest unit of the card's `currency`. The window
            resets at 00:00 UTC. Null means the card has no card-specific daily
            cap. When the platform config also supplies
            `cardConfigs.maxSpendPerDay`, Grid enforces the lower of the two
            values without replacing this configured value. Refunds, reversals,
            and authorization expiries do not restore capacity during the day.
            Spend exactly equal to the effective limit is allowed.
          example: 25000
        maxTransactionsPerDay:
          anyOf:
            - type: integer
              format: int32
              minimum: 1
              maximum: 2147483647
            - type: 'null'
          description: >-
            Card-specific cap on the number of transactions the card may
            authorize during one UTC calendar day. The window resets at 00:00
            UTC. Null means the card has no card-specific daily transaction cap.
            When the platform config also supplies
            `cardConfigs.maxTransactionsPerDay`, Grid enforces the lower of the
            two values without replacing this configured value. Each approved
            authorization counts once for the day it was authorized; refunds,
            reversals, and authorization expiries do not restore capacity during
            the day. A transaction that brings the day's count exactly to the
            effective limit is allowed.
          example: 20
        allowedMccs:
          type: array
          minItems: 1
          description: >-
            Merchant category codes the card may spend at. Present only on a
            card issued for an agent; absent when that card may spend at any
            category not blocked.
          items:
            type: string
            pattern: ^[0-9]{4}$
          example:
            - '5411'
        blockedMccs:
          type: array
          description: >-
            Merchant category codes a card issued for an agent declines, with
            `cardDeclinedReason: BLOCKED`. Present only on such a card, which
            also declines Grid's default agent categories unless
            `defaultMccBlocksLifted` is true.
          items:
            type: string
            pattern: ^[0-9]{4}$
          example:
            - '7995'
        agentId:
          type: string
          description: The agent the card was issued for, when there is one.
          example: Agent:019542f5-b3e7-1d02-0000-000000000042
        defaultMccBlocksLifted:
          type: boolean
          description: >-
            Whether the platform lifted Grid's default agent merchant-category
            blocks on this card. Present only for a card issued for an agent.
          example: false
        currency:
          type: string
          description: >-
            Currency the card transacts in, fixed at issuance by its card
            program. USDB-funded cards transact in USD, with funding converted
            at 1 USDB = 1 USD. Spending limits use the smallest unit of the
            card's currency (USD cents for USDB-funded cards). Changing the
            funding source does not change the card's currency or spending-limit
            units.
          example: USD
        processorRef:
          type: string
          description: >-
            Opaque processor-side reference for the card (e.g. the Lithic card
            token). Useful for cross-referencing in the processor's dashboards;
            not used for any Grid request routing.
          example: card_b81c2a4f
        issuerRef:
          type: string
          description: >-
            Opaque identifier for the card on the issuer of record (e.g. the
            Lead Bank account/card identifier). Useful for cross-referencing in
            issuer dashboards; not used for any Grid request routing.
          example: lead_card_7a1b9c3d
        createdAt:
          type: string
          format: date-time
          description: Creation timestamp
          example: '2026-05-08T14:10:00Z'
        updatedAt:
          type: string
          format: date-time
          description: Last update timestamp
          example: '2026-05-08T14:11:00Z'
    AgentCardKind:
      type: string
      enum:
        - STANDARD
      description: >
        How an agent card is used and funded.


        | Kind | Description |

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

        | `STANDARD` | A card issued for the agent, by the platform with `POST
        /cards` or by the agent with `POST /agents/me/cards`. The customer holds
        the card details and its spend is the customer's own; the agent can read
        it, tighten its limits, and freeze it. |
    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.
    PaymentDocumentRequirementId:
      type: string
      description: >-
        A stable identifier for one required document within a purpose's
        requirements. The same ID means the same requirement across quotes. It
        is separate from `PaymentDocumentType`. The requirement ID names the
        document to supply, and the document type names what a file is. The two
        differ where a requirement accepts alternatives. For example, a file
        declared as either `PURCHASE_ORDER` or `DELIVERY_SLIP` fills the
        `SUPPORTING_PROOF` requirement.


        [Supporting
        Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/send-payment#supporting-documents)
        lists the IDs each purpose requires.


        Treat the ID as an opaque value, not a member of a fixed list. Grid may
        add new IDs as requirements change.
      example: SUPPORTING_PROOF
    CardStatus:
      type: string
      enum:
        - PENDING_KYC
        - PROCESSING
        - PENDING_AUTH
        - ACTIVE
        - FROZEN
        - CLOSED
      description: >
        Lifecycle status of a card.


        | Status | Description |

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

        | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in
        this status cannot transact. |

        | `PROCESSING` | The card has been requested and is being provisioned
        with the issuer. |

        | `PENDING_AUTH` | The issuer has provisioned the card, but its USDB
        Embedded Wallet funding source lacks an active delegated signing key.
        Complete `POST /auth/delegated-keys` before using the card. |

        | `ACTIVE` | The card is live and can authorize transactions. |

        | `FROZEN` | The card is temporarily disabled by the platform or by
        Grid. New authorizations are declined with `cardDeclinedReason:
        CARD_NOT_ACTIVE`. Existing settlements and refunds continue to
        reconcile. A card Grid froze for review, or one frozen as `COMPROMISED`,
        cannot be unfrozen by the platform. |

        | `CLOSED` | The card is permanently closed. Terminal, irreversible
        status. |
    CardStatusReason:
      type: string
      enum:
        - DELEGATION_REQUIRED
        - ISSUER_REJECTED
        - CLOSED_BY_PLATFORM
        - CLOSED_BY_GRID
      description: >
        Reason a card reached a terminal or non-active status. Present on

        `PENDING_AUTH` and `CLOSED` cards, and on cards that fail provisioning
        before reaching

        `ACTIVE`.


        | Reason | Description |

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

        | `DELEGATION_REQUIRED` | The card funding source has no usable
        delegated signing key. Present while the card is `PENDING_AUTH`. |

        | `ISSUER_REJECTED` | The card issuer rejected provisioning during
        `PROCESSING`. |

        | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}`
        (`status: CLOSED`) by the platform. |

        | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or
        risk action). |
    CardBrand:
      type: string
      enum:
        - VISA
        - MASTERCARD
      description: |
        Card network brand. Read-only — determined by Grid when the card is
        provisioned with the issuer.
    CardForm:
      type: string
      enum:
        - VIRTUAL
      description: |
        Physical form factor of the card. Only `VIRTUAL` is supported in v1;
        `PHYSICAL` will be added in a later release.
    CardPinStatus:
      type: string
      enum:
        - NOT_SET
        - OK
        - BLOCKED
      example: OK
      description: >
        State of the card's PIN. On the Card resource, this is the last known
        status

        and is present whenever PIN management is supported. An absent value
        means

        PIN management is unavailable for this card; it does not mean `NOT_SET`.

        Use `GET /cards/{id}` to retrieve `pinStatus`.


        | Status | Description |

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

        | `NOT_SET` | No PIN has been set on the card. PIN verification is not
        enabled. Set one with `POST /cards/{id}/set-pin` or the hosted form
        returned by `GET /cards/{id}/pin-entry-url`. |

        | `OK` | A PIN is set and usable. |

        | `BLOCKED` | The PIN was entered incorrectly three consecutive times
        and is refused until cleared with `POST /cards/{id}/pin/unblock`, or
        replaced with `POST /cards/{id}/set-pin`. |
    CardCapabilities:
      type: object
      description: Actions supported by the card program associated with this resource.
      required:
        - supportsSpendLimits
        - supportsSpendLimitsAtIssuance
        - supportsTransactionCountLimit
        - supports3dSecurePassword
        - supportsPanReveal
        - supportsDigitalWalletTokenization
      properties:
        supportsSpendLimits:
          type: boolean
          description: >-
            Whether a card in this program can have `maxSpendPerTransaction` and
            `maxSpendPerDay` at all. On card programs where the card issuer
            makes authorization decisions, these limits can only be set after
            issuance through `PATCH /cards/{id}`. Check
            `supportsSpendLimitsAtIssuance` to determine whether you can supply
            them when issuing a card.
          example: true
        supportsSpendLimitsAtIssuance:
          type: boolean
          description: >-
            Whether `maxSpendPerTransaction` and `maxSpendPerDay` may be
            supplied on `POST /cards`. This is true for card programs where Grid
            makes the authorization decision and false for card programs where
            the card issuer makes authorization decisions.
          example: true
        supportsTransactionCountLimit:
          type: boolean
          description: Whether cards in this program accept `maxTransactionsPerDay`.
          example: true
        supports3dSecurePassword:
          type: boolean
          description: >-
            Whether cards in this program accept a caller-supplied
            `threeDSecurePassword`.
          example: false
        supportsPanReveal:
          type: boolean
          description: >-
            Whether cards in this program can be revealed through `POST
            /cards/{id}/reveal`.
          example: true
        supportsDigitalWalletTokenization:
          type: boolean
          description: >-
            Whether cards in this program can be added to Apple Pay, Google Pay,
            or Samsung Pay from your app through `POST /cards/{id}/tokenize`.
            Manual entry into a wallet works regardless of this flag.
          example: true
    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
  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/redeem`. Agent credentials are user-scoped: all
        requests are automatically bound to the agent's associated customer and
        subject to the agent's policy.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.