Answer: POST /api/v1/tools/html-to-pdf takes JSON with your HTML and returns a job envelope whose output_files[0].url is the PDF; one credit. Send a data object and the {{ }} placeholders, for loops and if blocks in the HTML are filled before rendering — strict mode, on by default, refuses a template with a missing variable and names it. The v2 route, POST /api/v2/tools/html-to-pdf, adds running headers and footers, page numbers, uploaded fonts and an explicit engine choice.
v1: a template and its data
The v1 route reads html, data, strict and literal_mode from the JSON body. Templating is sandboxed Jinja2 over data. A template with variables but no data is a 422 template_syntax_without_data; a variable data does not supply is a 422 missing_template_variables listing the names. Set literal_mode: true to print braces as text.
curl -X POST https://www.ashdocs.com/api/v1/tools/html-to-pdf \
-H "X-API-Key: ash_test_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "html": "<h1>Invoice {{ number }}</h1>{% for l in lines %}<p>{{ l.desc }}</p>{% endfor %}",
"data": { "number": "INV-0041", "lines": [ { "desc": "Design" } ] } }'v2: render control
The v2 route reads the body keys and the three options keys in the table below. It fills data only on deployments with v2 templating enabled; elsewhere a template sent to v2 renders with its braces as text, so send templates to v1 unless you have confirmed otherwise. The engine row gives the size rule auto uses to choose between WeasyPrint and Chromium.
curl -X POST https://www.ashdocs.com/api/v2/tools/html-to-pdf \
-H "X-API-Key: ash_test_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "html": "<h1>Report</h1>", "header_html": "<div>ACME</div>",
"page_numbers": { "start": 1 }, "options": { "margin_mm": 15 } }'Options
Generated from the backend source.
| Sent in | Key | What it does |
|---|---|---|
| v1 + v2 body | html | The HTML to render. Required. |
| v1 body | data | Object of template variables. {{ }}, {% for %} and {% if %} in the HTML are filled from it (sandboxed Jinja2) before rendering. Omit it and the HTML renders as sent. |
| v1 body | strict | Default true. A variable the template uses but data does not supply returns 422 missing_template_variables listing the names, instead of rendering a blank. |
| v1 body | literal_mode | true outputs the HTML exactly as sent: braces are text, not template syntax, and no data is needed. |
| v1 response | 422 template_syntax_without_data | The HTML contains template variables but no data was sent. Send data, or set literal_mode: true. |
| v1 response | 422 missing_template_variables | strict is on and these variables (listed in missing) are not in data. |
| v2 body | header_html / footer_html | HTML repeated at the top / bottom of every page. |
| v2 body | page_numbers | Object that adds a page-number footer when footer_html is not given; start sets the first number. |
| v2 body | engine | auto (default), weasyprint or chrome. auto renders with WeasyPrint below 512,000 bytes of HTML and with Chromium at or above it; an explicit value always wins. |
| v2 body | wait_for / wait_until | Chromium only: wait for an element (wait_for) or a load state (wait_until, default load) before printing. |
| v2 body | pdfa | Request PDF/A output at the given level. |
| v2 body | fonts | Ids of fonts you uploaded as assets; they are injected as @font-face before rendering. |
| v2 body | diagnostics | true adds render diagnostics (overflowing elements, blocked resources, warnings) to the response. |
| v2 body | dry_run | true checks the render without producing a billable job. |
| v2 body | preview | true returns a preview of the first page as well. |
| v2 options | options.margin_mm | Page margin in millimetres. Default 10. |
| v2 options | options.title | Document title written into the PDF (WeasyPrint). |
| v2 options | options.tagged | true produces a tagged (PDF/UA-1) file, which forces WeasyPrint; tagged with engine: chrome is a 400. Returns 404 tagged_not_available on deployments without PDF/UA output. |
Frequently asked questions
Why did my PDF print {{ name }} literally?
literal_mode was true, or the request went to the v2 route on a deployment without v2 templating. Send the template to /api/v1/tools/html-to-pdf with a data object.
What does 422 missing_template_variables mean?
strict is on (the default) and the template uses variables that data does not contain; the response lists them in missing. Supply them, or send strict: false to render them empty.
How much does a render cost?
One credit on either route.