Inkspan › Guides › How to generate a PDF from HTML in Next.js
Call the Inkspan /v1/generate/html endpoint from Next.js to generate a PDF from HTML — no headless browser,
font stack, or rendering infrastructure in your deploy. Keep your API key in the environment and POST.
Run this in a Route Handler rather than a Server Component — you need to stream a binary response, and the key must stay server-side. Set INKSPAN_KEY in your environment; a NEXT_PUBLIC_ prefix would ship it to the browser.
// app/api/pdf/route.ts
export async function POST() {
const res = await fetch('https://api.inkspan.dev/v1/generate/html', {
method: 'POST',
headers: {
'X-API-Key': process.env.INKSPAN_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({"html": "<h1>Invoice</h1>"}),
});
if (!res.ok) return new Response(await res.text(), { status: res.status });
return new Response(await res.arrayBuffer(), {
headers: { 'Content-Type': 'application/pdf' },
});
}
| Name | Type | Required | Description |
|---|---|---|---|
html | string | yes | The HTML document or fragment to render. |
filename | string | no | Filename in the response's Content-Disposition. Defaults to document.pdf. |
Returns a PDF as a binary stream with Content-Type: application/pdf and Content-Disposition: attachment; filename=document.pdf. Write the response body straight to disk — do not parse it as JSON.
Route Handlers on Vercel have an execution time limit. For large documents, generate in a background job and return a URL rather than blocking the request.
https:// URLs, or inline them as data: URIs.@page { size: A4; margin: 18mm; } in your HTML to control them.file:// URLs are rejected. Host assets publicly or inline them.| Status | Meaning | Fix |
|---|---|---|
401 | Invalid or missing API key | Send your key in the X-API-Key header. |
402 | Monthly quota exceeded | The response reports used/quota. Upgrade at inkspan.dev/#pricing. |
422 | Missing or invalid parameter | Check required fields in the table above — the body names the offending field. |
Failed requests do not count against your quota; only successful ones are metered.
Get a free API key →Same operation in cURL · Python · Node.js · Other frameworks: Django · Laravel · Ruby on Rails · PHP · All guides