The endpoint
POST https://a2pdf.com/convert
Accepts multipart/form-data (for file uploads) or application/x-www-form-urlencoded (for text and URLs). One conversion per request.
Quick recipes
Markdown → PDF
curl -X POST https://a2pdf.com/convert \ -F "text=# Hello Some **markdown**." \ -F "format=md" \ -F "theme=clean" \ -o output.pdf
HTML → PDF (normalize)
curl -X POST https://a2pdf.com/convert \ -F "text=<h1>Hello</h1><p>World</p>" \ -F "format=html" \ -F "theme=business" \ -o output.pdf
HTML → PDF (preserve source styling)
curl -X POST https://a2pdf.com/convert \ -F "text=<html>...</html>" \ -F "format=html" \ -F "preserve=1" \ -o output.pdf
DOCX → PDF
curl -X POST https://a2pdf.com/convert \ -F "[email protected]" \ -F "theme=business" \ -F "paper_size=a4" \ -o report.pdf
Image → PDF
curl -X POST https://a2pdf.com/convert \ -F "[email protected]" \ -F "paper_size=letter" \ -o photo.pdf
URL → PDF
curl -X POST https://a2pdf.com/convert \ -F "url=https://example.com/article" \ -F "preserve=1" \ -o article.pdf
Request fields
| Field | Type | Description |
|---|---|---|
file | multipart file | DOCX, MD, HTML, TXT, JPG, PNG. Required if not using text or url. |
text | string | Pasted content. Used instead of file. |
url | string | URL to fetch. Used instead of file or text. |
format | string | md, html, txt, docx, jpg, png, url, auto. Default: auto. |
theme | string | clean, academic, business, dark. Default: clean. |
paper_size | string | a4, letter, legal. Defaults from Accept-Language. |
preserve | boolean (1/0) | For HTML and URL only. Default: 0. |
filename | string | Used for the download filename. Default: document. |
Response modes
Default (no Accept header or anything other than application/json): the PDF bytes are returned inline with Content-Type: application/pdf and a Content-Disposition attachment header. Good for direct download.
With Accept: application/json: the PDF is staged on the server and the response is a small JSON object:
{
"download_id": "abc...",
"download_url": "/download/abc...",
"bytes": 123456,
"duration_ms": 1340
}
The download_url is single-use and expires after 10 minutes. Good for browser-side flows that need the size or duration first.
Status codes
200— success, body is the PDF (or JSON, see above).400— bad input (no file/text/url; invalid URL; conversion failed). Body has the message.429— rate limit hit (60 requests/hour per IP).503— server is busy (too many concurrent conversions). Try again in a few seconds.
Health check
curl https://a2pdf.com/health
# {"status":"healthy","service":"a2pdf","timestamp":"...","uptime_sec":12345,...}
For agents
If you'd rather call this from an AI assistant, see the MCP server — same functionality, JSON-RPC over MCP.