---
title: "Upload a payment document"
method: POST
path: "/payment-documents"
tags: ["Cross-Currency Transfers"]
---

# Upload a payment document

`POST /payment-documents`

## Request

- Base URL: `https://api.lightspark.com/grid/2025-10-13`
- URL: `https://api.lightspark.com/grid/2025-10-13/payment-documents`
- Auth: HTTP basic

Upload a supporting document for a payout that requires one. [Supporting
Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/send-payment#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.

## Request body `multipart/form-data`

- PaymentDocumentUploadRequest
  - `file` string, binary, required: 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` 'PURCHASE_ORDER' | 'LOGISTICS_BILL' | 'CUSTOMS_DECLARATION' | 'INVOICE' | 'CONTRACT' | 'DELIVERY_SLIP' | 'BILL_OF_LADING' | 'FLIGHT_TICKET' | 'TRAVEL_DOCUMENT' | 'HOTEL_BOOKING_CONFIRMATION', required: 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/send-payment#supporting-documents) lists the types each requirement accepts. When you upload a file with `POST /payment-documents`, `documentType` declares which type the file is.
  - `customerId` string: 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.

## Response `201`

Payment document uploaded successfully

- PaymentDocument: A supporting document uploaded for a payout that requires one. Pass its `id` in `documentIds` on `POST /quotes`.
  - `id` string, required: Unique identifier for this payment document
  - `customerId` string: 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.
  - `documentType` 'PURCHASE_ORDER' | 'LOGISTICS_BILL' | 'CUSTOMS_DECLARATION' | 'INVOICE' | 'CONTRACT' | 'DELIVERY_SLIP' | 'BILL_OF_LADING' | 'FLIGHT_TICKET' | 'TRAVEL_DOCUMENT' | 'HOTEL_BOOKING_CONFIRMATION', required: 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/send-payment#supporting-documents) lists the types each requirement accepts. When you upload a file with `POST /payment-documents`, `documentType` declares which type the file is.
  - `fileName` string, required: File name of the uploaded file
  - `sizeBytes` integer, required: Size of the uploaded file in bytes. It never exceeds the largest file `POST /payment-documents` accepts, which is 8,000,000 bytes today.
  - `contentType` string, required: 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.
  - `status` 'UPLOADED' | 'ATTACHED' | 'EXPIRED', required: 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. |
  - `expiresAt` string, date-time, required: When the document stops being usable if it has not been attached to a quote. This is 24 hours after `createdAt`.
  - `quoteId` string: ID of the quote whose payment this document is attached to. Present only when `status` is `ATTACHED`.
  - `createdAt` string, date-time, required: When this document was uploaded

## Other responses

- `400`: 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.
- `401`: Unauthorized
- `404`: Customer not found. Returned with `CUSTOMER_NOT_FOUND` when `customerId` does not match a customer on your platform.
- `500`: Internal service error

## Changes

> 115 revisions in range; 2 not diffed.

- **2026-10-28** `d996ddfb9d2b`: 2 info
  - added the optional property `details/missingFields` to the response with the `400` status
  - added the optional property `details/refusalReason` to the response with the `400` status
- **2026-10-24** `715332dcb111`: 1 warning
  - added the new `EXACT_AMOUNT_UNAVAILABLE` enum value to the `code` response property for the response status `400`
- **2026-10-20** `761d1d030cb5`: 1 warning
  - added the new `CARDHOLDER_AGREEMENT_NOT_ACCEPTED` enum value to the `code` response property for the response status `400`
- **2026-10-13** `ddcb4ec73fd0`: 1 warning
  - added the new `ACCOUNTHOLDER_AGREEMENT_NOT_ACCEPTED` enum value to the `code` response property for the response status `400`
- **2026-10-05** `6d67fe99049c`: 3 info
  - removed the `INVALID_PAYREQ_RESPONSE` enum value from the `code` response property for the response status `400`
  - removed the `LOOKUP_REQUEST_FAILED` enum value from the `code` response property for the response status `400`
  - removed the `QUOTE_REQUEST_FAILED` enum value from the `code` response property for the response status `400`

[Operation history](https://skmtc.dev/lightsparkdev/apis/grid-api/changes/payment-documents/post.md)

---

[API](https://skmtc.dev/lightsparkdev/apis/grid-api.md) - [All operations](https://skmtc.dev/lightsparkdev/apis/grid-api/llms.txt) - [OpenAPI document](https://skmtc.dev/lightsparkdev/apis/grid-api/revisions/7a1db46ec552?raw)
