Skip to main content

Template Schema Reference

This guide defines the exact JSON schema structure for document templates in Rynko. Use this as the authoritative reference when creating templates programmatically, via API, or with AI assistants.

LLM-Ready Reference

For AI systems and LLMs, we provide a plain-text schema reference optimized for context windows: Download llms-templates.txt - A single file containing the complete schema specification.

warning

For AI/LLM Systems: Variables must be a plain JSON array [...], NOT wrapped in an object like {"variables": [...]}. See the AI Import Format section below.

AI/LLM Import Format

When generating templates with AI, you need to provide two separate JSON structures:

  1. Variables Array - The data schema defining what variables the template expects
  2. Template Schema - The visual design structure (sections and components)

Variables Format

⚠️ CRITICAL FOR AI/LLM: Variables must be a PLAIN JSON ARRAY [...], NOT wrapped in an object like { "variables": [...] }.

danger

Common AI Mistake: Do NOT wrap variables in an object. The format is a plain array.

✅ CORRECT format (plain array):

[
{
"id": "var_1",
"name": "customerName",
"type": "string",
"required": true,
"description": "Customer's full name",
"defaultValue": "John Doe"
},
{
"id": "var_2",
"name": "orderTotal",
"type": "number",
"required": true,
"defaultValue": 99.99
}
]

❌ INCORRECT format (DO NOT USE):

{
"variables": [
{ "name": "customerName", "type": "string" }
]
}

This WILL NOT work. Variables must be a plain array, not wrapped in an object.

[
{
"id": "var_1",
"name": "customerName",
"type": "string",
"required": true,
"description": "Customer's full name",
"defaultValue": "John Doe"
}
]
{
"variables": [
{ "name": "customerName", "type": "string" }
]
}

This will NOT work. Variables must be a plain array.

Variable Object Fields

FieldTypeRequiredDescription
idstringNo*Unique identifier (auto-generated if omitted)
namestringYesVariable name (used in {{variableName}} syntax)
typestringYesOne of: string, number, boolean, date, array, object
requiredbooleanNoWhether the variable is required (default: false)
descriptionstringNoHuman-readable description
defaultValueanyRecommendedDefault/sample value for testing and preview
isCalculatedbooleanNotrue if this is a calculated variable
expressionstringNoJavaScript expression (required if isCalculated: true)
schemaobjectNoType schema for array and object types
formatobjectNoDisplay format configuration

*If id is omitted, it will be auto-generated when imported.

Array Variable Example

{
"id": "var_items",
"name": "items",
"type": "array",
"itemType": "object",
"required": true,
"description": "List of order items",
"defaultValue": [
{ "name": "Product A", "quantity": 1, "price": 29.99 }
],
"schema": {
"type": "array",
"itemType": "object",
"itemSchema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"quantity": { "type": "number" },
"price": { "type": "number" }
}
}
}
}

Object Variable Example

{
"id": "var_customer",
"name": "customer",
"type": "object",
"required": true,
"description": "Customer information",
"defaultValue": {
"name": "Jane Smith",
"email": "jane@example.com"
},
"schema": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Customer name" },
"email": { "type": "string", "description": "Customer email" }
}
}
}

Basic Template Schema

Templates use a sections array at the root level.

{
"sections": [
{
"id": "body-section",
"type": "body",
"props": {
"backgroundColor": "#ffffff",
"padding": "40px 20px"
},
"components": [
// Array of component objects
]
}
]
}

Section Types

TypeDescription
headerTop section (logo, navigation)
main or bodyMain content section
footerBottom section (copyright, links)

Multi-Page Template Schema

PDF and Excel templates can use a pages array with nested sections for multi-page documents:

{
"outputFormats": ["pdf"],
"pages": [
{
"pageId": "page-1",
"pageName": "Invoice",
"pageSettings": {
"format": "A4",
"orientation": "portrait",
"margin": { "top": "20mm", "right": "15mm", "bottom": "20mm", "left": "15mm" }
},
"sections": [
{
"id": "main-section",
"type": "main",
"props": {},
"components": []
}
]
}
]
}

