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-text✓✓Rich text with HTML (use instead of text)
button✓✗CTA buttons with links
image✓✓Images
table✓✓Data tables
table-layout✓✓Custom table layouts
container✓✗Component wrapper
columns✓✗Multi-column layout
divider✓✗Horizontal rule
spacer✓✗Vertical space
conditional✓✓If/else rendering
loop✓✓Iteration over arrays
list✓✗Ordered/unordered lists
qr-code✓✗QR codes
barcode✓✗Barcodes (Code128, EAN, UPC, etc.)
chart✓✓Charts (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.