# Upload a customer supporting document

Attaches a supporting document to a customer and starts its transfer into Resolve's document
validation service. Use this to hand Resolve buyer data you already hold — bank statements,
financial statements, credit references, or payment history — so it can be used in a credit decision.
Create the customer first; this endpoint is separate from customer creation and belongs to the
Partners API. MCP clients use `partner_create_customer_document` with the returned customer ID as
`merchant_customer_id`. In ChatGPT, attach the file as `download_url` and supply `filename` and
`filetype` separately. See the Partner MCP tool reference.
The transfer mode is determined by the request shape:
- Omit `download_url` and Resolve returns a presigned S3 `upload_url` (`transfer_method=presigned_upload`).
PUT the document bytes to that URL with the headers in `upload_headers` before `upload_expires_at`.
- Supply `download_url` and Resolve queues a background download job (`transfer_method=download_url`).
There is nothing to upload.

Documents are validated asynchronously, so a successful response means the document was accepted for
transfer, not that it passed validation. Poll #fetchCustomer for
the resulting `credit_status` and limit changes.
**Fulfilling a banking-data request.** When a credit decision is waiting on bank statements, pass the
open request's ID as `additional_data_request_id` alongside a `bank_statements` upload. Resolve fulfills
that request once the document validates. The field is only accepted with `document_type`
`bank_statements`, and is rejected with `422` if it does not identify a banking-data request on this
customer that is still awaiting a response.
Validation notes:
- `bank_statements` must be PDFs; other document types also accept PNG, JPEG, CSV, XLS, and XLSX
- `filename` must include an extension matching `filetype`
- `download_url`, when provided, must use `http` or `https`, carry no embedded credentials, and resolve
to a public host

For remote downloads, queue dispatch runs after the document row is committed. A dispatch failure at
that point does not roll the document back — the response is still successful and
`queue_dispatch_status` comes back as `failed`.

Endpoint: POST /customers/{customer_id}/documents
Version: partners-v1
Security: bearerAuth, basicAuth

## Security:

  - `bearerAuth` (unknown)
    http bearer JWT

  - `basicAuth` (unknown)
    http basic

## Path parameters:

  - `customer_id` (string, required)
    ID of the customer the supporting document belongs to

## Request body:

  - `application/json` (unknown)
    The supporting document to attach to the customer.
The transfer mode is determined by the request shape:
- Omit `download_url` and Resolve returns a presigned S3 upload URL for you to PUT the bytes to.
- Supply `download_url` and Resolve queues a background job to fetch the document from your host.

Validation notes:
- `filename` must include an extension, and for known MIME types that extension must match `filetype`
- `document_type` `bank_statements` is restricted to `application/pdf`
- `additional_data_request_id` is only accepted when `document_type` is `bank_statements`
- `download_url`, when provided, must use `http` or `https` and resolve to a public host
- Unknown fields are rejected with `400`

## Request fields (application/json):

  - `document_type` (string, required)
    The type of supporting document being uploaded.
    Enum: "bank_statements"

  - `additional_data_request_id` (string)
    Optional open banking-data additional data request to fulfill. Must reference an additional data
request on this customer with `request_type` `banking_data` that is still awaiting a response —
anything else is rejected with `422`.
This field is only accepted when `document_type` is `bank_statements`.
    Example: adr_1234567890abcdef

  - `filename` (string, required)
    Filename including a `.pdf` extension.
    Example: bank_statement_2026_01.pdf

  - `filetype` (string, required)
    Bank statements must be uploaded as PDFs.
    Enum: "application/pdf"

  - `filename` (string, required)
    Filename including an extension compatible with `filetype`. The extension must match the
MIME type — `.pdf`, `.png`, `.jpg`/`.jpeg`, `.csv`, `.xls`, or `.xlsx`.
    Example: financials_q4_2025.pdf

  - `filetype` (string, required)
    MIME type of the document. The filename extension must match this value.
    Enum: "application/pdf", "image/png", "image/jpeg", "image/jpg", "text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

  - `download_url` (string, required)
    Public HTTP(S) URL without embedded credentials that Resolve will fetch asynchronously.
Local, private, and unresolvable hosts are rejected.
    Example: https://partner-files.example.com/bank_statement_2026_01.pdf

## Request examples:

  - `Presigned upload, fulfilling a banking-data request` (unknown)

  - `Presigned upload, other supporting document` (unknown)

  - `Remote URL download` (unknown)

## Response 200:

  - `200` (unknown)
    Upload instructions for the customer document. The shape depends on the transfer mode requested.

