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
| Query | Type | Notes |
|---|---|---|
name | string | Optional filter by name. |
Create a templateβ
POST /api/templates Β· JWT
{
"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
{
"name": "Invoice (2026)",
"content": "<h1>Invoice {{invoiceNumber}}</h1>",
"expectedUpdatedAt": "2026-06-07T10:00:00Z"
}
content is required; name and expectedUpdatedAt are optional.
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:
{
"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.
| Shape | Meaning |
|---|---|
{ "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:
| Slot | Resolves to |
|---|---|
@primary | The palette's primary colour. |
@accent | The palette's accent colour. |
@onPrimary | Black or white, whichever reads better on primary. |
@onAccent | Black 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
| Part | Type | Required |
|---|---|---|
file | binary (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
Relatedβ
- Rendering β turn a template + data into a PDF.
- Collaboration β comments live under a template.