Template Components

Payload Structure

Complete reference for the top-level VaultPDF JSON payload. Covers templateId, metadata, theme, header, footer, layoutSchema, templateSettings, hierarchyRules, and all other recognized top-level keys.

Overview

Every VaultPDF document starts as a single JSON object. The rendering engine reads a fixed set of top-level keys to configure the document; all remaining keys are treated as data and fed to the content renderer.

{
  "templateId":       "...",
  "metadata":         { },
  "theme":            { },
  "templateSettings": { },
  "hierarchyRules":   { },
  "watermarkText":    "...",
  "layoutSchema":     { },
  "sampleData":       { },

  "customerName":  "Acme Corp",
  "salesOrders":   [ ]
}

The .vpdf File Format

A .vpdf file is a plain JSON file saved with a .vpdf extension - there is no binary encoding or compression. It is the portable, self-contained export of a VaultPDF template: everything the rendering engine needs to produce a PDF, bundled into one file.

What's Inside

A .vpdf file contains exactly the same top-level keys described in this document, plus extra metadata catalog fields (displayName, category, tags, complexity, thumbnail) that power the template library browser.

{
  "templateId": "invoice-standard-v2",
  "metadata": {
    "templateId": "invoice-standard-v2",
    "displayName": "Invoice Standard v2",
    "description": "Enterprise-grade invoice with logo and line-item table.",
    "category": "finance",
    "tags": ["invoice", "finance"],
    "version": "2.0",
    "author": "VaultPDF Team",
    "engineVersion": "1.0.0",
    "renderMode": "flow",
    "lastModified": "2026-02-13"
  },
  "theme": { },
  "templateSettings": { },
  "layoutSchema": { },
  "hierarchyRules": { },
  "sampleData": { }
}

How .vpdf Files Are Used

ContextBehaviour
Designer - ExportThe "Export" button in the Designer saves the current template as {templateName}.vpdf. All schema, theme, and settings are embedded.
Designer - ImportDrop or pick a .vpdf file to reload a template. The Designer restores schema, theme, templateSettings, sampleData, and hierarchyRules in one step.
Server renderingThe rendering engine resolves the incoming templateId and reads {templateId}.vpdf from the server's templates/ folder.
Render API callSend the .vpdf JSON directly as the request body, merging your live data at the top level. The sampleData key is ignored at render time - it is only used for Designer preview.

Sending a .vpdf to the Render API

Read the .vpdf file, add your runtime data keys at the top level alongside the existing template keys, and POST the merged object:

