Skip to main content

Templates

Tag: Templates · Version: v1 · Stability: 🟒 Stable

A template is the reusable document blueprint: a name, HTML-ish content with {{token}} placeholders, and (optionally) an uploaded base PDF to design over. All endpoints are JWT-only and workspace-scoped β€” a template from another workspace returns 404.

Rendering a template lives on its own page: Rendering.

List templates​

GET /api/templates Β· JWT

QueryTypeNotes
namestringOptional filter by name.

Create a template​

POST /api/templates Β· JWT

Request β€” CreateTemplateBody
{
"name": "Invoice",
"content": "<h1>Invoice {{invoiceNumber}}</h1><p>Total: {{total}}</p>"
}

Both name and content are required. Returns the new template, including its id (UUID).

Get a template​

GET /api/templates/{id} Β· JWT β€” {id} is a UUID.

Update a template​

PUT /api/templates/{id} Β· JWT

Request β€” UpdateTemplateBody
{
"name": "Invoice (2026)",
"content": "<h1>Invoice {{invoiceNumber}}</h1>",
"expectedUpdatedAt": "2026-06-07T10:00:00Z"
}

content is required; name and expectedUpdatedAt are optional.

Optimistic concurrency

Pass the expectedUpdatedAt you last read. If a teammate saved in the meantime, the server returns 409 Conflict instead of silently overwriting their change. Re-fetch, reconcile, and retry.

Delete a template​

DELETE /api/templates/{id} Β· JWT


Stored content​

The designer saves content as a JSON string. A current document (version: 4) is a stack of bands plus the data schema the {{tokens}} resolve against:

content (abridged)
{
"version": 4,
"pageSize": { "id": "a4" },
"direction": "rtl",
"brand": { "primary": "#E11D48", "accent": "#0EA5E9" },
"bands": [
{ "id": "b1", "kind": "report-header", "height": 120, "elements": [] }
],
"schema": []
}

direction and brand are written only when set: a left-to-right document on the default colours has neither key. Prefer building templates in the designer and saving what it produces over hand-writing this shape.

Page size​

pageSize is one of three shapes. Anything unknown renders as A4.

ShapeMeaning
{ "id": "a5" }A preset, portrait.
{ "id": "a4", "orientation": "landscape" }A preset, landscape.
{ "id": "custom", "width": 283, "height": 425 }A custom size in points (36–3370 per side).

Preset ids: a3 a4 a5 a6 b5 Β· letter legal tabloid executive halfLetter Β· receipt80 receipt58 Β· fourBySix label100x150 label4x2 label2x1 Β· envelopeDl envelopeC5 envelope10 Β· businessCard idCard ticket. The two receipt rolls have a fixed width and render as one page as tall as their content (see Rendering).

Direction​

"direction": "rtl" makes the document right to left. A missing key means left to right. Text, lists and tables also carry their own direction (auto, ltr or rtl) per element.

Brand colours​

brand holds the template's palette, { "primary", "accent" }, each #rgb or #rrggbb. When it is absent the palette is #2563eb and #f59e0b. An element's colour (a color, fill, bg, or any …Color / …Bg property) can hold a slot reference instead of a hex value:

SlotResolves to
@primaryThe palette's primary colour.
@accentThe palette's accent colour.
@onPrimaryBlack or white, whichever reads better on primary.
@onAccentBlack or white, whichever reads better on accent.

A render's theme overrides primary and accent for that render only; the stored template is unchanged.


Base-PDF overlay​

Attach an uploaded PDF as a template's background layer, then position elements on top of it. The server rasterises each page to a PNG so the designer canvas and the rendered output share a byte-identical base (true WYSIWYG). JWT-only β€” this is a design-time feature, not part of the render API.

Upload a base PDF​

POST /api/templates/{id}/base-pdf Β· JWT Β· multipart/form-data

PartTypeRequired
filebinary (IFormFile)βœ…

Uploads and rasterises the PDF. Rejected: encrypted/password-protected, XFA/ dynamic forms, oversized, corrupt, or (MVP) mixed-page-size files β€” each with a clear error.

Get base-PDF metadata​

GET /api/templates/{id}/base-pdf Β· JWT β€” page count and per-page dimensions.

Get a rendered page image​

GET /api/templates/{id}/base-pdf/pages/{index} Β· JWT

{index} is an integer (0-based) page index. Returns the page raster (PNG) used as the canvas/render background.

Remove the base PDF​

DELETE /api/templates/{id}/base-pdf Β· JWT