> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-codex-at-6686-payment-documents-spec.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload a payment document

> Upload a supporting document for a payout that requires one. [Supporting
Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/supporting-documents)
lists which payouts need documents, the documents each
`purposeOfPayment` needs, and what the payout partner checks in them.
Upload each file here,
then pass the returned `id` values in `documentIds` on `POST /quotes`.
Grid attaches the files to the payment before it returns the quote.

The request must use multipart/form-data with the file in the `file`
field and metadata in the remaining fields. Each request uploads one file.
To upload several files, send one request per file. You can send them in
parallel. A quote accepts up to 3 documents.

Supported formats are PDF, JPEG, and PNG. Grid detects the format from the
file contents, not the file name. The file must be from 1 to 8,000,000
bytes. An empty file, a larger file, and any other format return
`400 INVALID_INPUT`.

A payment document:

- can be used until its `expiresAt`, 24 hours after upload
- can be used on one quote only, and only on a quote for the customer in
  `customerId`, or on the platform's own quote when `customerId` is
  omitted
- has its file deleted by Grid once it is attached to the payment

Grid does not check what a document says. The payout partner reviews each
document after Grid attaches it, and may reject or delay the payout. A
successful attachment means the payout partner received the file, not
that it approved it.




## OpenAPI

````yaml /openapi.yaml post /payment-documents
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:
  /payment-documents:
    post:
      tags:
        - Cross-Currency Transfers
      summary: Upload a payment document
      description: >
        Upload a supporting document for a payout that requires one. [Supporting

        Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/supporting-documents)

        lists which payouts need documents, the documents each

        `purposeOfPayment` needs, and what the payout partner checks in them.

        Upload each file here,

        then pass the returned `id` values in `documentIds` on `POST /quotes`.

        Grid attaches the files to the payment before it returns the quote.


        The request must use multipart/form-data with the file in the `file`

        field and metadata in the remaining fields. Each request uploads one
        file.

        To upload several files, send one request per file. You can send them in

        parallel. A quote accepts up to 3 documents.


        Supported formats are PDF, JPEG, and PNG. Grid detects the format from
        the

        file contents, not the file name. The file must be from 1 to 8,000,000

        bytes. An empty file, a larger file, and any other format return

        `400 INVALID_INPUT`.


        A payment document:


        - can be used until its `expiresAt`, 24 hours after upload

        - can be used on one quote only, and only on a quote for the customer in
          `customerId`, or on the platform's own quote when `customerId` is
          omitted
        - has its file deleted by Grid once it is attached to the payment


        Grid does not check what a document says. The payout partner reviews
        each

        document after Grid attaches it, and may reject or delay the payout. A

        successful attachment means the payout partner received the file, not

        that it approved it.
      operationId: uploadPaymentDocument
      requestBody:
        $ref: '#/components/requestBodies/PaymentDocumentUploadRequestBody'
      responses:
        '201':
          description: Payment document uploaded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentDocument'
              example:
                id: PaymentDocument:019542f5-b3e7-1d02-0000-000000000001
                customerId: Customer:019542f5-b3e7-1d02-0000-000000000001
                documentType: INVOICE
                fileName: invoice-2025-0142.pdf
                sizeBytes: 482133
                contentType: application/pdf
                status: UPLOADED
                expiresAt: '2025-10-04T12:00:00Z'
                createdAt: '2025-10-03T12:00:00Z'
        '400':
          description: >-
            Bad request. Returned with `INVALID_INPUT` when the file is empty,
            larger than 8,000,000 bytes, or not a PDF, JPEG, or PNG, when
            `documentType` is not a valid value, or when a required field is
            missing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401'
        '404':
          description: >-
            Customer not found. Returned with `CUSTOMER_NOT_FOUND` when
            `customerId` does not match a customer on your platform.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error404'
        '500':
          description: Internal service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error500'
      security:
        - BasicAuth: []
