Skip to content

Templates

Templates define the layout and content of your documents. They can be created in the dashboard’s visual editor or defined as JSON and sent inline with render requests.

Every template uses schema v2. This example includes every element kind:

{
"version": 2,
"units": "in",
"meta": {
"name": "Shipping Label",
"description": "4x6 shipping label with barcode",
"tags": ["shipping", "labels"]
},
"size": {
"width": 101.6,
"height": 152.4,
"safeMargin": 3
},
"schema": {
"type": "object",
"properties": {
"recipient": { "type": "object" },
"trackingNumber": { "type": "string" },
"items": { "type": "array" }
}
},
"sampleData": {
"recipient": { "name": "Jane Smith" },
"trackingNumber": "BP123456789",
"items": [{ "name": "Widget A", "quantity": 2 }]
},
"elements": [
{
"id": "background",
"kind": "box",
"position": { "x": 3, "y": 3 },
"size": { "width": 95.6, "height": 146.4 },
"fill": "#ffffff",
"stroke": { "color": "#111111", "width": 0.4 },
"radius": 2
},
{
"id": "recipient",
"kind": "text",
"position": { "x": 8, "y": 10 },
"size": { "width": 70, "height": 12 },
"expression": "recipient.name",
"font": { "family": "Arial", "size": 16, "weight": "bold" },
"color": "#111111"
},
{
"id": "rule",
"kind": "divider",
"position": { "x": 8, "y": 27 },
"orientation": "horizontal",
"length": 85.6,
"thickness": 0.5,
"color": "#777777"
},
{
"id": "tracking",
"kind": "code",
"position": { "x": 8, "y": 34 },
"size": { "width": 85.6, "height": 25 },
"format": "code128",
"expression": "trackingNumber",
"showText": true,
"color": "#111111",
"fill": "#ffffff"
},
{
"id": "logo",
"kind": "image",
"position": { "x": 78, "y": 8 },
"size": { "width": 15, "height": 15 },
"dataUri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
"fit": "contain"
},
{
"id": "items",
"kind": "repeat",
"position": { "x": 8, "y": 67 },
"size": { "width": 85.6, "height": 60 },
"data": "items",
"rowHeight": 10,
"maxRows": 6,
"children": [
{
"id": "item-name",
"kind": "text",
"position": { "x": 0, "y": 0 },
"size": { "width": 65, "height": 8 },
"expression": "row.name",
"font": { "family": "Arial", "size": 9 },
"color": "#111111"
},
{
"id": "item-quantity",
"kind": "text",
"position": { "x": 68, "y": 0 },
"size": { "width": 17.6, "height": 8 },
"expression": "String(row.quantity)",
"font": { "family": "Arial", "size": 9 },
"align": "right",
"color": "#111111"
}
]
}
]
}
Field Type Required Description
version number Yes Must be 2.
units "mm" | "in" Yes Display preference for rulers and inputs.
meta object Yes Template metadata.
meta.name string Yes Template name.
meta.description string No Human-readable description.
meta.tags string[] No Organizational tags.
size object Yes Document size.
size.width number Yes Document width in millimetres.
size.height number Yes Document height in millimetres.
size.safeMargin number No Safe margin inset in millimetres.
media object No Embedded single-label or sheet media definition. Its spatial values are millimetres.
rotationOnMedia 0 | 90 | 180 | 270 No Rotation when placing the design on media.
schema object No JSON Schema for validating data at render time.
customFonts string[] No Additional font family names used by the template.
sampleData object No Representative data used for previews and expression validation.
elements array Yes Array of design elements.

Spatial values are always stored as numbers in millimetres; font sizes are numbers in points. The required units field only controls whether design tools display millimetres or inches—it does not change the stored values.

Elements are the building blocks of a template. Positioning is absolute: position.x and position.y are numeric millimetre offsets from the document origin. The order of elements is paint order, from back to front, so later elements are drawn over earlier ones. Repeat children use the same element shapes, with positions relative to each row.

Field Type Required Description
id string Yes Unique element identifier.
kind string Yes Element kind (see below).
position object Yes Numeric x and y coordinates in millimetres.
size object Most kinds Numeric width and height in millimetres. Dividers use length and thickness instead.
rotation number No Degrees clockwise around the element centre. Defaults to 0.
visible boolean No Literal visibility. Cannot be combined with visibleExpression.
visibleExpression string No JavaScript expression controlling visibility. Cannot be combined with visible.
locked boolean No Locks the element in the designer; ignored during rendering.
opacity number No Element opacity.
Kind Description
text Literal text or a dynamic expression, plus a required font object. Supports alignment, spacing, overflow, padding, fill, and stroke.
box Rectangle with optional fill, stroke, and corner radius.
divider Horizontal or vertical rule with length, thickness, color, and optional dash style.
code Barcode or matrix code. Set format to code128, code39, ean13, ean8, upca, upce, itf14, interleaved2of5, gs1-128, qr, or datamatrix.
image Static or dynamic image with dataUri or srcExpression and optional fit.
repeat Repeats its children for rows at the data path in data. Uses rowHeight and optional maxRows.

Styles are fields on each element kind, not a shared style object. stroke is a border with color, numeric millimetre width, and optional style; fill is the area behind content; and color is the ink used for text, dividers, or codes. A text element’s font.size is numeric points. See the complete example above for each form.

Elements can use expressions to dynamically render content from the data object passed at render time.

Text and code elements can set either text for literal content or expression for dynamic content, but not both. Expressions are JavaScript expressions evaluated at render time. Top-level keys from the render request’s data object are available as variables; repeat children also receive the current item as row.

For static content, set text directly. For example, a text or code element can use "text": "SHIP TO:" instead of an expression.

Any element can set a literal visible boolean or a dynamic visibleExpression, such as "priority === 'rush'". These two fields are mutually exclusive.

Templates created in the dashboard are stored and can be referenced by ID in render requests using templateId. Published templates are available to API keys; draft templates are only accessible via the dashboard.

Status API Key Access Dashboard Access
Draft No Yes
Published Yes Yes

Every template gets an auto-generated slug based on its name (e.g., shipping-label). Slugs are human-readable identifiers you can use as templateId in render requests instead of opaque template IDs.

Slug format: lowercase letters, digits, and hyphens (e.g., product-2x1, shipping-label).

Templates can belong to a library — a shared collection accessible to any team. Library templates use a qualified slug format: librarySlug:templateSlug (e.g., carbon:product-2x1).

See Template Libraries for details.