Generate PDF invoices and receipts from your app’s own URLs
Generate an invoice PDF from the URL your app already serves, with the customer’s data, your styles and your locale. Billing pages, order receipts, monthly statements and signed quotes all start as HTML behind a login. Forward the session so the browser is logged in, strip the app chrome with CSS, and get a hosted PDF back.
A second invoice template for PDF is a second source of bugs
The invoice exists twice in most codebases: once as the HTML page the customer sees, and once as a PDF template written for a rendering library. The second copy needs its own layout code, its own fonts and its own tests, and it drifts the moment someone adds a tax line or a new currency to the first.
The usual escape routes do not hold either. Asking customers to print from the browser gives you their margins, their headers and the sidebar on every page. Running your own headless Chrome works until the login flow changes, the instance leaks memory, or month-end sends every customer to the download button at once.
The PDF API prints any URL with a real browser. Send the session cookie or token as an x-api-header-* request header and Microlink forwards it to the target page, so the invoice loads as that user. Hide the sidebar and the buttons with injected CSS, pick the paper with the PDF options, and name the file. The page stays the single source of truth.
How to generate an invoice PDF from an authenticated URL
Three options do the work: a forwarded header for authentication, a CSS rule for the chrome, and the PDF options for paper and filename. The private pages guide for PDFs covers the header patterns in depth.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { url } = await microlink.pdf('https://app.example.com/invoices/42', {
headers: {
'x-api-header-cookie': `session=${process.env.SESSION_COOKIE}`
},
styles: ['nav, aside, .actions { display: none !important }'],
filename: 'invoice-42.pdf'
})The SDK sends the cookie as a real HTTP header, never in the URL. Microlink strips the x-api-header- prefix and forwards it, the CSS hides the app chrome, and url points to the hosted PDF.
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { url, size_pretty: size } = await microlink.pdf(
'https://app.example.com/invoices/42',
{
format: 'A4',
margin: { top: '12mm', bottom: '16mm', left: '10mm', right: '10mm' },
headers: {
'x-api-header-cookie': `session=${process.env.SESSION_COOKIE}`
}
}
)A4 is the default format; switch to Letter for US customers. The response also carries the file size, which is handy for email attachments. The paper size and margins recipe lists every layout option.
curl -G https://pro.microlink.io \
-d url=https://app.example.com/invoices/42 \
-d pdf=true \
-d meta=false \
-d filename=invoice-42.pdf \
-H 'x-api-key: $MICROLINK_API_KEY' \
-H 'x-api-header-cookie: session=abc123'Credentials stay in HTTP headers and the query string only carries public options. meta=false skips metadata extraction, the biggest speedup for PDF-only requests. Authenticated requests go to pro.microlink.io with your API key.
- pdf Turns on PDF generation; the response carries the hosted document URL, type and size.
- headers Forwards HTTP headers to the target page; send secrets as x-api-header-* request headers. Pro plans.
- styles Injects inline CSS or a stylesheet URL to hide navigation, sidebars and buttons before printing.
- filename Names the generated file for downloads and archives. Pro plans.
- pdf.format A4 by default; Letter, Legal, Tabloid, Ledger and A0 to A6 are available.
- pdf.margin One value for all sides or an object per side, in px, in, cm or mm. Default 0.35cm.
PDF generation renders with the print media type by default, so a print stylesheet in your app applies automatically. Set mediaType to screen if you want the on-screen layout instead.
Why print the invoice page instead of templating a PDF
The invoice page is already tested, styled and localized. Reusing it removes a whole class of drift, and the headers feature keeps the login out of your automation code.
A print stylesheet in your app, applied automatically because PDFs render with the print media type, is usually all the customization you need.
Keep these calls on your backend. Every request runs in its own isolated browser, so one customer’s session never meets another’s.
When not to: treat the hosted URL as delivery, not as your system of record. For invoices you must retain for years, download the file and store it yourself, and see PDF download links for the delivery side.
FAQ
How do I generate a PDF of an invoice page that requires login?
How do I remove the app navigation from the invoice PDF?
Can I name the invoice PDF file that customers download?
How long does a generated invoice PDF stay available?
Is my invoice PDF rendered in a browser shared with other requests?
Solve the next problem with the same API
PDF download links and previews
PDFs in bulk
Paper size, margins and orientation
Clean PDFs without ads or banners
PDFs of JavaScript-rendered pages
Screenshots behind a login
Ready to generate invoice PDFs?
Print the invoice page you already render, with the session forwarded and the chrome removed. Get a Pro key and ship downloadable invoices this week.