Template Settings
Reference for templateSettings in REFRACT PDF. Controls locale, date/time formatting, number and currency display, boolean labels, section numbering, Table of Contents, watermarks, security, and consent.
Overview
templateSettings is a top-level key placed on the JSON payload (or the template's docDefinition) that governs global rendering behaviour. All properties are optional - omitting a setting preserves the existing default, so existing templates are never affected by adding the key.
templateSettings vs. options.features
templateSettings controls how a document is rendered - locale, formatting, watermarks, layout. It lives inside the data payload JSON.
Feature flags (options.features) are different: they control which REFRACT Platform services run after rendering - storage, audit, signatures, accessibility, redaction. They live in the API request options object. See Feature Flags for the full reference.
{
"templateSettings": { },
"salesOrders": [ ]
}Locale & Date / Time
Controls how dates, times, and locale-sensitive values are formatted across the entire document.
| Property | Type | Default | Description |
|---|---|---|---|
timezone | string | "UTC" | IANA timezone identifier applied to all date/datetime formatting. |
locale | string | "en-US" | BCP 47 locale tag used by Intl.NumberFormat for number and currency values. |
dateFormat | string | "M/D/YYYY" | Display format for date-only values. Accepts moment.js tokens. |
dateTimeFormat | string | "M/D/YYYY, h:mm A" | Display format for datetime values. Accepts moment.js tokens. |
inputDateFormat | string | none | Parsing pattern for incoming non-ISO date strings. Supported tokens: YYYY MM M DD D. Without this, non-ISO strings are returned as-is with a console warning. |
European locale:
{
"templateSettings": {
"timezone": "Europe/Berlin",
"locale": "de-DE",
"dateFormat": "DD.MM.YYYY",
"dateTimeFormat": "DD.MM.YYYY HH:mm",
"inputDateFormat": "DD/MM/YYYY"
}
}UK locale with custom datetime:
{
"templateSettings": {
"timezone": "Europe/London",
"locale": "en-GB",
"dateFormat": "DD MMM YYYY",
"dateTimeFormat": "DD MMM YYYY, HH:mm"
}
}US Central with 12-hour time:
{
"templateSettings": {
"timezone": "America/Chicago",
"locale": "en-US",
"dateFormat": "MMM D, YYYY",
"dateTimeFormat": "MMM D, YYYY h:mm A"
}
}Number Formatting
Applied to all columns with format: "number" unless overridden per-column in a columnManifest.
| Property | Type | Default | Description |
|---|---|---|---|
number.decimalPlaces | number | 2 for fractions, 0 for integers | How many decimal places to display. |
number.thousandsSeparator | string | "," | Character used to group thousands. |
number.decimalSeparator | string | "." | Character used as the decimal point. |
European number style (period thousands, comma decimal):
{
"templateSettings": {
"number": {
"decimalPlaces": 2,
"thousandsSeparator": ".",
"decimalSeparator": ","
}
}
}Integer quantities, no decimals:
{
"templateSettings": {
"number": {
"decimalPlaces": 0,
"thousandsSeparator": ","
}
}
}Currency Formatting
Applied to all columns with format: "currency" unless overridden per-column.
| Property | Type | Default | Description |
|---|---|---|---|
currency.code | string | "USD" | ISO 4217 currency code used by Intl.NumberFormat (e.g. "EUR", "GBP", "JPY"). |
currency.symbol | string | none | Override the rendered symbol (e.g. "€", "£"). Defaults to the symbol implied by code. |
currency.position | "before" | "after" | "before" | Whether the symbol appears before or after the numeric value. |
currency.decimalPlaces | number | 2 | Number of decimal places. |
currency.thousandsSeparator | string | "," | Thousands grouping character. |
currency.decimalSeparator | string | "." | Decimal point character. |
US Dollars (default, explicit):
{
"templateSettings": {
"currency": {
"code": "USD",
"symbol": "$",
"position": "before",
"decimalPlaces": 2
}
}
}Euros (symbol after amount):
{
"templateSettings": {
"currency": {
"code": "EUR",
"symbol": "€",
"position": "after",
"decimalPlaces": 2,
"thousandsSeparator": ".",
"decimalSeparator": ","
}
}
}Japanese Yen (no decimals):
{
"templateSettings": {
"currency": {
"code": "JPY",
"symbol": "¥",
"position": "before",
"decimalPlaces": 0
}
}
}Per-Column Overrides
Per-column overrides in a columnManifest always win over templateSettings.currency. Set currency at the template level for the document default, then override per-column only where needed.
Boolean Display
Applied to all columns with format: "boolean". Controls the text labels and optional icons rendered for truthy/falsy values.
| Property | Type | Default | Description |
|---|---|---|---|
boolean.trueLabel | string | "Yes" | Text label rendered when the value is truthy. |
boolean.falseLabel | string | "No" | Text label rendered when the value is falsy. |
boolean.icons.true | string | none | Icon key prepended to the true label (e.g. "CheckCircle"). |
boolean.icons.false | string | none | Icon key prepended to the false label (e.g. "XCircle"). |
boolean.icons.warning | string | none | Icon shown when the value cannot be classified (e.g. "AlertTriangle"). |
Yes/No with icons:
{
"templateSettings": {
"boolean": {
"trueLabel": "Yes",
"falseLabel": "No",
"icons": {
"true": "CheckCircle",
"false": "XCircle"
}
}
}
}Active/Inactive (no icons):
{
"templateSettings": {
"boolean": {
"trueLabel": "Active",
"falseLabel": "Inactive"
}
}
}Enabled / Disabled with warning state:
{
"templateSettings": {
"boolean": {
"trueLabel": "Enabled",
"falseLabel": "Disabled",
"icons": {
"true": "CheckCircle",
"false": "XCircle",
"warning": "AlertTriangle"
}
}
}
}Section Numbering
When sectionNumbering is true, every top-level section title is automatically prefixed with a sequential number (1., 2., 3., ...).
| Property | Type | Default | Description |
|---|---|---|---|
sectionNumbering | boolean | false | Prefix section titles with sequential numbers. |
{
"templateSettings": {
"sectionNumbering": true
}
}Rendered output:
1. Customer Information
2. Sales Orders
3. Payment SummaryTable of Contents (TOC)
When toc.enabled is true, a dedicated TOC page is generated and inserted at the start or end of the document. The TOC lists every section title with its page number and optional leader dots.
No Side Effects
When toc is absent or toc.enabled is false, no TOC page is generated and existing templates are completely unaffected.
TocSettings Properties
| Property | Type | Default | Description |
|---|---|---|---|
toc.enabled | boolean | false | Enable TOC generation. |
toc.position | "start" | "end" | "start" | "start" inserts the TOC before the first content page. "end" appends it after all content. |
toc.maxDepth | number | 1 | Maximum section nesting depth included. 1 = top-level sections only. |
toc.showPageNumbers | boolean | true | Display page numbers right-aligned on each TOC entry. |
toc.leaderDots | boolean | true | Render dotted leader lines between the section title and its page number. |
toc.excludeSections | string[] | [] | Array of section node IDs or exact section titles to exclude from the TOC. |
toc.includeIcons and toc.style are not read by the TOC page builder - setting either has no effect on the rendered TOC page.
Per-Section Overrides
Individual sections can opt out of the TOC or provide a custom TOC label without changing the global settings:
| Property | Type | Default | Description |
|---|---|---|---|
settings.excludeFromTOC | boolean | false | Exclude this specific section from the TOC. |
settings.tocLabel | string | section title | Custom label for this entry in the TOC. Falls back to the section's own title. |
TOC at start of document:
{
"templateSettings": {
"toc": {
"enabled": true,
"position": "start",
"showPageNumbers": true,
"leaderDots": true
}
}
}TOC at end, top-level sections only:
{
"templateSettings": {
"toc": {
"enabled": true,
"position": "end",
"maxDepth": 1,
"showPageNumbers": true,
"leaderDots": false
}
}
}Exclude specific sections from TOC:
{
"templateSettings": {
"toc": {
"enabled": true,
"excludeSections": ["Appendix A", "Internal Notes"]
}
}
}Per-section TOC override on a node:
{
"type": "hierarchical_table",
"title": "Patient Information",
"settings": {
"excludeFromTOC": false,
"tocLabel": "Patient Info"
}
}Exclude a section node from TOC:
{
"type": "section",
"title": "Internal Notes",
"settings": {
"excludeFromTOC": true
}
}Watermark
Renders a text or SVG image watermark on every page of both the browser preview and server-generated PDFs.
No Side Effects
When watermark is absent or watermark.enabled is false, no watermark is applied and existing templates are completely unaffected.
Dynamic Watermark Text
You can inject dynamic watermark text at render time by setting a top-level watermarkText key in the JSON payload. This takes precedence over watermark.value.
{ "watermarkText": "DRAFT", "templateSettings": { } }WatermarkSettings Properties
| Property | Type | Default | Description |
|---|---|---|---|
watermark.enabled | boolean | false | Master switch - must be true for any watermark to render. |
watermark.type | "text" | "image" | "text" | "text" renders value as diagonal text. "image" renders value as an inline SVG. |
watermark.value | string | none | Watermark content. Supports {{field}} payload tokens. For type: "text" use a plain string; for type: "image" use an SVG string. |
watermark.opacity | number | 0.1 | Opacity from 0.0 (invisible) to 1.0. Text watermarks are hard-capped at 0.2 for readability. |
watermark.rotation | number | -45 | Rotation angle in degrees. Only applies to type: "text". |
watermark.position | WatermarkPosition | "center" | Anchor position on each page (see values below). |
watermark.fontSize | number | 60 | Font size (pt) for text watermarks. |
watermark.color | string | "#000000" | Fill color for text watermarks. Hex string. |
position values:
| Value | Description |
|---|---|
"center" | Centered horizontally and vertically on the page. |
"top-center" | Horizontally centered, near the top margin. |
"bottom-center" | Horizontally centered, near the bottom margin. |
"top-left" | Near the top-left corner. |
"top-right" | Near the top-right corner. |
"bottom-left" | Near the bottom-left corner. |
"bottom-right" | Near the bottom-right corner. |
Standard "CONFIDENTIAL" diagonal watermark:
{
"templateSettings": {
"watermark": {
"enabled": true,
"type": "text",
"value": "CONFIDENTIAL",
"opacity": 0.1,
"rotation": -45,
"position": "center",
"fontSize": 60,
"color": "#000000"
}
}
}"DRAFT" in red, larger font:
{
"templateSettings": {
"watermark": {
"enabled": true,
"type": "text",
"value": "DRAFT",
"opacity": 0.15,
"rotation": -30,
"position": "center",
"fontSize": 80,
"color": "#DC2626"
}
}
}Dynamic watermark from payload:
{
"templateSettings": {
"watermark": {
"enabled": true,
"type": "text",
"value": "{{status}}",
"opacity": 0.1,
"rotation": -45,
"position": "center"
}
},
"status": "DRAFT"
}Bottom-right corner stamp:
{
"templateSettings": {
"watermark": {
"enabled": true,
"type": "text",
"value": "INTERNAL USE ONLY",
"opacity": 0.18,
"rotation": 0,
"position": "bottom-right",
"fontSize": 14,
"color": "#6B7280"
}
}
}Top-right corner, no rotation:
{
"templateSettings": {
"watermark": {
"enabled": true,
"type": "text",
"value": "COPY",
"opacity": 0.2,
"rotation": 0,
"position": "top-right",
"fontSize": 20,
"color": "#1E40AF"
}
}
}Security
Password protection is implemented in both browser and server rendering: when active, the resolved password is set as pdfmake's userPassword, which pdfmake encrypts the PDF with, so the file cannot be opened without it.
| Property | Type | Default | Description |
|---|---|---|---|
security.enabled | boolean | false | Master switch. Password encryption only applies when this is true. |
security.requireJsonPassword | boolean | false | Require a password to be supplied in the render request (options.userPassword) rather than falling back to a template default. |
security.userPassword | string | none | The password pdfmake encrypts the PDF with. Checked before defaultPassword. |
security.defaultPassword | string | none | Fallback password used when userPassword is absent. |
security.validatePassword | boolean | false | Defined in the settings type but not read by the renderer - it has no effect regardless of value. |
{
"templateSettings": {
"security": {
"enabled": true,
"requireJsonPassword": true
}
}
}Distribution
Controls how the renderer outputs documents when the payload contains a batch array (multiple records). When distribution.enabled is true and mode is "individual", the server generates one PDF file per batch item and uses fileNameTemplate to name each file. When mode is "combined" (or distribution is absent/disabled), all batch items are merged into a single PDF with page breaks between them.
Server-Side Only
distribution is a server-side setting. In browser preview mode all batch items are always combined into one PDF regardless of this setting.
| Property | Type | Default | Description |
|---|---|---|---|
distribution.enabled | boolean | false | Enable per-item file splitting on the server. |
distribution.mode | "individual" | "combined" | "individual" | "individual" - one file per batch item. "combined" - all items in one PDF. |
distribution.fileNameTemplate | string | "Doc_{BATCHID}" | File name pattern for each output file. Supports {BATCHID} (0-based index) and any {{field}} payload token. |
fileNameTemplate tokens:
| Token | Resolves to |
|---|---|
{BATCHID} | Zero-based index of the batch item (0, 1, 2, ...). |
{{field}} | Any top-level field from the item's data record (e.g. {{orderId}}, {{customerName}}). |
One PDF per customer:
{
"templateSettings": {
"distribution": {
"enabled": true,
"mode": "individual",
"fileNameTemplate": "Invoice_{{invoiceNumber}}"
}
}
}Single combined PDF (disabled):
{
"templateSettings": {
"distribution": {
"enabled": false,
"mode": "combined"
}
}
}Approval Panel
When approvalPanel.enabled is true, an Approval & Verification page is automatically appended to every rendered document. The page displays a signature grid (populated from data.signatures or data.documentAttestation.signatures), an optional integrity fingerprint, and an optional QR code linking to a verification URL. For full details on how signature data is structured and how the approval page integrates with e-signature platforms, see Signature Zones.
Per-Request Overrides
The approvalPanel settings act as document-level defaults. Any individual field (e.g. headingLabel, verificationUrl) can also be overridden per-request by setting the same key directly on the data payload or inside documentAttestation.
| Property | Type | Default | Description |
|---|---|---|---|
approvalPanel.enabled | boolean | false | Append an approval page to the document. |
approvalPanel.columns | 1 | 2 | 3 | 2 | Number of signature columns in the approval grid. |
approvalPanel.includeDigitalThumbprint | boolean | false | Append a deterministic fingerprint derived from document metadata and approver names: a SHA-256 digest of documentId (or the first of invoiceNumber/poNumber/orderId present), generatedDate (or invoiceDate/orderDate), and each signer's role, name and required flag, formatted as 4 hyphen-separated groups of 8 uppercase hex characters. It does not include a version field. |
approvalPanel.headingLabel | string | "Approval & Verification" | Custom heading displayed at the top of the approval page. |
approvalPanel.headingAlignment | "left" | "center" | "right" | "left" | Alignment of the heading text. |
approvalPanel.headingFontSize | number | 14 | Font size (pt) for the heading. |
approvalPanel.user | string | none | Name or identifier of the requesting user, displayed in the document metadata area of the approval page. Supports {{field}} payload tokens. |
approvalPanel.verificationUrl | string | none | URL embedded as a QR code on the approval page. Rendered alongside a "Scan to verify" label. Supports {{field}} payload tokens. |
Minimal approval page (signature grid only):
{
"templateSettings": {
"approvalPanel": {
"enabled": true,
"columns": 2
}
}
}Full approval page with integrity fingerprint and QR:
{
"templateSettings": {
"approvalPanel": {
"enabled": true,
"columns": 2,
"includeDigitalThumbprint": true,
"headingLabel": "Document Approval & Verification",
"headingAlignment": "center",
"headingFontSize": 22,
"user": "{{user}}",
"verificationUrl": "refractlogic.com"
}
}
}Three-column layout, dynamic verification URL:
{
"templateSettings": {
"approvalPanel": {
"enabled": true,
"columns": 3,
"includeDigitalThumbprint": true,
"headingLabel": "Signoff Required",
"headingAlignment": "left",
"verificationUrl": "https://portal.example.com/verify/{{documentId}}"
}
}
}Signatures Required
The approval page requires at least one entry in data.signatures (or data.documentAttestation.signatures) to render. If the signatures object is absent or empty, the approval page is silently omitted even when enabled is true.
Consent
Each product's block (templateSettings.esign, templateSettings.workflow, and templateSettings.delivery) takes a consent setting. It says whether the participant is shown a consent policy and must accept it before their first act, and which policy they are shown.
{
"templateSettings": {
"esign": { "consent": { "mode": "required", "policyId": "acme-consumer-records" } },
"workflow": { "consent": { "mode": "none" } }
}
}| Property | Type | Default | Description |
|---|---|---|---|
consent.mode | "required" | "none" | Per product (below) | required: the participant accepts the policy before their first act. none: no consent step. |
consent.policyId | string | none | The id of your own policy, published as consent-policies/{policyId}.yaml in the tenant assets library. Leave it out to show the product's REFRACT system policy. |
| Block | mode values | Default when there is no consent block |
|---|---|---|
templateSettings.esign.consent | required | required |
templateSettings.workflow.consent | required or none | required |
templateSettings.delivery.consent | required or none | none |
A delivery consent step is shown on the recipient's secure link, so required needs delivery mode SECURE_LINK. Consent Step on the REFRACT Delivery page describes what the recipient sees, and what happens when they decline.
consent is a template setting. Set it in the template; a request that sets consent in its own templateSettings is refused with consent_not_request_settable.
The block also takes contacts, the text for the policy's contact tokens. Consent Policies describes the system policies, how to publish your own and select it with consent.policyId, and the policy file format.
| Code | Meaning |
|---|---|
consent_setting_invalid | The template's consent block is not valid: mode is not required or none, or policyId or a contact value is malformed. setting names the value. |
consent_requires_portal_link | The template sets templateSettings.delivery.consent.mode to required with a delivery mode (SHAREPOINT or BOTH) that hands the recipient the document without a portal link, so no consent step can be shown. |
Error Responses and Codes lists every consent code, with its status and what to do.
Related
- Feature Flags -
options.featuresreference: which REFRACT Platform services to activate per request (storage, audit, signatures, redaction, accessibility) - Signature Zones - configuring the approval panel and signature data
- Payload Structure - top-level payload schema
- Premium Features - Section 508, XMP Metadata, and Explain Document
- Consent Policies - the system consent policies, and how to publish and select your own
Full Example
Complete templateSettings block combining all features. Omit any section you don't need - defaults are applied automatically.
{
"templateSettings": {
"timezone": "America/Chicago",
"locale": "en-US",
"dateFormat": "MMM D, YYYY",
"dateTimeFormat": "MMM D, YYYY h:mm A",
"inputDateFormat": "MM/DD/YYYY",
"currency": {
"code": "USD",
"symbol": "$",
"position": "before",
"decimalPlaces": 2,
"thousandsSeparator": ",",
"decimalSeparator": "."
},
"number": {
"decimalPlaces": 2,
"thousandsSeparator": ",",
"decimalSeparator": "."
},
"boolean": {
"trueLabel": "Yes",
"falseLabel": "No",
"icons": {
"true": "CheckCircle",
"false": "XCircle",
"warning": "AlertTriangle"
}
},
"sectionNumbering": true,
"toc": {
"enabled": true,
"position": "start",
"maxDepth": 1,
"showPageNumbers": true,
"leaderDots": true,
"excludeSections": []
},
"watermark": {
"enabled": false,
"type": "text",
"value": "CONFIDENTIAL",
"opacity": 0.1,
"rotation": -45,
"position": "center",
"fontSize": 60,
"color": "#000000"
},
"security": {
"enabled": false
},
"distribution": {
"enabled": false,
"mode": "individual",
"fileNameTemplate": "Doc_{BATCHID}"
},
"approvalPanel": {
"enabled": true,
"columns": 2,
"includeDigitalThumbprint": true,
"headingLabel": "Document Approval & Verification",
"headingAlignment": "center",
"headingFontSize": 22,
"user": "{{user}}",
"verificationUrl": "refractlogic.com"
}
}
}Supplementary Annex
Generate a per-line-item supporting documentation section at the end of any REFRACT PDF output. The supplementary_Annex block flattens hierarchical order-line data, fetches and downsamples images, and renders a themed header, notes, and photo grid for every qualifying item - all gated behind a single feature flag.
Feature Flags
Complete reference for options.features - the boolean flags that control which REFRACT Platform capabilities are activated per render request.