components:
  requestBodies:
    PaymentDocumentUploadRequestBody:
      required: true
      content:
        multipart/form-data:
          schema:
            $ref: '#/components/schemas/PaymentDocumentUploadRequest'
  schemas:
    PaymentDocument:
      type: object
      description: >-
        A supporting document uploaded for a payout that requires one. Pass its
        `id` in `documentIds` on `POST /quotes`.
      required:
        - id
        - documentType
        - fileName
        - sizeBytes
        - contentType
        - status
        - expiresAt
        - createdAt
      properties:
        id:
          type: string
          description: Unique identifier for this payment document
          example: PaymentDocument:019542f5-b3e7-1d02-0000-000000000001
        customerId:
          type: string
          description: >-
            ID of the sending customer whose payment this document supports. The
            document can only be used on this customer's quotes. Absent when the
            platform itself is the sender.
          example: Customer:019542f5-b3e7-1d02-0000-000000000001
        documentType:
          $ref: '#/components/schemas/PaymentDocumentType'
        fileName:
          type: string
          description: File name of the uploaded file
          example: invoice-2025-0142.pdf
        sizeBytes:
          type: integer
          description: >-
            Size of the uploaded file in bytes. It never exceeds the largest
            file `POST /payment-documents` accepts, which is 8,000,000 bytes
            today.
          minimum: 1
          example: 482133
        contentType:
          type: string
          description: >-
            File format as a MIME type, as Grid detected it from the file
            contents. Today one of `application/pdf`, `image/jpeg`, or
            `image/png`. Treat it as an open value, because Grid may accept more
            formats later.
          example: application/pdf
        status:
          $ref: '#/components/schemas/PaymentDocumentStatus'
        expiresAt:
          type: string
          format: date-time
          description: >-
            When the document stops being usable if it has not been attached to
            a quote. This is 24 hours after `createdAt`.
          example: '2025-10-04T12:00:00Z'
        quoteId:
          type: string
          description: >-
            ID of the quote whose payment this document is attached to. Present
            only when `status` is `ATTACHED`.
          example: Quote:019542f5-b3e7-1d02-0000-000000000006
        createdAt:
          type: string
          format: date-time
          description: When this document was uploaded
          example: '2025-10-03T12:00:00Z'
    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 |

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

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

            | PAYMENT_DOCUMENT_NOT_FOUND | Payment document 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
            - PAYMENT_DOCUMENT_NOT_FOUND
        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
    PaymentDocumentUploadRequest:
      title: Payment Document Upload Request
      type: object
      required:
        - file
        - documentType
      properties:
        file:
          type: string
          format: binary
          description: >
            The document file, from 1 to 8,000,000 bytes. Grid accepts PDF,
            JPEG,

            and PNG files and detects the format from the file contents, not the

            file name. An empty file, a larger file, and any other format return

            `400 INVALID_INPUT`.
        documentType:
          $ref: '#/components/schemas/PaymentDocumentType'
          description: >-
            What the file is. To fill a requirement, use one of the types it
            accepts, as listed in [Supporting
            Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/supporting-documents).
        customerId:
          type: string
          description: >-
            ID of the sending customer whose payment this document supports. The
            document can only be used on this customer's quotes. Omit it when
            the platform itself is the sender, as on a quote with no
            `customerId`. The document can then only be used on the platform's
            own quotes.
          example: Customer:019542f5-b3e7-1d02-0000-000000000001
    PaymentDocumentType:
      type: string
      description: >-
        What a supporting document is. These are kinds of evidence, not file
        formats: `INVOICE` means the file is an invoice.


        [Supporting
        Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/supporting-documents)
        lists the types each requirement accepts. When you upload a file with
        `POST /payment-documents`, `documentType` declares which type the file
        is.
      enum:
        - PURCHASE_ORDER
        - LOGISTICS_BILL
        - CUSTOMS_DECLARATION
        - INVOICE
        - CONTRACT
        - DELIVERY_SLIP
        - BILL_OF_LADING
        - FLIGHT_TICKET
        - TRAVEL_DOCUMENT
        - HOTEL_BOOKING_CONFIRMATION
      example: INVOICE
    PaymentDocumentStatus:
      type: string
      description: >
        Where the payment document is in its lifecycle.


        | Status | Terminal | Meaning |

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

        | `UPLOADED` | No | Ready to use. Pass the `id` in `documentIds` on
        `POST /quotes` before `expiresAt`. |

        | `ATTACHED` | Yes | Attached to the payment behind the quote in
        `quoteId`. Grid has deleted the file. |

        | `EXPIRED` | Yes | Not attached to a quote before `expiresAt`. The
        document can no longer be used. |
      enum:
        - UPLOADED
        - ATTACHED
        - EXPIRED
      example: UPLOADED
    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/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
    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/{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.

````