Output Formats

FormatDescription
["pdf"]Generate PDF attachment
["excel"]Generate Excel attachment
["pdf", "excel"]Generate both formats

Page Settings

FieldTypeDefaultDescription
formatstring"A4""A4", "Letter", "Legal", "A3", "A5", "Tabloid"
orientationstring"portrait""portrait" or "landscape"
marginobject-Page margins (top, right, bottom, left)
backgroundColorstring"#ffffff"Page background color
headerobject-Header configuration
footerobject-Footer configuration
pageBackgroundobject-Background image (PDF only) — { image, opacity?, fit? }
pageBorderobject-Page border (PDF only) — { width?, color?, style?, inset?, radius? }
watermarkobject-Watermark text (PDF only) — { text, fontSize?, opacity?, color?, rotation?, fontWeight? }

Page Background Image (PDF only)

Display a background image on every page. Set in defaultPageSettings or per-page pageSettings.

{
"pageBackground": {
"image": "https://example.com/ornate-frame.png",
"opacity": 0.3,
"fit": "fill"
}
}
  • image (required): URL or asset path
  • opacity: 0–1, default 1
  • fit: "fill" (stretch), "contain" (fit within page), "cover" (fill and crop)

Page Border (PDF only)

Draw a decorative border around each page. Supports per-side configuration, compound line styles, shadows, 3D effects, and per-corner radii.

{
"pageBorder": {
"width": 2,
"color": "#c8a960",
"style": "double",
"inset": 15,
"radius": 5
}
}
  • width: Border width in points, 0.25-6 (default 1)
  • color: Hex color (default "#000000")
  • style: Line style (default "solid"). Values: "solid", "dashed", "dotted", "double", "groove", "ridge", "dotDash", "dotDotDash", "thinThick", "thickThin", "thinThickThin", "wavy"
  • inset: Distance from page edge in points (default 10)
  • radius: Uniform corner radius in points (default 0)
  • sides: Per-side overrides. Each side (top, right, bottom, left) accepts { width, color, style } or false to disable
  • shadow: { offsetX, offsetY, color, opacity, blur } — adds a shadow behind the border
  • effect: "none", "inset", or "outset" — applies 3D per-side coloring
  • corners: { topLeft, topRight, bottomRight, bottomLeft } — per-corner radii (overrides radius)

Watermark (PDF only)

Display a diagonal watermark on every page. Supports {{variable}} syntax.

{
"watermark": {
"text": "DRAFT",
"fontSize": 60,
"opacity": 0.1,
"color": "#ff0000",
"rotation": -45,
"fontWeight": "bold"
}
}
  • text (required): Watermark text
  • fontSize: Font size in points (default 48)
  • opacity: 0–1 (default 0.15)
  • color: Hex color (default "#888888")
  • rotation: Degrees (default -45)
  • fontWeight: "normal" or "bold" (default "normal")

Per-Page Decoration Overrides

Individual pages can override pageBorder, pageBackground, watermark, and backgroundColor from defaultPageSettings in their own pageSettings:

  • Omit the field (or undefined): Inherit from defaultPageSettings
  • Set to an object: Use a custom decoration for this page
  • Set to null: Explicitly disable the decoration on this page
{
"pages": [
{
"pageId": "cover",
"pageName": "Cover Page",
"pageSettings": {
"pageBorder": null,
"watermark": null
},
"sections": []
},
{
"pageId": "content",
"pageName": "Content",
"pageSettings": {},
"sections": []
},
{
"pageId": "terms",
"pageName": "Terms",
"pageSettings": {
"pageBorder": { "width": 2, "color": "#FF0000", "style": "double", "inset": 8 }
},
"sections": []
}
]
}

