---
title: "Upload a bank statement PDF"
method: POST
path: "/documents"
tags: ["Documents"]
---

# Upload a bank statement PDF

`POST /documents`

## Request

- Base URL: `https://api.bankstatemently.com/v1`
- URL: `https://api.bankstatemently.com/v1/documents`
- Auth: API key in header `X-API-Key`

Upload a PDF bank statement for conversion. The file is processed asynchronously. Poll the returned `id` via GET /v1/documents/{id} to check progress. Rate limit: 10 requests per minute. Alternatively, POST a JSON body `{ "upload_id": "..." }` referencing a token minted via POST /v1/upload-tokens, to convert a previously-PUT file by reference.

## Query parameters

- `retry` 'true'

## Headers

- `Idempotency-Key` string
- `X-Filename` string
- `X-Webhook-URL` string, uri
- `X-Password` string

## Request body

- object
  - `upload_id` string, required: An upload_id from POST /v1/upload-tokens, after PUTting the file to its upload_url. Converts the previously-uploaded file by reference instead of sending PDF bytes in this request.
  - `webhook_url` string, uri: Webhook URL for processing completion notifications. Overrides the default webhook URL configured on the API key.

## Response `202`

Upload accepted. Processing has started, or the PDF requires a password.

- StatementUploadResponse: Response returned when a PDF is successfully accepted for processing.
  - `id` string, uuid, required: Unique document identifier. Use this to poll status and request exports.
  - `status` 'processing' | 'completed' | 'failed' | 'password_required', required: The processing status of a document.
  - `contentHash` string, required: Content-addressable hash of the uploaded file.
  - `createdAt` string, date-time, required: Timestamp when the document was created.
  - `statements` StatementSummary[], required: Always an empty array on upload; populated once processing completes.
    - `index` integer, required: Zero-based index of this statement within the document.
    - `statementPeriod` StatementPeriod: The date range covered by a single statement within the document.
      - `from` string, date, required: Start date of the statement period (ISO 8601).
      - `to` string, date, required: End date of the statement period (ISO 8601).
    - `transactionCount` integer, nullable: Number of transactions in this statement, or null if not yet counted.
  - `links` object, required
    - `self` string, uri, required: URL to poll for processing status.
    - `unlock` string, uri: URL to submit a password for unlocking. Only present when status is `password_required`.

## Other responses

- `400`: Invalid request (e.g., missing file, wrong content type, invalid file).
- `401`: Authentication failed, API key revoked, or API key expired.
- `403`: Quota exceeded (insufficient credits, page limit, or file size).
- `409`: Document already exists or is being processed.
- `422`: Wrong password. Only returned when X-Password header is provided for an encrypted PDF.
- `429`: Too many requests. Wait the number of seconds indicated by the `Retry-After` header.
- `500`: An unexpected server error occurred.
- `503`: The service is temporarily unavailable.

---

[API](https://skmtc.dev/bankstatemently/apis/bankstatemently-api.md) · [All operations](https://skmtc.dev/bankstatemently/apis/bankstatemently-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bankstatemently/apis/bankstatemently-api/revisions/4c3b7fb26edf?raw)