{
  "templateId": "invoice-standard-v2",
  "metadata": { },
  "theme": { },
  "templateSettings": { },
  "layoutSchema": { },

  "companyName": "Acme Corp",
  "customerName": "Beta Industries",
  "invoiceNumber": "INV-1042",
  "invoiceLines": [
    { "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99 }
  ]
}

sampleData at Render Time

sampleData is only read by the Designer for live preview. At render time the engine reads data from the runtime keys you supply at the top level - it never renders sampleData into the final PDF.


Top-Level Key Reference

KeyRequiredDescription
templateIdRequiredStable identifier for the template. Used by the API and the "Prepare for Production" checker.
metadataRecommendedHuman-readable document meta - version, description, author, etc.
themeRecommendedColor palette and typography for the document. Falling back omits explicit colors across tables and headers.
templateSettingsRecommendedLocale, date formats, currency, boolean labels, TOC, watermark, security. See Template Settings.
hierarchyRulesOptionalPer-level styling, computations, and column manifests for hierarchical tables. See Hierarchical Table.
watermarkTextOptionalRuntime override for watermark text. Takes precedence over templateSettings.watermark.value.
layoutSchemaOptionalDesigner-generated schema (SchemaV2). When present this path takes precedence over content[].
contentOptionalLegacy document content array. Used when layoutSchema is absent.
sampleDataOptionalExample payload for template preview and the "Prepare for Production" checker.

Reserved Key Names

Keys that start with _ and the reserved names theme, activeTheme, metadata, hierarchyRules, __meta, __schema are excluded from adaptive table columns automatically. Your data keys never conflict with these control keys as long as you avoid those names.


templateId

A stable, unique string that identifies the template. Required for production export and API calls.

  • Resolved first from the top-level templateId key.
  • Falls back to metadata.templateId if the top-level key is absent.
  • Must be a non-empty string.
{
  "templateId": "sales-order-v2",
  "metadata": {
    "version": "2.1"
  }
}

Tip

Use a consistent slug-style identifier (e.g. "invoice-us-en", "shipment-manifest") so it remains stable across payload versions.


metadata

Optional free-form object for human-readable document meta. None of the fields are structurally required, but version is used by the integrity checker.

PropertyTypeDescription
metadata.templateIdstringFallback template identifier when the top-level templateId key is absent.
metadata.versionstringTemplate version string (e.g. "1.0", "2.3.1"). Used by the integrity checker - a warning is emitted when absent.
metadata.descriptionstringHuman-readable description of the template's purpose.
metadata.authorstringTemplate author or team name.
metadata.createdAtstringISO date string recording when the template was created.
metadata.tagsstring[]Free-form tags for categorization.
{
  "metadata": {
    "templateId": "sales-order-v2",
    "version": "2.1",
    "description": "Sales order confirmation for US domestic accounts.",
    "author": "VaultPDF Team",
    "createdAt": "2026-01-15",
    "tags": ["sales", "order", "us", "domestic"]
  }
}

theme

The theme object supplies the visual identity for the entire document. Colors defined here propagate automatically to table headers, section title accents, border lines, zebra-stripe rows, and all "theme.*" token references in node props.

Structure

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#1E3A5F",
      "secondary":     "#2D6A9F",
      "headerShade":   "#F1F5F9",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    },
    "typography": {
      "bodyFont":    "Inter",
      "headingFont": "Inter"
    }
  }
}

theme.type

ValueDescription
"modern"Clean sans-serif enterprise style with lighter tints auto-generated from primary.
"formal"More structured layout with slightly higher contrast.
"custom"All palette values taken literally - no automatic tint generation.

theme.colors Properties

All color values must be valid 3- or 6-digit hex strings (e.g. "#1E3A5F" or "#FFF").

PropertyDescriptionEffect when missing
primaryPrimary brand color. Used for table header fills and section title accents.Falls back to #1A73E8.
secondarySecondary accent color. Used for tints and highlights.Auto-derived from primary.
headerShadeLight background tint used in key-value sections and sub-headers.Auto-derived from primary.
textOnPrimaryText and icon color rendered on top of primary-filled cells.Auto-computed via contrast ratio.
textOnShadeDefault body text and label color.Falls back to #333333.
borderColorLine color for table borders, separators, and section outlines.Falls back to #E5E7EB.
stripeShadeFill color for zebra-striped table rows.Falls back to #F9FAFB.

Auto-Generated Colors

When theme.colors.primary is supplied and theme.type is "modern" or "formal", VaultPDF auto-generates secondary, headerShade, textOnPrimary, textOnShade, and stripeShade using a perceptual contrast algorithm. You only need to override them explicitly when the auto-generated values don't match your brand.

theme.typography

PropertyTypeDefaultDescription
typography.bodyFontstring"Inter"Font family for body text and table content. Must be registered in the VaultPDF font registry.
typography.headingFontstring"Inter"Font family for section headings and table headers.

Theme Tokens

Node props throughout the Designer accept "theme.*" string tokens instead of raw hex values. The renderer resolves them at render time from the active palette so swapping the theme object automatically recolors the entire document.

TokenResolves to
"theme.primary"theme.colors.primary
"theme.secondary"theme.colors.secondary
"theme.headerShade"theme.colors.headerShade
"theme.textOnPrimary"theme.colors.textOnPrimary
"theme.textOnShade"theme.colors.textOnShade
"theme.borderColor"theme.colors.borderColor
"theme.stripeShade"theme.colors.stripeShade

Applying a token in a field node prop:

{
  "type": "field",
  "props": {
    "label": "Customer",
    "path": "customerName",
    "labelFillColor": "theme.primary",
    "labelTextColor": "theme.textOnPrimary",
    "labelStyled": true
  }
}

