---
title: "Upload invoice PDF"
method: POST
path: "/invoices/{id}/pdf"
tags: ["Invoices"]
---

# Upload invoice PDF

`POST /invoices/{id}/pdf`

Upload the original invoice PDF (max 10 MB). Provide exactly one of `content` (base64-encoded bytes) or `url` (a public HTTPS link we download once, at upload time). Both variants behave identically once accepted: we store our own copy of the bytes and never read the link again, so the document keeps serving even if your host later goes away, and an unreachable link fails this request outright rather than degrading for a customer later. **Updates are push-only:** we never re-read the link or poll for changes, so a PDF updated in your system is not reflected here until you send this request again — with fresh `content`, or with the `url` (the same url is fine; we re-download it at that moment). Each upload replaces the previous PDF; last write wins. Only invoices synced from an accounting integration accept a PDF: an invoice created through `POST /invoices` has no original document from your system, and returns `422 unsupported_invoice`.

## Path parameters

- `id` string, required

## Request body

- UploadInvoicePdfInput — Invoice PDF upload request. Provide exactly one of content (base64-encoded bytes) or url (public HTTPS link to the PDF, downloaded once at upload time and stored). Either way we keep our own copy and never read the link again, so send the request again to publish an updated document.
  - `content` string — The PDF document as standard base64 (RFC 4648). Must decode to a valid PDF (the file must start with the PDF header) of at most 10 MB. Mutually exclusive with url.
  - `url` string — A public, absolute HTTPS link to the PDF. Fetched exactly once, at upload time; we store our own copy and never read the link again — if the document behind it changes, re-send this request to publish the new version. HTTP links, redirects to non-HTTPS locations, and links resolving to private addresses are rejected. The response must be a PDF of at most 10 MB. Mutually exclusive with content.

## Response `200`

`path` is the stored location of the PDF, for both variants. It is an opaque identifier — retrieve the document via GET /invoices/{id}/pdf-link

- UploadInvoicePdfReply
  - `path` string — Path is the stored location of the PDF, for both the content and url variants. It is an opaque identifier, not a downloadable link — to retrieve the document, call GET /invoices/{id}/pdf-link for a signed URL.

## Other responses

- `400` — Invalid request: both or neither of `content`/`url` provided; `content` is not valid base64 or does not decode to a PDF; `url` is not HTTPS, redirects to a non-HTTPS location, is unreachable (non-2xx), resolves to a blocked address, exceeds the redirect limit, times out, or does not return a PDF
- `404` — Invoice not found
- `413` — The PDF exceeds the 10 MB limit (applies to both the decoded `content` bytes and the `url` response body)
- `422` — The invoice is not synced from an accounting integration

---

[API](https://skmtc.net/alternativepayments/apis/alternative-payments.md) · [All operations](https://skmtc.net/alternativepayments/apis/alternative-payments/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/alternativepayments/alternative-payments/revisions/730efda86cd1/schema)
