PDFOven

HTML、Markdown、URL、またはHandlebarsテンプレートからPDFおよびPNG画像を生成します。無料のAPIキーで月100回のレンダリングが可能です。

ホスト型 MCP サーバー

npx add-mcp 'https://pdfoven.com/mcp'

Claude Code、Codex、Cursor などにインストールできます

ドキュメント

API documentation

Base URL: https://pdfoven.com. All requests use JSON and an API key from your dashboard (free signup). The whole API is described in the OpenAPI 3.1 spec.

Quickstart

  1. Create a free account; your API key is ready right away and set it as PDFOVEN_KEY.
  2. Run this. It uses the built-in invoice template, so it works with no setup:
curl https://pdfoven.com/v1/pdf \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template_id":"tpl_invoice","data":{"number":"INV-0001"}}' \
  -o invoice.pdf

The response body is the PDF (Content-Type: application/pdf), with headers X-Render-Ms (render time) and X-Usage-Remaining (renders left within your plan limit this month). Past the limit you're in the 10% grace buffer: X-Usage-Grace-Remaining counts the renders left before HTTP 429, and X-Usage-Notice says you're in the buffer and suggests upgrading. Errors come back as JSON, described under Errors.

Authentication

Send your key as a bearer token: Authorization: Bearer po_live_…. The X-API-Key header also works.

POST /v1/pdf

Renders a PDF. Provide exactly one source:

htmlAn HTML string. Fragments are wrapped in a document with sensible base styles.
markdownA Markdown string (GitHub-flavored).
urlA public http(s) URL to capture.
template + dataAn inline Handlebars template and the JSON to fill it with.
template_id + dataA template saved in your dashboard, or a built-in template such as tpl_invoice. If data is omitted, its sample data is used.

Optional fields:

cssExtra CSS appended to the document.
options.formatA4 (default), Letter, Legal, A3, A5, Tabloid
options.landscapeBoolean, default false.
options.marginUniform margin such as "0.5in", "12mm" or "20px".
options.print_backgroundPrint background colors and images. Default true.
options.header_template / footer_templateHTML for a repeating header/footer. Use <span class="pageNumber"></span> and <span class="totalPages"></span>. Requires a margin so it has room.
options.scale0.1 – 2.
wait_for_selectorWait for a CSS selector before rendering, for pages that draw charts with JavaScript.
timeout_ms1,000 – 60,000. Default 30,000.
response"binary" (default) returns the file. "base64" returns JSON { "data": "…", "content_type": "application/pdf", "bytes": 1234 }.
filenameSets the Content-Disposition filename.
curl https://pdfoven.com/v1/pdf \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"html":"<h1>Hello, PDF</h1>","options":{"format":"Letter","margin":"0.5in"}}' \
  --output hello.pdf

POST /v1/image

Takes the same sources as /v1/pdf and returns a PNG. Call /v1/image?type=jpeg for a JPEG instead. Image options in options: width, height, full_page, device_scale_factor (1–3) and quality (JPEG only).

For social share images, use a built-in 1200×630 card and send only the text: tpl_og_article, tpl_og_product or tpl_og_announcement. Long titles shrink to fit. See the fields under Built-in templates, or design one in the social image generator.

curl "https://pdfoven.com/v1/image" \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template_id":"tpl_og_article","data":{"site":"acme.dev","title":"Launch day","author":"Ada"}}' \
  --output og.png

POST /v1/screenshot

Screenshots a public web page. It's /v1/image with a url, plus options made for pages you don't control:

options.width / heightViewport size in pixels. Default 1280 × 800.
options.full_pageCapture the whole scrollable page.
options.color_scheme"light" (default) or "dark", for sites that follow the system theme.
options.hide_selectorsCSS selectors to hide first, such as cookie banners and chat widgets.
options.selectorCapture just the first element matching this selector.
options.delay_msWait 0–10,000 ms after loading, for animations.
options.device_scale_factor2 for retina-sharp images.
curl "https://pdfoven.com/v1/screenshot?type=jpeg" \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","options":{"width":1440,"full_page":true,"hide_selectors":["#cookie-banner"]}}' \
  --output page.jpg

PDF tools

