Skip to main content

HTML documents

For content-driven documents (letters, orders, multi-page notices), laying out absolute boxes is the wrong tool. POST /v1/documents with an html source renders your HTML/CSS with a real browser layout engine: proper text flow, CSS styling, and automatic pagination.

curl -s "https://api.pdfs.ecourtdate.com/v1/documents" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "hearing-notice",
"page": { "size": "letter" },
"html": {
"content": "<h1>Notice of Hearing</h1><p>Your hearing is scheduled for <strong>August 15, 2026</strong> at 9:00 AM.</p>"
},
"response": { "mode": "json" }
}'

How it differs from blank-page generation:

  • The content determines the page count: page.count is rejected; page.size and orientation set the paper.
  • The response must be JSON mode (422 HTML_REQUIRES_JSON_RESPONSE): you receive a download URL (response modes).
  • fields still compose onto the rendered pages afterwards, and options apply as usual: overlay a barcode or a watermark on an HTML-authored document freely.
  • A content fragment is wrapped in a page shell using the built-in fonts; a complete document with its own <style> is used as-is.

Sanitization

HTML is sanitized to a safe allow-list before rendering. Removed, and reported with an HTML_CONTENT_SANITIZED warning so nothing disappears silently:

  • Scripts and event handlers
  • Frames and embedded documents
  • Forms
  • Anything that fetches from the network

Two practical consequences:

  • Images must be data: URIs: embed them (<img src="data:image/png;base64,…">) rather than linking.
  • Stylesheets and style attributes pass through: style freely with inline CSS and <style> blocks; external resources never load.

The rendering sandbox itself runs with scripting disabled and no network access (Security).

Content is limited to 1 MB (413 HTML_TOO_LARGE).

Fonts

Three embedded font families are available by name in your CSS:

FamilyCoverage
"Noto Sans" (default)Latin, Latin-extended, Greek, Cyrillic
"Noto Sans Hebrew"Hebrew
"Noto Sans SC"Simplified Chinese
<p style="font-family: 'Noto Sans Hebrew'; direction: rtl;"></p>

Headers, footers, and margins

html.header and html.footer (≤ 10 KB each) are print templates repeated on every page. Elements with these classes are substituted:

<div style="font-size: 9px; width: 100%; text-align: center;">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
ClassSubstituted with
pageNumberCurrent page number
totalPagesTotal page count
datePrint date
titleDocument title

html.margins sets page margins in points (top/right/bottom/left, 0–288, default 36 on every side). print_background (default true) controls whether CSS backgrounds render.

Accessible tagged PDFs

"html": { "tagged": true, … } emits a tagged PDF: the document's structure (headings, paragraphs, lists, tables) is embedded so screen readers can navigate it, supporting Section 508 accessibility requirements.

Tagged output cannot be combined with fields, options, typography, flatten, or unicode (422 HTML_TAGGED_CONFLICT). Composing drawn content over a tagged document would corrupt its structure tree. Author the entire document in HTML when you need tagged output, and set the document language via semantic HTML (<html lang="en">).

For non-tagged documents, still set options.metadata.language: it helps assistive technology choose the right voice.

HTML in a box

To place HTML inside an absolutely-positioned box on any document (blank pages, an uploaded base PDF, or a rendered HTML document), use the html field type instead: same sanitization, with {{merge_tag}} substitution, sized exactly to the field box.

Prefer whole-document html when the content should flow and paginate; prefer html fields when a template's layout is fixed and one region needs rich content. Note that whole-document HTML preserves link annotations and (optionally) tagging; composed HTML boxes keep their visual layout only.