In this example: the cover page has no border or watermark, the content page inherits template defaults, and the terms page uses a custom red double border.

Component Reference

Component Types by Output Format

ComponentPDFExcelDescription
rich-textRich text with HTML (use instead of text)
buttonCTA buttons with links
imageImages
tableData tables
table-layoutCustom table layouts
containerComponent wrapper
columnsMulti-column layout
dividerHorizontal rule
spacerVertical space
conditionalIf/else rendering
loopIteration over arrays
listOrdered/unordered lists
qr-codeQR codes
barcodeBarcodes (Code128, EAN, UPC, etc.)
chartCharts (bar, line, pie, etc.)
note

The text and heading components are deprecated. Use rich-text instead.

Component Structure

Components use one of three patterns:

1. Content-based (rich-text, button, list):

{
"id": "welcome-text",
"type": "rich-text",
"props": { "marginBottom": "16px" },
"content": "<p>Hello {{name}}</p>"
}

2. Props-based (image, divider, spacer, qr-code):

{
"id": "logo",
"type": "image",
"props": {
"src": "{{company.logo}}",
"alt": "Logo",
"width": "120px"
}
}

3. Children-based (container, columns, conditional, loop):

{
"id": "wrapper",
"type": "container",
"props": { "padding": "20px" },
"children": [
{ "id": "child-1", "type": "rich-text", "content": "..." }
]
}

Variable Syntax

Basic Substitution

{{variableName}}
{{customer.firstName}}
{{order.items[0].name}}

In Content

{
"type": "rich-text",
"content": "<p>Hello {{customer.name}}, your order #{{order.number}} is ready.</p>"
}

In Props

{
"type": "button",
"props": {
"href": "{{trackingUrl}}"
},
"content": "Track Package"
}

Conditional Logic

{
"id": "discount-banner",
"type": "conditional",
"props": {
"condition": "hasDiscount",
"operator": "==",
"value": true
},
"children": [
{
"id": "discount-text",
"type": "rich-text",
"content": "<p>You saved ${{discountAmount}}!</p>"
}
]
}

Operators

OperatorDescription
==Equals
!=Not equals
>Greater than
<Less than
>=Greater than or equal
<=Less than or equal
containsString/array contains
startsWithString starts with
endsWithString ends with
existsValue exists (not null/undefined)
isEmptyValue is empty

Loop Iteration

{
"id": "items-loop",
"type": "loop",
"props": {
"dataSource": "{{items}}",
"itemVariable": "item",
"indexVariable": "index"
},
"children": [
{
"id": "item-row",
"type": "rich-text",
"content": "<p>{{index}}. {{item.name}} - ${{item.price}}</p>"
}
]
}

Loop Props

PropRequiredDescription
dataSourceYesVariable containing array: {{items}}
itemVariableYesName for current item: item
indexVariableNoName for current index: index

System-Provided Global Constants

These variables are automatically available in all templates:

Date/Time Constants

VariableExample Value
{{__CURRENT_DATE__}}2025-12-02
{{__CURRENT_YEAR__}}2025
{{__CURRENT_MONTH__}}December
{{__CURRENT_MONTH_NUMBER__}}12
{{__CURRENT_DAY__}}2
{{__CURRENT_DAY_NAME__}}Tuesday

User/Project Constants

VariableDescription
{{__CURRENT_USER_ID__}}Current user's ID
{{__CURRENT_USER_NAME__}}Current user's display name
{{__CURRENT_USER_EMAIL__}}Current user's email address
{{__CURRENT_TEAM_ID__}}Current project's ID (referred to as teamId in the API)
{{__CURRENT_TEAM_NAME__}}Current project's name

Company Constants