These endpoints work on PDFs you already have. Send each file as JSON, either {"base64": "…"} or {"url": "https://…"}, with "password" if it's protected. Or upload it as multipart/form-data: the PDF in a file field (files for merge), and the other parameters as fields of the same name or as one JSON payload field.

  • Each call uses one render, except listing form fields, which is free. Failed calls don't count.
  • Files can be up to 50 MB each and 60 MB together, and up to 5,000 pages.
  • Results come back as the file, with X-Page-Count and the usage headers. "response": "base64" returns JSON with the file and the same details. Output is never password-protected.
  • Page selections look like "1-3,5,8-". last means the final page, and a range can run backwards ("last-1") to reverse the order.

POST /v1/pdf/merge

Joins 2–50 PDFs in the order given. Each file can take pages to pick and reorder its pages; one file with pages also works, for reordering a single PDF.

curl https://pdfoven.com/v1/pdf/merge \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -F files=@cover.pdf -F files=@report.pdf \
  -o merged.pdf
{
  "files": [
    { "url": "https://example.com/cover.pdf" },
    { "base64": "JVBERi0x…", "pages": "2-last" }
  ],
  "filename": "q3-report"
}

POST /v1/pdf/split

Send exactly one of:

pagesExtract these pages into one PDF, e.g. "1,3-4".
rangesOne PDF per range, e.g. ["1-2","3-last"], returned as a zip.
everySplit into parts of this many pages, returned as a zip. X-File-Count says how many.
When ranges or every produces a single part, you get that PDF instead of a zip; check Content-Type.
curl https://pdfoven.com/v1/pdf/split \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -F file=@statement.pdf -F every=1 \
  -o pages.zip

POST /v1/pdf/compress

Makes a PDF smaller by recompressing and downscaling large photos, compressing uncompressed content and dropping unused data. Text and vector graphics stay sharp. level is low (closest to the original), medium (default) or high (smallest). remove_metadata also strips the title, author and XMP metadata.

The response headers X-Original-Bytes, X-Compressed-Bytes and X-Saved-Percent report the result. If the file can't be made smaller you get it back unchanged with X-Already-Optimized: true.

curl https://pdfoven.com/v1/pdf/compress \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -F file=@scan.pdf -F level=high \
  -o smaller.pdf

POST /v1/pdf/watermark

Stamps text (up to 5 lines, Latin characters) or an image (PNG or JPEG) on every page, or on pages.

positioncenter (default, diagonal), tile (repeated across the page), or a corner or edge: top-left, top-center, top-right, bottom-left, bottom-center, bottom-right.
opacity0.01–1. Default 0.2 for text, 0.3 for images.
colorHex text color. Default #6b7280.
rotationDegrees. Center and tile follow the page diagonal unless set.
font_size / scaleText size in points, or a size multiplier (0.1–3) when the size is automatic.
marginDistance from the edge for corner positions, in points. Default 36.

Rotated pages are handled, so the watermark always reads upright.

curl https://pdfoven.com/v1/pdf/watermark \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"file":{"url":"https://example.com/contract.pdf"},"text":"CONFIDENTIAL","position":"tile","opacity":0.12}' \
  -o watermarked.pdf

Fill PDF forms

POST /v1/pdf/form/fields lists a form's fields: name, a readable label, type (text, checkbox, radio, dropdown, option_list …), current value, options, max_length and the pages it's on. It's free.

