Skip to content

Render a PDF

POST
/v2/pdf

Renders a PDF from a complete Press document, or from data merged into the template named by template_id. The response body is the PDF itself.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Query Parameters

template_id

The template to render or validate against. Required when the body is JSON, CSV, or Markdown; optional when the body is a complete Press document.

Type
string
Examples
"papermill-invoice""papermill-modern-invoice""papermill-modern-letter""papermill-modern-report""papermill-simple-report"
flow

With Content-Type: text/markdown, the template flow the body replaces. Defaults to body. Supplying it with any other content type is rejected rather than silently ignored.

Type
string
draft

Set to true to render against your draft allowance instead of your production page allowance. Any other value renders against the production allowance.

Type
string

Request Body

XML

Responses

The rendered PDF.

application/pdf

Playground

Authorization
Variables
Key
Value
Body

Samples

Example

Render a saved template with markdown as the body. The response is the PDF itself, so write the bytes to a file rather than to your terminal.

shell
curl -X POST "https://api.papermill.io/v2/pdf?template_id=papermill-simple-report" \
  -H "Authorization: Bearer $PAPERMILL_API_KEY" \
  -H "Content-Type: text/markdown" \
  -o report.pdf \
  --data-binary @- <<EOF
# Q3 Revenue Summary

Strong quarter overall, driven by add-on adoption.
EOF
python
import os
import requests

response = requests.post(
    "https://api.papermill.io/v2/pdf",
    params={"template_id": "papermill-simple-report"},
    headers={
        "Authorization": f"Bearer {os.environ['PAPERMILL_API_KEY']}",
        "Content-Type": "text/markdown",
    },
    data="# Q3 Revenue Summary\n\nStrong quarter overall.".encode("utf-8"),
)
response.raise_for_status()

with open("report.pdf", "wb") as f:
    f.write(response.content)
javascript
import fs from 'node:fs/promises'

const response = await fetch('https://api.papermill.io/v2/pdf?template_id=papermill-simple-report', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PAPERMILL_API_KEY}`,
    'Content-Type': 'text/markdown',
  },
  body: '# Q3 Revenue Summary\n\nStrong quarter overall.',
})

if (!response.ok) throw new Error(`${response.status} ${response.statusText}`)
await fs.writeFile('report.pdf', Buffer.from(await response.arrayBuffer()))

A payload should carry only the values that change per render — see Template & Payload for how merging works.