# Invoice PDFs

Render or download an invoice PDF and create a customer-facing download URL.

Invoice PDF rendering is synchronous. The first render request pins the language
selected by `Accept-Language`; the first successful render is billable, while
cached requests are free and keep that language.

Responses are JSON by default. Send `Accept: application/pdf` to receive the PDF
bytes directly. JSON responses contain an unauthenticated customer-facing URL
that expires after 30 days. Anyone with that URL can download the invoice until
it expires, so treat it as a secret.

`GET` only retrieves a cached PDF and never renders or bills. `POST` renders the
PDF when necessary and returns the cached PDF otherwise.

## The Invoice PDF object

### Properties

#### `id`

Type: `string`

Opaque identifier for the generated PDF.

#### `object`

Type: `string`

String identifying this as an Invoice PDF object. Always `invoice_pdf`.

#### `live`

Type: `boolean`

True when the object belongs to the live environment; false for test data.

#### `invoice`

Type: `string`

Invoice rendered into this PDF.

#### `status`

Type: `enum`

Current rendering state.

Possible values:

- `rendering` — FiscalRail is generating the PDF.
- `ready` — The PDF is available for download.
- `failed` — The last render attempt failed.

#### `locale`

Type: `enum`

Language pinned when this PDF was first rendered.

Possible values:

- `es` — Spanish.
- `en` — English.

#### `rendered_at`

Type: `string or null`

When rendering completed, or null until the PDF is ready.

#### `url`

Type: `string or null`

Temporary unauthenticated download URL, or null until the PDF is ready.

#### `url_expires_at`

Type: `string or null`

When the download URL expires, or null when no URL is available.


### Example

```json
{
  "id": "inv_pdf_14Vxtqg6oXpAY5WdWoq4wW",
  "object": "invoice_pdf",
  "live": true,
  "invoice": "inv_14Vxtqg6oXpAY5WdWoq4wW",
  "status": "ready",
  "locale": "es",
  "rendered_at": "2026-07-31T09:31:00Z",
  "url": "https://api.fiscalrail.com/invoice-pdfs/inv_pdf_14Vxtqg6oXpAY5WdWoq4wW?token=example",
  "url_expires_at": "2026-08-30T09:31:00Z"
}
```

## Render an invoice PDF

`POST /v1/invoices/{invoice_id}/pdf`

Synchronously renders the PDF and charges only when no cached PDF
exists. `Accept-Language` selects `es` or `en` for the first render
request; that locale remains pinned for the invoice PDF. The account
invoice locale is used as fallback. Returns JSON metadata by default; send
`Accept: application/pdf` for PDF bytes. A cached render returns `200`,
while a newly rendered PDF returns `201`.

### Path parameters

#### `invoice_id`

Type: `string` — required

The opaque ID of the invoice whose PDF should be retrieved or rendered.


### Headers

#### `Accept-Language`

Type: `string`

Preferred language for the first render. Supports Spanish and English; the account's invoice locale is the fallback.


### Responses

- `200` — [A cached Invoice PDF object or the PDF bytes.](#the-invoice-pdf-object) Formats: JSON or PDF.
- `201` — [A newly rendered Invoice PDF object or the PDF bytes.](#the-invoice-pdf-object) Formats: JSON or PDF.

### Example request

```bash
curl --request POST \
  'https://api.fiscalrail.com/v1/invoices/inv_14Vxtqg6oXpAY5WdWoq4wW/pdf' \
  --header "Authorization: Bearer ak_test_..." \
  --header "Accept-Language: es"
```

### Example response — 200

```json
{
  "id": "inv_pdf_14Vxtqg6oXpAY5WdWoq4wW",
  "object": "invoice_pdf",
  "live": true,
  "invoice": "inv_14Vxtqg6oXpAY5WdWoq4wW",
  "status": "ready",
  "locale": "es",
  "rendered_at": "2026-07-31T09:31:00Z",
  "url": "https://api.fiscalrail.com/invoice-pdfs/inv_pdf_14Vxtqg6oXpAY5WdWoq4wW?token=example",
  "url_expires_at": "2026-08-30T09:31:00Z"
}
```

## Retrieve an existing invoice PDF without generating or billing

`GET /v1/invoices/{invoice_id}/pdf`

Returns JSON metadata by default. Send `Accept: application/pdf` to
download the PDF bytes. This operation never renders or bills; it
returns `404` if no PDF has been generated.

### Path parameters

#### `invoice_id`

Type: `string` — required

The opaque ID of the invoice whose PDF should be retrieved or rendered.


### Responses

- `200` — [An Invoice PDF object or the PDF bytes.](#the-invoice-pdf-object) Formats: JSON or PDF.

### Example request

```bash
curl --request GET \
  'https://api.fiscalrail.com/v1/invoices/inv_14Vxtqg6oXpAY5WdWoq4wW/pdf' \
  --header "Authorization: Bearer ak_test_..."
```

### Example response — 200

```json
{
  "id": "inv_pdf_14Vxtqg6oXpAY5WdWoq4wW",
  "object": "invoice_pdf",
  "live": true,
  "invoice": "inv_14Vxtqg6oXpAY5WdWoq4wW",
  "status": "ready",
  "locale": "es",
  "rendered_at": "2026-07-31T09:31:00Z",
  "url": "https://api.fiscalrail.com/invoice-pdfs/inv_pdf_14Vxtqg6oXpAY5WdWoq4wW?token=example",
  "url_expires_at": "2026-08-30T09:31:00Z"
}
```
