Skip to content

API Reference

Render a PDF — POST /v1/render

Renders an HTML document to PDF and returns the PDF bytes directly in the response body.

Request

Content-Type: application/json. The body has the following shape:

{
  "html": "<html><body><h1>Invoice #1024</h1></body></html>",
  "output": "pdf",
  "options": {
    "format": "A4",
    "landscape": false,
    "printBackground": true,
    "scale": 1.0,
    "margin": { "top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm" },
    "width": "210mm",
    "height": "297mm"
  }
}
Field Type Required Notes
html string Yes The HTML document to render. Must be non-empty and at most 10 MB.
output string No Output format. Only "pdf" is supported; may be omitted.
options object No Rendering options (see Options reference). All fields optional.

The request schema is strict. Unknown fields are rejected with an INVALID_REQUEST error. Send only the fields documented here.

Response

On success (200 OK), the response body is the raw PDF with these headers:

Header Description
Content-Type application/pdf
Content-Length Size of the PDF in bytes
X-Render-ID Unique ID for this render (useful for support/debugging)

The PDF is returned inline — there is no separate "fetch the file" step and no JSON envelope around it.

Example — minimal

curl -X POST https://api.zindle.com.au/v1/render \
  -H "Authorization: Bearer $ZINDLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Hello</h1>"}' \
  --output out.pdf

Example — with options (Node.js)

import fs from "node:fs";

const res = await fetch("https://api.zindle.com.au/v1/render", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.ZINDLE_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    html: "<h1>Invoice</h1><p>Thank you for your business.</p>",
    options: {
      format: "A4",
      printBackground: true,
      margin: { top: "20mm", bottom: "20mm", left: "15mm", right: "15mm" },
    },
  }),
});

if (!res.ok) {
  const err = await res.json();
  throw new Error(`Render failed (${res.status}): ${err.error?.code}${err.error?.message}`);
}

const pdf = Buffer.from(await res.arrayBuffer());
fs.writeFileSync("invoice.pdf", pdf);

Example — with options (Python)

import os
import requests

resp = requests.post(
    "https://api.zindle.com.au/v1/render",
    headers={"Authorization": f"Bearer {os.environ['ZINDLE_KEY']}"},
    json={
        "html": "<h1>Report</h1>",
        "options": {"format": "Letter", "landscape": True, "scale": 0.9},
    },
)

if resp.status_code != 200:
    raise RuntimeError(f"Render failed ({resp.status_code}): {resp.json()}")

with open("report.pdf", "wb") as f:
    f.write(resp.content)

Options reference

All options live under the options object and are optional. Anything you omit uses the default.

Option Type Default Allowed values
format string A4 A4, A3, A5, Letter, Legal, Tabloid
landscape boolean false true / false
printBackground boolean false true / false — render background colours/images
scale number 1.0 Between 0.1 and 2.0
margin.top string none A dimension (see below)
margin.bottom string none A dimension
margin.left string none A dimension
margin.right string none A dimension
width string none A dimension — custom page width (overrides format)
height string none A dimension — custom page height (overrides format)

Dimensions (margin.*, width, height) must be a number followed by a unit: mm, cm, in, or px. Examples: 20mm, 1in, 2.5cm, 800px. Values without a valid unit are rejected.

Notes:

  • scale outside 0.12.0 is rejected.
  • If you set width and height, they define the page size directly; format is the simpler choice for standard paper sizes.