## Response 200 fields (application/json):

  - `id` (string, required)
    Unique identifier of the customer document.
    Example: mcd_1234567890abcdef

  - `document_id` (string, required)
    Alias of the customer document identifier.
    Example: mcd_1234567890abcdef

  - `document_type` (string, required)
    Enum: "bank_statements", "credit_references", "financial_statements", "payment_history", "other"

  - `upload_url` (string, required)
    Presigned S3 URL to PUT the document bytes to.
    Example: https://resolve-document-validation-uploads.s3.amazonaws.com/merchant_customer/cus_123/document/mcd_123/bank_statement_2026_01.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&...

  - `upload_expires_at` (string, required)
    Expiration timestamp for `upload_url`.
    Example: 2026-02-26T18:35:00.000Z

  - `object_key` (string, required)
    S3 object key where the document is expected to be stored.
    Example: merchant_customer/cus_1234567890abcdef/document/mcd_1234567890abcdef/bank_statement_2026_01.pdf

  - `transfer_method` (string, required)
    How the document is moved into Resolve-managed storage.
    Enum: "presigned_upload"

  - `queue_dispatch_status` (string, required)
    Always `null` for presigned uploads. Only remote-URL requests dispatch a download job.
    Enum: null

  - `upload_headers` (object, required)
    Headers to include on the presigned upload PUT request.
Always includes:
- `x-amz-meta-validation_profile`

May include callback routing headers when configured by Resolve:
- `x-amz-meta-callback_domain`
- `x-amz-meta-callback_url`
    Example: {"x-amz-meta-validation_profile":"merchant_underwriting_document_default"}

  - `validation_profile` (string, required)
    Validation profile Resolve applies to the document. Managed by Resolve and not overridable.
    Enum: "merchant_underwriting_document_default"

  - `upload_url` (string, required)
    Always `null` for remote downloads.
    Example: null

  - `upload_expires_at` (string, required)
    Always `null` for remote downloads.
    Example: null

  - `object_key` (string, required)
    S3 object key where the fetched document will be stored.
    Example: merchant_customer/cus_1234567890abcdef/document/mcd_1234567890abcdef/payment_history_2025.csv

  - `queue_dispatch_status` (string, required)
    Result of dispatching the background download job. Dispatch happens after the document row is
committed, so a `failed` dispatch still returns `200` — the document is marked failed rather than
the request being rejected. Retry by submitting the request again.
    Enum: "queued", "failed"

  - `upload_headers` (object, required)
    Empty for remote downloads, since there is no presigned PUT to sign headers for.
    Example: {}

## Response 400:

  - `400` (unknown)
    Bad request error

## Response 400 fields (application/json):

  - `error` (object)

  - `error.message` (string)
    A short string, describing error details
    Example: Validation error

  - `error.type` (string)
    A short string, describing error type
    Enum: "validation_error"

  - `error.details` (array)

  - `error.details.path` (string)
    Path to the field failed validation
    Example: path.to.field

  - `error.details.message` (string)
    Detailed description of the error
    Example: `[field]` is required

## Response 401:

  - `401` (unknown)
    Unauthorized error

## Response 401 fields (application/json):

  - `error` (object)

  - `error.message` (string)
    A short string, describing error details
    Example: Invalid merchant credentials

  - `error.type` (string)
    A short string, describing error type
    Enum: "authentication_error"

## Response 404:

  - `404` (unknown)
    Not found error

## Response 404 fields (application/json):

  - `error` (object)

  - `error.message` (string)
    A short string, describing error details
    Example: [entity] not found

  - `error.type` (string)
    A short string, describing error type
    Enum: "not_found_error"

## Response 422:

  - `422` (unknown)
    `additional_data_request_id` is not an open banking-data request for this customer

## Response 422 fields (application/json):

  - `error` (object)

  - `error.code` (string)
    A short string, identifying the error
    Enum: "INVALID_PARAM"

  - `error.message` (string)
    A short string, describing error details
    Example: Invalid additional_data_request_id

  - `error.type` (string)
    A short string, describing error type
    Enum: "invalid_request"

## Response 429:

  - `429` (unknown)
    Rate limit error

## Response 429 fields (application/json):

  - `error` (object)

  - `error.message` (string)
    A short string, describing error details
    Example: Too many requests

  - `error.type` (string)
    A short string, describing error type
    Enum: "rate_limit_error"

## Response 200 examples:

  - `Presigned upload instructions` (unknown)

  - `Queued remote download` (unknown)

  - `Remote download dispatch failed after the document was recorded` (unknown)