VariableDescription
{{__COMPANY_NAME__}}Company display name
{{__COMPANY_LEGAL_NAME__}}Legal name
{{__COMPANY_TRADE_NAME__}}Trade name
{{__COMPANY_EMAIL__}}Contact email
{{__COMPANY_PHONE__}}Phone number
{{__COMPANY_WEBSITE__}}Website URL
{{__COMPANY_ADDRESS_LINE1__}}Address line 1
{{__COMPANY_ADDRESS_LINE2__}}Address line 2
{{__COMPANY_CITY__}}City
{{__COMPANY_STATE__}}State/Province
{{__COMPANY_POSTAL_CODE__}}Postal/ZIP code
{{__COMPANY_COUNTRY__}}Country
{{__COMPANY_GSTIN__}}GSTIN (tax ID)
{{__COMPANY_PAN__}}PAN (tax ID)

Template Constants

VariableDescription
{{__TEMPLATE_ID__}}Current template's ID
{{__TEMPLATE_NAME__}}Current template's name

Complete Example

Variables

[
{
"id": "var_customer",
"name": "customer",
"type": "object",
"required": true,
"defaultValue": { "name": "Jane Smith", "email": "jane@example.com" },
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
}
}
},
{
"id": "var_items",
"name": "items",
"type": "array",
"itemType": "object",
"required": true,
"defaultValue": [
{ "name": "Widget", "qty": 2, "price": 25.00 }
],
"schema": {
"type": "array",
"itemType": "object",
"itemSchema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"qty": { "type": "number" },
"price": { "type": "number" }
}
}
}
},
{
"id": "var_total",
"name": "orderTotal",
"type": "number",
"required": true,
"defaultValue": 99.99
}
]

Template Schema

{
"sections": [
{
"id": "body-section",
"type": "body",
"props": { "backgroundColor": "#f9fafb", "padding": "40px 20px" },
"components": [
{
"id": "main-container",
"type": "container",
"props": {
"backgroundColor": "#ffffff",
"maxWidth": "600px",
"margin": "0 auto",
"borderRadius": "8px",
"padding": "32px"
},
"children": [
{
"id": "greeting",
"type": "rich-text",
"props": { "marginBottom": "24px" },
"content": "<h1 style=\"margin: 0; font-size: 24px;\">Hello {{customer.name}}</h1>"
},
{
"id": "intro",
"type": "rich-text",
"props": { "marginBottom": "16px" },
"content": "<p style=\"margin: 0; color: #6b7280;\">Thank you for your order:</p>"
},
{
"id": "items-loop",
"type": "loop",
"props": {
"dataSource": "{{items}}",
"itemVariable": "item"
},
"children": [
{
"id": "item-row",
"type": "rich-text",
"content": "<p style=\"margin: 4px 0;\">• {{item.name}} x {{item.qty}} = ${{item.price}}</p>"
}
]
},
{
"id": "total-row",
"type": "rich-text",
"props": { "marginTop": "16px" },
"content": "<p style=\"margin: 0; font-weight: bold;\">Total: ${{orderTotal}}</p>"
}
]
}
]
}
]
}

AI Generation Checklist

Before outputting a template, verify:

  • Variables are a plain array [...], not { "variables": [...] }
  • Every variable has name and type fields
  • Every variable has a defaultValue for testing
  • Array variables have itemType and schema.itemSchema.properties
  • Object variables have schema.properties
  • Schema has sections array (single-page) or pages array (multi-page)
  • Every component has a unique id
  • Variable references use {{variableName}} syntax
  • Loop components use {{arrayVariable}} for dataSource
  • Nested object access uses dot notation: {{customer.name}}

How to Import into Rynko

Open the Template Designer

Navigate to Templates and create a new template or edit an existing one.

Import Variables

  1. Click Manage Variables in the toolbar
  2. Switch to the Raw JSON tab
  3. Paste your variables array
  4. Click Validate to check for errors
  5. Click Apply Changes

Import Schema

  1. Click the code icon (</>) in the toolbar to open Raw Schema Editor
  2. Paste your schema JSON
  3. Click Validate to check for errors
  4. Click Apply Changes

Save Template

Click Save to persist your changes.