Minimal (primary only - let engine auto-generate the rest):

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary": "#1E3A5F"
    }
  }
}

Full override (every color explicit):

{
  "theme": {
    "type": "custom",
    "colors": {
      "primary":       "#1E3A5F",
      "secondary":     "#2D6A9F",
      "headerShade":   "#F1F5F9",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    },
    "typography": {
      "bodyFont": "Inter"
    }
  }
}

Warm amber brand:

{
  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#B45309",
      "textOnPrimary": "#FFFFFF",
      "borderColor":   "#FDE68A"
    }
  }
}

The header is a Designer node of type: "header" inside layoutSchema. When present and visible is not false, it repeats on every page in the top margin area. The page's top content margin is automatically increased to prevent content from overlapping the header.

Header Node Props

PropertyTypeDefaultDescription
titlestring"Document"Main heading text. Supports {FIELD} tokens.
subtitlestringnoneSecondary line below the title.
textColorstring"theme.textOnShade"Color for title and subtitle text. Accepts hex or "theme.*" token.
fontSizenumber18Font size (pt) for the title text.
subtitleFontSizenumber10Font size (pt) for the subtitle text.
alignment"left" | "center" | "right""left"Horizontal alignment of the title block (used when no logo is present).
titleLayout"combined" | "split" | "split-reverse""combined""combined" stacks title and subtitle. "split" puts them in a two-column row (title left, subtitle right). "split-reverse" reverses the order.
backgroundstringnoneHeader area background fill. Accepts hex or "theme.*" token.
borderStyle"solid" | "dashed" | "none""none"Style of the border line drawn below the header.
borderColorstring"#E2E8F0"Color of the header border line.
borderWidthnumber1Width (pt) of the header border line.
paddingVnumber6Vertical padding (pt) inside the header area. Increasing this also increases the top content margin.
visiblebooleantrueWhen false, no header is rendered and top content margin returns to the default 40pt.

Logo Props

PropertyTypeDefaultDescription
showLogobooleanfalseEnable logo rendering in the header.
logoType"svg" | "image""svg""svg" uses an inline SVG string; "image" uses a base64-encoded raster image.
logoSvgstringnoneInline SVG string for the logo (used when logoType: "svg").
logoBase64stringnoneBase64-encoded PNG/JPEG (used when logoType: "image").
logoWidthnumber120Rendered width (pt) of the logo. Height scales proportionally.
logoAlignment"left" | "center" | "right""left"Alignment of the logo within its column.
logoLayout"logo-left-title-right" | "title-left-logo-right" | "title-center""logo-left-title-right"Layout of logo and title within the header row.

Title + subtitle, no logo:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "Sales Order Confirmation",
    "subtitle": "{{companyName}}",
    "textColor": "#1E293B",
    "fontSize": 20,
    "subtitleFontSize": 11,
    "alignment": "left",
    "borderStyle": "solid",
    "borderColor": "#CBD5E1",
    "borderWidth": 0.5,
    "paddingV": 8
  }
}

Logo left, title right:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "{{companyName}}",
    "subtitle": "Sales Order Confirmation",
    "textColor": "#1E293B",
    "showLogo": true,
    "logoType": "svg",
    "logoSvg": "<svg ...>...</svg>",
    "logoWidth": 100,
    "logoLayout": "logo-left-title-right",
    "borderStyle": "solid",
    "borderColor": "#E2E8F0",
    "paddingV": 6
  }
}

Title left, subtitle right (split layout):

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "Acme Corporation",
    "subtitle": "Invoice #{{invoiceNumber}}",
    "titleLayout": "split",
    "textColor": "#1E293B",
    "fontSize": 16,
    "subtitleFontSize": 12,
    "borderStyle": "solid",
    "borderColor": "#CBD5E1",
    "paddingV": 8
  }
}

Themed background:

{
  "type": "header",
  "id": "header-1",
  "props": {
    "title": "{{documentTitle}}",
    "textColor": "theme.textOnPrimary",
    "background": "theme.primary",
    "fontSize": 18,
    "paddingV": 10
  }
}

