# Download an invoice PDF

> The invoices.pdf operation: GET /api/v1/invoices/{id}/pdf in the REST API and the invoices_pdf tool in the MCP server.

Downloads the PDF of an invoice or receipt of the brand. Over REST the response is the PDF itself
(`Content-Type: application/pdf`, `ETag` = its SHA-256, `Content-Disposition` with the invoice number);
MCP clients get the file's metadata and download URL.

The PDF is rendered once, right after issue, from the invoice as issued, and never changes: the stored file
is checked against the SHA-256 recorded on the invoice before it is served. Until it is rendered the call
answers `invoice_pdf_not_ready` (retryable).

## At a glance

- **REST:** `GET /api/v1/invoices/{id}/pdf`
- **MCP tool:** `invoices_pdf`
- **Operation ID:** `invoices.pdf`
- **Scope:** Brand
- **Permission:** `invoices:read`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Authentication:** API key with the `invoices:read` scope
- **Since:** M4

## Request

### Path parameters

| Field | Type       | Description               |
| ----- | ---------- | ------------------------- |
| `id`  | `inv_…` ID | The invoice ID (`inv_…`). |

### Query parameters

This operation takes no query parameters.

## Response

`200 OK` with a JSON object:

| Field             | Type                | Description                                            |
| ----------------- | ------------------- | ------------------------------------------------------ |
| `object`          | `"invoice_pdf"`     |                                                        |
| `invoiceId`       | `inv_…` ID          |                                                        |
| `number`          | string              |                                                        |
| `fileId`          | `file_…` ID         |                                                        |
| `contentType`     | `"application/pdf"` |                                                        |
| `filename`        | string              |                                                        |
| `size`            | integer             |                                                        |
| `sha256`          | string              |                                                        |
| `templateVersion` | integer             |                                                        |
| `url`             | string              | Where to download the bytes with the same credentials. |

## Examples

### The PDF of a receipt

Over REST the body is the PDF; this is the metadata MCP clients see.

```http
GET /api/v1/invoices/inv_01m4tx5nj8emwbyf7y9vcf47yb/pdf
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "invoice_pdf",
  "invoiceId": "inv_01m4tx5nj8emwbyf7y9vcf47yb",
  "number": "GEN-2026-000123",
  "fileId": "file_01m4tx5nj8emwbyf7y9vcf47yg",
  "contentType": "application/pdf",
  "filename": "GEN-2026-000123.pdf",
  "size": 27265,
  "sha256": "4f1c3c3e6a2f0b9d8e7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e",
  "templateVersion": 1,
  "url": "/api/v1/invoices/inv_01m4tx5nj8emwbyf7y9vcf47yb/pdf"
}
```

## Errors

| Code                                                                                               | HTTP status | When                                                                                                  | What to do                                                                                                                                                             |
| -------------------------------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed)             | 400         | `id` isn't an invoice ID (`inv_…`).                                                                   | Fix the fields listed in `details.issues` and send the request again.                                                                                                  |
| [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found)           | 404         | This brand has no such numbered invoice in this mode (a draft has no PDF until it's finalized).       | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.                                                                   |
| [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required)                   | 400         | The request names no brand (an org or entity key without `Ownrecord-Brand`).                          | Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (`details.required_scope`).                     |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied)             | 403         | You can't read this brand's invoices (`invoices:read`; every role but billing admin has it).          | Ask an organization owner or admin for a role or scope that allows this action.                                                                                        |
| [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed)       | 403         | You have no live-mode access, so you can't use live invoices.                                         | Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.                                            |
| [`invoice_pdf_not_ready`](https://ownrecord.io/docs/reference/errors.md#invoice_pdf_not_ready)     | 409         | The PDF is still being rendered (right after issue); try again shortly.                               | The PDF is rendered right after the invoice is issued, usually within a minute. Try again shortly; `pdf.status` on the invoice says when it's ready.                   |
| [`invoice_pdf_unavailable`](https://ownrecord.io/docs/reference/errors.md#invoice_pdf_unavailable) | 500         | The stored file couldn't be read or doesn't match its SHA-256 (download route only); try again later. | Try again in a few minutes. If it keeps failing, contact support with the request ID: the file is checked against its stored SHA-256 and never served when it differs. |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