POST /v1/pdf/form/fill fills fields by name. Text takes strings or numbers, checkboxes take true / false, and radio and dropdown values must match an option (case doesn't matter). flatten: true makes the result read-only. A misspelled field name is an error that suggests the right one; send strict: false to skip unknown names instead.

curl https://pdfoven.com/v1/pdf/form/fill \
  -H "Authorization: Bearer $PDFOVEN_KEY" \
  -F file=@w9.pdf \
  -F 'fields={"name":"Ada Lovelace","agree":true,"state":"OR"}' \
  -F flatten=true \
  -o filled.pdf

Templates

Templates are HTML with Handlebars placeholders, plus optional CSS and default page options. Create them in the dashboard with a live preview, or via the API. Markdown templates are also supported.

Built-in templates

Every account can render these without saving anything; they don't count toward your template limit. Send any subset of fields in data and the rest come from the sample data, so {"template_id":"tpl_invoice","data":{"number":"INV-2041"}} works as-is with a new key.

tpl_invoiceClean invoice with line items, tax and totals.
tpl_receiptCompact payment receipt for e-commerce and SaaS.
tpl_certificateLandscape certificate of completion.
tpl_reportReadable multi-page report written in Markdown.
tpl_paystubEarnings statement with hours, rates, deductions and net pay.
tpl_packing_slipOrder packing slip with ship-to address, SKUs and quantities, no prices.
tpl_og_articleOpen Graph image for a blog post or page: site name, title, subtitle, author and date. Light or dark. Render with /v1/image (1200×630). Fields: site, eyebrow, title, subtitle, author, date, accent, dark.
tpl_og_productProduct or listing card: brand, product name, tagline, price, a badge and a product image. Render with /v1/image (1200×630). Fields: brand, name, tagline, price, badge, accent.
tpl_og_announcementLaunch or event announcement on a gradient: label, headline, detail line and a call to action. Render with /v1/image (1200×630). Fields: label, headline, detail, site, cta, color_from, color_to.

To customize one, open it in the template editor as a starter and save your own copy.

Built-in helpers:

{{formatCurrency amount "EUR"}}Formats money. Defaults to USD.
{{formatNumber value 2}}Fixed decimals.
{{formatDate issued_at "medium"}}short / medium / long / full.
{{sum items "amount"}}Sums a field across an array.
{{lineTotal items "qty" "price"}}Sum of qty × price across an array.
{{multiply a b}}, {{add a b}}Arithmetic.
{{#if (eq status "paid")}}Equality checks.
{{upper text}}Uppercase.

GET /v1/templates

Lists your templates.

POST /v1/templates

{
  "name": "Invoice",
  "engine": "handlebars",
  "content": "<h1>Invoice {{number}}</h1>",
  "css": "h1 { color: #c8155f }",
  "sample_data": { "number": "INV-1" },
  "page_options": { "format": "Letter", "margin": "0.5in" }
}

GET /v1/usage

Returns your plan, limit and renders used this calendar month (UTC). grace_limit is the limit plus the 10% grace buffer every plan gets; once used passes limit, in_grace_buffer is true and notice suggests upgrading.

{ "plan": "starter", "period": "2026-10", "used": 2050, "limit": 2000, "grace_limit": 2200,
  "remaining": 0, "grace_remaining": 150, "in_grace_buffer": true,
  "notice": "You're in the 10% grace buffer: 2,050 of 2,000 renders used on the Starter plan, 150 left before HTTP 429. Upgrade at https://pdfoven.com/pricing to keep rendering." }

Errors

Errors are JSON: { "error": { "code": "quota_exceeded", "message": "…" } }

400invalid_request — the body failed validation.
401unauthorized — missing or invalid API key.
404template_not_found
400invalid_pages, unknown_field or invalid_field_value — the message says which page or field.
413too_large — a file is over the size limit, or a PDF is too complex to process.
422template_error or render_failed (blocked URL, timeout, HTTP error).
422invalid_pdf, encrypted_pdf (send password), wrong_password, too_many_pages, no_form, invalid_image, unsupported_text or fetch_failed.
429quota_exceeded — monthly limit plus the 10% grace buffer used up. Failed renders don't count.
503busy — too many PDF jobs queued. Retry after a few seconds.

MCP server for AI agents

PDFOven speaks the Model Context Protocol over Streamable HTTP at https://pdfoven.com/mcp. Agents get render_pdf and render_image (including screenshots and social cards); merge_pdfs, split_pdf, compress_pdf, watermark_pdf, list_pdf_form_fields and fill_pdf_form for existing PDFs; and list_templates, get_template, create_template, update_template and delete_template to manage saved templates. Files come back as embedded resources.

Claude Code:

claude mcp add --transport http pdfoven https://pdfoven.com/mcp \
  --header "Authorization: Bearer $PDFOVEN_KEY"

Cursor / other clients (mcp.json):

{
  "mcpServers": {
    "pdfoven": {
      "url": "https://pdfoven.com/mcp",
      "headers": { "Authorization": "Bearer po_live_..." }
    }
  }
}

Limits

  • Every render counts once, whatever the page count or file size.
  • Request bodies up to 6 MB (HTML up to 5 MB); renders time out after 30 seconds by default, up to 60 seconds with timeout_ms; each resource a page fetches is capped at 50 MB.
  • PDF tools take files up to 50 MB each and 60 MB per request, up to 5,000 pages each.
  • Renders keep working through a 10% grace buffer past your plan's monthly limit (110 on Free), then return 429 until the 1st (UTC).
  • URL rendering is limited to public addresses.
  • Rendered and uploaded files are processed in memory and never stored.

Support

Questions or a render that looks wrong? Email support@pdfoven.com with the request you sent and the error code you got back.