The footer is a Designer node of type: "footer" inside layoutSchema. When present and visible is not false, it renders at the bottom of every page via the document engine's footer callback - completely outside the content flow, so it never pushes content to a new page.

PropertyTypeDefaultDescription
textstring""Left-side footer text. Supports {FIELD} tokens.
textColorstring"theme.textOnShade"Color for footer text and page number. Accepts hex or "theme.*" token.
showPageNumbersbooleantrueShow Page X of Y right-aligned in the footer. Set to false to suppress page numbers.
fontSizenumber9Font size (pt) for footer text and page numbers.
backgroundstringnoneFooter area background fill. Accepts hex or "theme.*" token.
borderStyle"solid" | "dashed" | "none""none"Style of the border line drawn above the footer.
borderColorstring"theme.borderColor"Color of the footer border line.
borderWidthnumber0.5Width (pt) of the footer border line.
paddingVnumber4Vertical padding (pt) inside the footer area.
visiblebooleantrueWhen false, no footer is rendered.

Text + page numbers:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "Confidential - Acme Corp",
    "textColor": "#6B7280",
    "showPageNumbers": true,
    "fontSize": 9,
    "borderStyle": "solid",
    "borderColor": "#E5E7EB",
    "borderWidth": 0.5,
    "paddingV": 4
  }
}

Dynamic text from payload:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "Order: {orderNumber}  |  Customer: {customerName}",
    "textColor": "#6B7280",
    "showPageNumbers": true,
    "fontSize": 8
  }
}

Themed background footer:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "text": "{{companyName}}",
    "textColor": "theme.textOnPrimary",
    "background": "theme.primary",
    "showPageNumbers": true,
    "fontSize": 9,
    "paddingV": 6
  }
}

No footer:

{
  "type": "footer",
  "id": "footer-1",
  "props": {
    "visible": false
  }
}

layoutSchema

layoutSchema is the Designer-generated schema (SchemaV2 format). When this key is present, the rendering engine uses it as the primary rendering path instead of content[].

Structure

{
  "layoutSchema": {
    "schemaVersion": 2,
    "rootId": "root-1",
    "nodes": {
      "root-1": {
        "id": "root-1",
        "type": "root",
        "children": ["header-1", "section-1", "footer-1"]
      },
      "header-1": {
        "id": "header-1",
        "type": "header",
        "props": { "title": "{{documentTitle}}" }
      },
      "section-1": {
        "id": "section-1",
        "type": "section",
        "props": { "title": "Customer Details" },
        "children": ["field-1", "field-2"]
      },
      "field-1": {
        "id": "field-1",
        "type": "field",
        "props": { "label": "Name", "path": "customerName" }
      },
      "field-2": {
        "id": "field-2",
        "type": "field",
        "props": { "label": "Account #", "path": "accountNumber" }
      },
      "footer-1": {
        "id": "footer-1",
        "type": "footer",
        "props": { "text": "Confidential", "showPageNumbers": true }
      }
    }
  }
}

Supported Node Types in layoutSchema

Node typeDescription
"root"Root container. Contains children referencing all top-level nodes in document order.
"header"Repeating page header (title, subtitle, logo). See Header.
"footer"Repeating page footer (text, page numbers). See Footer.
"section"Content section with optional title, accent color, box model, and column layout.
"layout_group"Multi-column layout container. Children are rendered as side-by-side columns.
"field"Key-value field with label and data path binding.
"text"Plain text or data-bound text block.
"table"Data-bound table with column definitions, grouping, and aggregates.
"hierarchical_table"Multi-level nested table. Delegates to the Universal Adaptive Renderer.
"spacer_separator"Visual divider or vertical space gap.
"signature"Signature/initials/date/check capture zone.

watermarkText

A runtime override for the watermark value. When present, it takes precedence over templateSettings.watermark.value.

This is the preferred way to inject dynamic watermark text from the API without re-publishing the template.

{
  "watermarkText": "DRAFT",
  "templateSettings": {
    "watermark": {
      "enabled": true,
      "type": "text",
      "opacity": 0.1,
      "rotation": -45,
      "position": "center"
    }
  }
}

