Gotenberg as an API

Gotenberg 8's own routes, hosted: point any Gotenberg client at one base URL with your API key. HTML, Markdown, web pages and Office files to PDF, plus merge, split and PDF/A. 1 credit per request.

Last updated

Engine Gotenberg 8.38, with Chromium and LibreOffice
Price 1 credit per request on every /forms route, whatever the page count; /health and /version are free
Limits 26 MB and 55 seconds per request
Not supported Webhooks, the downloadFrom field and the Factur-X route
Free tool Word to PDF, up to 4 MB, no account needed

Gotenberg turns HTML, Markdown, web pages and office documents into PDFs, with Chromium and LibreOffice inside, and merges, splits, flattens, watermarks, encrypts and converts PDFs to PDF/A or PDF/UA. This API runs Gotenberg 8.38 and serves its own routes under one base URL:

https://api.pagespool.com/v1/gotenberg

So POST /forms/chromium/convert/html becomes POST https://api.pagespool.com/v1/gotenberg/forms/chromium/convert/html, with the same form fields, the same Gotenberg-* headers (Gotenberg-Output-Filename, Gotenberg-Trace) and the same output.

What it costs

Every request to a /forms/... route costs 1 credit, whatever the page count or the output. GET /v1/gotenberg/health and GET /v1/gotenberg/version are free. A request that answers with an error status costs nothing.

A free account gets 100 credits a month and 10 more a day. Paid plans are on the pricing page, and one balance covers every engine on this site.

Limits

  • 26 MB per request. A larger body gets a 413 payload_too_large.
  • 55 seconds per request. A longer conversion gets a 504 engine_timeout. Split large jobs into several requests.
  • No webhooks and no downloadFrom. The answer always carries the result. A Gotenberg-Webhook-* header gets a 400 webhooks_unsupported, and a downloadFrom field a 400 download_from_unsupported.
  • Public URLs only. Chromium does not load pages or resources on private networks: /forms/chromium/convert/url with such a URL gets a 403.
  • No Factur-X. The /forms/pdfengines/factur-x route is not offered.

Gotenberg's own errors come back with its status and its message, as an RFC 9457 problem (application/problem+json) whose code is engine_rejected. When Gotenberg is not available, the answer is a 503 engine_unavailable with Retry-After: 30.

Your API key

Every /forms/... route needs an API key. Create one in your account after signing up, and send it in any of three ways:

  • the header X-API-Key: <key>;
  • the header Authorization: Bearer <key>;
  • HTTP Basic, with any user name and the key as the password (-u x:<key> in curl, or https://x:<key>@… in a client that only takes a URL).

Basic is how Gotenberg clients send credentials, so it is the form the examples below use. A missing or wrong key gets a 401.

Quickstart: curl

Convert an HTML file (Gotenberg needs it named index.html):

curl -u "x:$API_KEY" \
  -F files=@index.html \
  https://api.pagespool.com/v1/gotenberg/forms/chromium/convert/html \
  -o out.pdf

Convert a Word document with LibreOffice:

curl -u "x:$API_KEY" \
  -F files=@report.docx \
  https://api.pagespool.com/v1/gotenberg/forms/libreoffice/convert \
  -o report.pdf

Merge two PDFs:

curl -u "x:$API_KEY" \
  -F files=@a.pdf -F files=@b.pdf \
  https://api.pagespool.com/v1/gotenberg/forms/pdfengines/merge \
  -o merged.pdf

Quickstart: chromiumly (Node.js)

import { Chromiumly, HtmlConverter } from "chromiumly";

Chromiumly.configure({
  endpoint: "https://api.pagespool.com/v1/gotenberg",
  username: "x",
  password: process.env.API_KEY,
});

const pdf = await new HtmlConverter().convert({ html: "index.html" });

Quickstart: gotenberg-php

gotenberg-php builds a PSR-7 request, so the key goes on as a header:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium('https://api.pagespool.com/v1/gotenberg')
    ->pdf()
    ->html(Stream::path('index.html'))
    ->withHeader('Authorization', 'Basic ' . base64_encode('x:' . getenv('API_KEY')));

$filename = Gotenberg::save($request, __DIR__);

Quickstart: gotenberg-client (Python)

import os
from pathlib import Path

from gotenberg_client import GotenbergClient

with GotenbergClient(
    "https://api.pagespool.com/v1/gotenberg", auth=("x", os.environ["API_KEY"]), timeout=60
) as client:
    with client.chromium.html_to_pdf() as route:
        response = route.index(Path("index.html")).run()
        response.to_file(Path("out.pdf"))

MCP server

AI agents reach Gotenberg through its own MCP server:

https://api.pagespool.com/mcp/gotenberg/

It has two tools, html_to_pdf (Chromium) and office_to_pdf (LibreOffice). Each takes a file up to 4 MB, as base64 or as a public https link, costs 1 credit and needs an API key. The PDF comes back as a download link that works for one hour. The connect page shows how to add the server to a client.

Self-hosting or this API

Gotenberg is open source and runs anywhere as one Docker image, gotenberg/gotenberg. That image carries Chromium and LibreOffice, so it needs memory to match (ours runs with 2 GB), and keeping it safe on a network is your job: its flags that refuse private addresses, the body and time limits, the queue size and the updates.

Self-host when you convert many documents a day, need webhooks, or must keep documents inside your own network. Use this API when you want Gotenberg without running it: one API key and one credit balance, shared with the other engines on this site.

Try it without an account

The free Word to PDF tool converts a document up to 4 MB with the same LibreOffice route, in the browser.

Gotenberg is a trademark of its owner; pagespool is not affiliated.

FAQ

Does my Gotenberg client work with this API?
Yes, if it lets you set the base URL and HTTP Basic credentials. Point it at the API's /v1/gotenberg base URL, with any user name and your API key as the password. The routes and form fields are Gotenberg's own.
Can I use webhooks or downloadFrom?
No. Every request is answered synchronously with the result, so a Gotenberg-Webhook-* header gets a 400 webhooks_unsupported. Send the files in the form: a downloadFrom field gets a 400 download_from_unsupported.
What does a failed conversion cost?
Nothing. Every request that answers with an error status, Gotenberg's own errors included, gets its credit back.