← All posts

How to add PDF generation to your app with AI

Tell your coding agent to add PDF invoices to your app. It wires kove's hosted API in for you. You review and ship. Nothing to host or scale.

ai-agentspdfapihow-to

Adding PDF generation to an app used to be a project. You picked a library, fought with a headless browser, wrote CSS for page breaks, and kept a render server alive forever. With a hosted API and a coding agent, it is now a single task you hand off.

kove is a hosted document API. We run all the rendering. You run nothing. The fastest way to add it is to let your coding agent do the integration: you describe what you want, the agent wires kove’s API into your code, and you review the change before you ship.

Tell your agent what you want

Open your coding agent in your project and ask for the feature in plain words:

Add PDF invoices to my checkout. After a payment succeeds, generate the invoice with kove and email it to the customer.

The agent reads your code, finds where payments succeed, and writes the integration. It knows how to call kove because kove ships AI-friendly docs: an llms.txt index, an OpenAPI spec, and a simple JSON document model. The agent does not guess at the API. It reads the spec and writes the correct call.

You barely notice there is an external provider. You asked for invoices, you got invoices, and the wiring sits in your codebase like any other code you can read and own.

What the agent actually writes

Under the hood, kove takes a JSON description of the document. You list the page settings, an optional header and footer, and a body made of blocks. Each block is one idea: a heading, some text, a table, the totals.

{
"page": { "size": "A4" },
"footer": { "pageNumbers": "Page {page} of {pages}" },
"body": [
{ "type": "heading", "text": "Invoice F-001" },
{ "type": "fields", "items": [
{ "label": "Bill to", "value": "Acme Inc." },
{ "label": "Date", "value": "2026-01-14" }
] },
{ "type": "table",
"columns": ["Item", "Qty", "Price"],
"rows": [
["Design work", "12", "$1,200.00"],
["Hosting", "1", "$84.00"]
] },
{ "type": "totals", "lines": [
{ "label": "Total", "value": "$1,284.00" }
] }
]
}

The agent maps your real data, the customer, the line items, the totals, into this shape, then sends it to the API with a Bearer key:

Terminal window
curl -X POST https://api.kove.dev/v1/documents \
-H "Authorization: Bearer $KOVE_API_KEY" \
-H "Content-Type: application/json" \
-d @invoice.json \
-o invoice.pdf

A finished PDF comes back, ready to store or email. There is no headless browser in your deploy and no render server to keep alive. The document primitives cover most real documents: heading, text, fields, table, totals, section, divider, spacer, pageBreak, image, and signature, plus page, header, and footer for the layout.

Review, then ship

Because the agent writes plain code against a documented API, you can read the diff like any pull request. Check where the call happens, confirm the data mapping, make sure the key comes from an environment variable. The integration is yours to own, not a black box.

Want to see the output before you wire anything? Render a sample document locally with the CLI, free and with no account:

Terminal window
npx kove validate invoice.json
npx kove render invoice.json -o invoice.pdf

Validate first so a small mistake fails fast and cheap, then render. This is the quick way to feel the layout while you build. The same JSON goes to the hosted API later with no changes.

Why this beats letting the agent draw the PDF

When an agent builds a PDF directly, it has to manage a browser, write CSS for page breaks, repeat table headers by hand, and add page numbers. Every one of those is a place to fail, and the failures show up on page two where nobody is looking until a customer complains.

By describing the document and letting the hosted API render it, the agent does the part it is good at, mapping your data, and skips the part it is bad at. Headers repeat, totals stay with their table, page numbers appear, and the type looks like a person set it. Better still, none of that rendering code lives in your stack. It lives in ours, and we keep it working.

Where MCP and the CLI fit

The API is the main way in, because most apps generate documents from their backend. Two other surfaces use the same document model:

  • MCP, for runtime agents. If your product is itself an agent, add kove once with claude mcp add kove -- npx @kove/mcp and it gets render_document, validate_document, and friends as native tools.
  • CLI, for local and CI. npx kove render makes PDFs on a machine you control, free and unlimited, with no account.

Pick the surface that matches where the work happens. The document is identical in every case, so the result is too.

Start by telling your agent to add document generation to your app. It reads the docs, writes the call, and you ship. The infrastructure stays our problem.