sampleData

Optional object containing representative sample values for every data field in the template. Used by:

  • The Designer's live preview to render a realistic-looking document.
  • The "Prepare for Production" integrity checker (emits a warning when absent).
{
  "sampleData": {
    "documentTitle": "Sales Order Confirmation",
    "customerName": "Acme Corp",
    "orderNumber": "SO-1001",
    "orderDate": "2026-03-15",
    "salesOrders": [
      {
        "partNumber": "P-101",
        "description": "Widget Alpha",
        "qty": 5,
        "unitPrice": 49.99
      }
    ]
  }
}

Full Payload Example

A complete, minimal-but-realistic VaultPDF payload combining all top-level keys. Copy, adjust the templateId and data, and send to the render API.

{
  "templateId": "sales-order-v2",

  "metadata": {
    "version": "2.1",
    "description": "Sales order confirmation - US domestic",
    "author": "VaultPDF Team"
  },

  "theme": {
    "type": "modern",
    "colors": {
      "primary":       "#1E3A5F",
      "textOnPrimary": "#FFFFFF",
      "textOnShade":   "#1E293B",
      "borderColor":   "#CBD5E1",
      "stripeShade":   "#F8FAFC"
    }
  },

  "templateSettings": {
    "timezone":   "America/Chicago",
    "locale":     "en-US",
    "dateFormat": "MMM D, YYYY",
    "currency":   { "code": "USD", "symbol": "$", "position": "before" },
    "toc":        { "enabled": false },
    "watermark":  { "enabled": false }
  },

  "watermarkText": "",

  "layoutSchema": {
    "schemaVersion": 2,
    "rootId": "root-1",
    "nodes": {
      "root-1": {
        "id": "root-1",
        "type": "root",
        "children": ["header-1", "section-customer", "table-orders", "footer-1"]
      },
      "header-1": {
        "id": "header-1",
        "type": "header",
        "props": {
          "title": "Sales Order Confirmation",
          "subtitle": "{{companyName}}",
          "textColor": "#1E293B",
          "fontSize": 20,
          "borderStyle": "solid",
          "borderColor": "#CBD5E1",
          "paddingV": 8
        }
      },
      "section-customer": {
        "id": "section-customer",
        "type": "section",
        "props": { "title": "Customer Details", "showHeader": true },
        "children": ["field-name", "field-order", "field-date"]
      },
      "field-name": {
        "id": "field-name",
        "type": "field",
        "props": { "label": "Customer", "path": "customerName", "labelStyled": true }
      },
      "field-order": {
        "id": "field-order",
        "type": "field",
        "props": { "label": "Order #", "path": "orderNumber", "labelStyled": true }
      },
      "field-date": {
        "id": "field-date",
        "type": "field",
        "props": { "label": "Order Date", "path": "orderDate", "format": "date", "labelStyled": true }
      },
      "table-orders": {
        "id": "table-orders",
        "type": "hierarchical_table",
        "props": {
          "title": "Order Lines",
          "dataSource": "{{lines}}"
        }
      },
      "footer-1": {
        "id": "footer-1",
        "type": "footer",
        "props": {
          "text": "Confidential - {{companyName}}",
          "textColor": "#6B7280",
          "showPageNumbers": true,
          "fontSize": 9,
          "borderStyle": "solid",
          "borderColor": "#E5E7EB"
        }
      }
    }
  },

  "sampleData": {
    "companyName": "Acme Corp",
    "customerName": "Beta Industries",
    "orderNumber": "SO-1001",
    "orderDate": "2026-03-15",
    "lines": [
      { "partNumber": "P-101", "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99 }
    ]
  },

  "companyName": "Acme Corp",
  "customerName": "Beta Industries",
  "orderNumber": "SO-1001",
  "orderDate": "2026-03-15",
  "lines": [
    { "partNumber": "P-101", "description": "Widget Alpha", "qty": 5,  "unitPrice": 49.99 },
    { "partNumber": "P-102", "description": "Gadget Beta",  "qty": 2,  "unitPrice": 129.00 }
  ]
}

On this page