Generate a PDF in n8n
n8n has no PDF node of its own. The built-in HTTP Request node is enough: post the Markdown, HTML or invoice data to the API and the node hands the PDF to the next step as a binary field, ready for Gmail, Google Drive, Slack, S3 or a webhook response. Works on n8n Cloud and self-hosted alike. Two importable workflows are below; the requests they make were run against the live API before this page went up.
Setup: one credential
Create a free API key at /signup. In n8n open Credentials → Add credential → Header Auth and set Name to Authorization and Value to Bearer dp_your_key. Call the credential PaperType API; the workflows below reference it by that name. The key never appears in the workflow JSON, so you can share or export the workflow safely.
Markdown to PDF with the HTTP Request node
Import markdown-to-pdf.json (Workflow menu → Import from URL, or paste the JSON onto the canvas), pick the credential in the Render PDF node and run it. It is three nodes: a manual trigger, a Set node holding title and markdown (replace it with whatever produces your text: a database row, a form, an AI node), and the HTTP Request node configured like this:
- Method POST, URL
https://papertype.dev/v1/pdf. - Authentication Generic Credential Type → Header Auth →
PaperType API. - Send Body on, Body Content Type JSON, Specify Body Using JSON, with this expression as the body (building the body with
JSON.stringifykeeps newlines and quotes in your Markdown correctly escaped):
{{ JSON.stringify({
markdown: $json.markdown,
title: $json.title,
theme: 'clean',
toc: true,
page_numbers: true
}) }}- Options → Response → Response Format File, Put Output in Field
data.
The node's output item carries the PDF in the binary field data with the right MIME type and a filename. For HTML instead of Markdown, send html: $json.html; the other options (theme, page_size, cover, footer, css) are the same and listed in the API docs.
Invoice PDF from a webhook
invoice-webhook.json turns n8n into a small invoice service: a Webhook node receives the invoice as JSON, the HTTP Request node renders it with the hosted invoice template, and a Respond to Webhook node (Respond With Binary File) returns the PDF to the caller. The request body in the HTTP Request node is:
{{ JSON.stringify({
template: 'invoice',
data: $json.body,
page_size: 'Letter',
filename: $json.body.number + '.pdf'
}) }}Test it from a terminal once the workflow is active (use the test URL shown on the Webhook node while you are still in the editor):
curl -X POST https://your-n8n.example.com/webhook/invoice \
-H 'Content-Type: application/json' \
-d '{"number":"INV-1042","date":"2026-10-21","due_date":"2026-11-20","currency":"USD",
"from":{"name":"Northwind Studio","address_lines":["12 Example Road","Springfield"]},
"to":{"name":"Acme Client Ltd","address_lines":["1 Sample Street","Shelbyville"]},
"items":[{"description":"Design, October","quantity":10,"unit_price":120}],
"tax_rate":8.25,"tax_label":"Sales tax"}' \
-o INV-1042.pdfA missing required field (for example date) comes back as a 422 whose message names the field; the certificate and report templates work the same way with their own fields.
Send the PDF somewhere
Every n8n node that accepts a file reads it from a binary field, so connect the HTTP Request node directly to the destination and point it at data:
- Gmail / Send Email: Attachments → field
data. - Google Drive, Dropbox, S3, Nextcloud: Upload with Input Data Field Name
data. - Slack, Telegram, Discord: send a file from binary field
data. - Write Binary File (self-hosted) to keep a copy on disk.
To rename the file, use the Edit Fields or Rename Keys node, or set filename in the request as the invoice workflow does.
Limits that matter in n8n
- Images. The renderer has no network access. Images, fonts and stylesheets at external URLs are never fetched; inline them as
data:URIs. A request that references an external URL fails with a 422 that names the URL, rather than silently dropping the asset. In n8n, run the image through Extract from File → Move File to Base64 String and build thedata:image/png;base64,…URI in an expression. - 2 MB of source per request, 300 pages per document, 2 concurrent renders per account. Larger inputs return
413; split long reports into several documents. - Quota. Free-plan output carries a small
papertype.devfooter mark. Paid plans (from $9/month) do not. A workflow that fires on every webhook call can use the free plan's 50 documents quickly; the response headersX-Quota-UsedandX-Quota-Limitare available under Response → Include Response Headers and Status. - Errors. Set the HTTP Request node's On Error to Continue (using error output) to route a 401, 413, 422 or 429 to an error branch instead of stopping the workflow; the JSON error body says what went wrong. Failed renders are not counted against the quota.
- No JavaScript is executed. Send the final HTML; anything a script would have drawn or filled in will not appear.
Questions
Is there a PaperType node for n8n instead of the HTTP Request node?
A community node (`n8n-nodes-papertype`, operations Render PDF and Get Account, with a credential type that tests the key) is finished and awaits publication on npm; this page will show the install line as soon as it is installable from Settings → Community Nodes. The HTTP Request setup above is exactly what the node does internally and keeps working either way.
Does this work on n8n Cloud?
Yes. The HTTP Request, Set, Webhook and Respond to Webhook nodes are built in, so nothing needs to be installed. The same workflow JSON imports into self-hosted n8n.
Can I render HTML produced by an AI node or a template?
Yes. Put the HTML in a field and send `html: $json.html` instead of `markdown`. Inline any images as data: URIs and any custom font with an @font-face rule whose src is a data: URI; nothing is fetched from the network.
Is my document stored?
No. The API returns the PDF and keeps neither the source nor the output. Only a per-account usage count and the page count of each render are logged.
Why does the preview in n8n show a download link instead of the PDF?
n8n displays binary output as a file item with a View or Download button; that is the PDF. Open it to check the result, then connect the node to wherever the file should go.
Related
Free previews carry a watermark and are deleted after 24 hours. Free API output carries a footer mark. The renderer runs no JavaScript and never fetches external URLs. Privacy · Terms · Refunds