Generate PDFs through the REST API
Use any programming language that can make an HTTP request. The API uses standard REST, so you do not need an SDK.
Quick start
Send your first PDF request.
# Simple HTML to PDF conversion
curl -X POST https://api.pdf-mcp.io/htmlToPdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Hello World</h1><p>Your first PDF</p>",
"css": "@page { size: A4; margin: 20mm; }",
"filename": "document.pdf"
}' \
--output document.pdf The API accepts a JSON request and returns the generated PDF.
- Send HTML with CSS styling
- Configure page size and margins
- Receive PDF binary directly
Works with any language
Any HTTP client can send a PDF generation request.
JavaScript / Node.js
Generate PDFs server-side with native fetch or axios
- Native fetch API support
- Stream responses for large PDFs
- Ready for Express or Fastify middleware
- TypeScript definitions available
Python
Use the requests library with Django, Flask, or FastAPI
- requests/httpx libraries
- Async support with aiohttp
- Django/Flask integrations
- Type hints included
Any language
The standard REST API works with any HTTP client
- Go, Rust, Java, PHP, Ruby
- cURL for shell scripts
- OpenAPI spec available
- No SDK required
What you can build
Common patterns for direct API integrations.
Render invoices, receipts, or reports without running a PDF renderer in your own backend.
Build HTML with a templating engine such as Handlebars, Jinja2, or EJS, then convert it to a PDF. You keep full control of the document design.
Process a set of documents by looping through your data, sending concurrent requests, and handling each result in your application.
Send HTML, plain text, or images to a dedicated endpoint and receive a PDF.
Use dedicated endpoints to merge PDFs, extract pages or text, crop pages, or fill forms.
Store generated PDFs in AWS S3 or bring your own bucket (BYOB) without handling an intermediate file. Support for more storage providers is planned.
API design
Predictable endpoints, authentication, rate limits, and errors.
REST endpoints
Endpoints use standard HTTP methods and status codes, with binary PDFs or JSON metadata in the response.
Authentication
Authenticated endpoints accept one API key as a bearer token.
Storage modes
Return the PDF directly, keep it in managed storage, or send it to your S3 bucket.
Error handling
Errors include messages and codes that you can inspect during development.
How it works
Prepare the HTML and send one authenticated request.
Get your API key
Create an account to receive an API key and a coupon for 100 free credits.
Build your HTML
Create the HTML and CSS with any templating engine you prefer.
Make the API call
Send your HTML and options in a POST request to /htmlToPdf.
Receive the PDF
Receive the PDF directly, get a stored-file link, or send the file to your own S3 bucket.
Code examples
Examples for Node.js, Python, and Go.
Node.js / JavaScript
// Node.js with native fetch
const response = await fetch('https://api.pdf-mcp.io/htmlToPdf', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDF_MCP_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: `
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.header { color: #333; border-bottom: 2px solid #e11d48; }
</style>
</head>
<body>
<h1 class="header">Invoice #${invoiceId}</h1>
<p>Amount: $${amount}</p>
</body>
</html>
`,
css: '@page { size: A4; margin: 20mm; }',
filename: `invoice-${invoiceId}.pdf`
})
});
const pdf = await response.arrayBuffer();
fs.writeFileSync('invoice.pdf', Buffer.from(pdf)); Python
# Python with requests library
import requests
import os
def generate_pdf(html: str, filename: str, css: str = "") -> bytes:
"""Generate PDF from HTML using pdf-mcp API"""
response = requests.post(
"https://api.pdf-mcp.io/htmlToPdf",
headers={
"Authorization": f"Bearer {os.environ['PDF_MCP_API_KEY']}",
"Content-Type": "application/json"
},
json={
"html": html,
"css": css or "@page { size: A4; margin: 20mm; }",
"filename": filename
}
)
response.raise_for_status()
with open(filename, 'wb') as f:
f.write(response.content)
return response.content
# Usage with Jinja2 template
from jinja2 import Template
template = Template(open('invoice.html').read())
html = template.render(customer=customer, items=items)
generate_pdf(html, 'invoice.pdf') Go
// Go with net/http
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
)
type PDFRequest struct {
HTML string `json:"html"`
CSS string `json:"css,omitempty"`
Filename string `json:"filename,omitempty"`
}
func generatePDF(html string) ([]byte, error) {
payload := PDFRequest{
HTML: html,
CSS: "@page { size: A4; margin: 20mm; }",
Filename: "document.pdf",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://api.pdf-mcp.io/htmlToPdf",
bytes.NewBuffer(body))
req.Header.Set("Authorization",
"Bearer "+os.Getenv("PDF_MCP_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
} The API documentation has advanced examples for PHP, Ruby, Java, Rust, C#, and other languages.
Why use the API directly?
- No SDK dependency There is no SDK to install or maintain
- Control the response Stream, buffer, or save the result
- Standard HTTP debugging Inspect familiar requests, status codes, and responses
- Clear failure responses Handle HTTP status codes and error details in your client
[12:45:23] POST /htmlToPdf
[12:45:23] HEADERS Authorization: Bearer ***
[12:45:23] BODY { html: "...", css: "...", filename: "..." }
[12:45:24] STATUS 200 OK
[12:45:24] CONTENT-TYPE application/pdf
[12:45:24] RECEIVED 245.3 KB
Available endpoints
Generate, combine, inspect, extract, and convert PDFs.
Convert HTML to PDF with full CSS support
Combine multiple PDF files into one
Extract text content from PDF documents
Extract specific pages from a PDF
Convert PDF pages to PNG or JPEG images
Get the page count of a PDF document
Make your first request
Create an API key and call the REST endpoint directly. You do not need an SDK or local server.