Examples

Approval Workflow

A complete recipe for building a multi-stage approval document - request details, a reviewer grid, signature zones, and an appended QR-verified Approval page - using Section, Layout Group, Signature Zones, and Template Settings together.

What You'll Build

A structured approval document that includes:

  • A document header with request number, date, and department
  • A two-column summary block showing requester details alongside request value
  • Per-stage signature zones for each approver in the workflow
  • An optional Approval & Verification page appended at the end with an integrity fingerprint and QR code

This example shows how signature zones fit into a normal section-based layout and how the Approval page is driven entirely from the signatures payload key.


Controls Used

ControlRole in This Template
templateSettingsSets date format and locale for consistent display across the document
sectionGroups the document header, request summary, and each approval stage
layout_groupPlaces requester info and request value side by side
Signature ZonesReserves space for each approver and drives the Approval page

Payload Shape

{
  "templateId": "approval-workflow",
  "templateSettings": { },
  "theme":            { },
  "layoutSchema":     { },

  "requestNumber":  "CAPEX-2026-042",
  "requestDate":    "2026-03-18",
  "department":     "IT Infrastructure",
  "projectName":    "Server Infrastructure Upgrade",
  "requestedBy":    "Michael Torres",
  "requestedAmount": 245000.00,
  "currency":       "USD",
  "justification":  "Replace aging hardware reaching end of support in Q3 2026.",

  "signatures": {
    "preparer": { "name": "Michael Torres", "date": "2026-03-10" },
    "manager":  { "name": "Sarah Kim",      "date": "2026-03-12" },
    "cfo":      { "name": "",               "date": "" }
  }
}

The signatures object drives two things simultaneously: the pre-filled name/date text below each inline signature zone, and the signer grid on the Approval & Verification page.


Step 1 - Template Settings

"templateSettings": {
  "locale":     "en-US",
  "dateFormat": "MMM D, YYYY",
  "timezone":   "America/New_York"
}

Step 2 - Request Summary (Layout Group)

The requester details and financial summary sit side by side. Each side has its own titled section - so layout_group is the right choice over section layout: "2".

{
  "type": "layout_group",
  "props": {
    "columns": [
      { "width": "star" },
      { "width": "star" }
    ],
    "columnGap": 16,
    "verticalAlign": "top"
  }
}

Left column - a section titled "Requested By" with titleIcon: "user" bound to requestedBy, department, requestDate.

Right column - a section titled "Request Value" with titleIcon: "tag" showing requestedAmount (format: currency), currency, and projectName.

Binding field values

Fields inside sections bind to top-level payload keys by their field name. A field with key requestedAmount and format "currency" will read payload.requestedAmount and format it using the locale from templateSettings automatically.


Step 3 - Justification Section

A single full-width section for the free-text justification field. Setting showHeader: true with a light headerFillColor creates a clear visual block that separates this narrative area from the signature zone below.

{
  "type": "section",
  "props": {
    "title":           "Justification",
    "titleIcon":       "file-text",
    "showHeader":      true,
    "headerFillColor": "#F1F5F9"
  }
}

Step 4 - Signature Zones

Each stage in the approval chain gets its own signature node. All three zones live inside a shared section titled "Approvals" so they render as a grouped block.

{
  "type": "section",
  "props": {
    "title":     "Approvals",
    "titleIcon": "check",
    "layout":    "1"
  }
}

Inside that section, each signer zone:

{
  "type": "signature",
  "label": "Prepared By",
  "role": "preparer",
  "fieldType": "sign",
  "width": 220,
  "height": 80,
  "required": true,
  "showName": true,
  "showDate": true,
  "borderStyle": "full"
}
{
  "type": "signature",
  "label": "Manager Approval",
  "role": "manager",
  "fieldType": "sign",
  "width": 220,
  "height": 80,
  "required": true,
  "showName": true,
  "showDate": true,
  "borderStyle": "full"
}
{
  "type": "signature",
  "label": "CFO Sign-Off",
  "role": "cfo",
  "fieldType": "sign",
  "width": 220,
  "height": 80,
  "required": true,
  "showName": true,
  "showDate": true,
  "borderStyle": "full"
}

Role keys must match payload keys

The role value on each zone must exactly match the corresponding key under signatures in the payload. role: "cfo" reads from signatures.cfo. A mismatch means the name and date fields render blank.

Zones are placeholders, not signing tools

Each zone renders a reserved rectangle with an embedded anchor tag (e.g. [[SIGN_CFO|required]]). The actual e-signature is applied by your chosen e-signature platform after the PDF is generated. REFRACT PDF does not process signatures itself.


Step 5 - Approval & Verification Page

The Approval page is appended automatically when approvalPanel.enabled is set in templateSettings. It requires no extra layout work - the rendering engine builds it from the signatures payload object.

"templateSettings": {
  "locale":     "en-US",
  "dateFormat": "MMM D, YYYY",
  "timezone":   "America/New_York",
  "approvalPanel": {
    "enabled":                  true,
    "headingLabel":             "Approval & Verification",
    "verificationUrl":          "https://example.com/verify/{{documentId}}",
    "includeDigitalThumbprint": true
  }
}

The page includes: a signer grid (role, name, date per signatory), document metadata, and - when enabled - an integrity fingerprint and a scannable QR code linking to verificationUrl. approvalPage, title, documentLabel and showQRCode/showThumbprint are not read - the object key is approvalPanel, the heading is headingLabel, the QR code appears automatically whenever verificationUrl is set, and the integrity fingerprint is controlled by includeDigitalThumbprint.

Integrity fingerprint is not a cryptographic signature

The integrity fingerprint is a SHA-256 digest of the document ID, the generated date, and each signer's role, name and required/optional status - not the document's content, layout or amounts, so it does not detect changes to those. It is printed inside the document itself, so it is a consistency reference for the approver list, not proof the document is unaltered. See Signature Zones for the exact input fields and how to verify a document instead using the audit chain.


Complete Payload

{
  "templateId": "approval-workflow",
  "templateSettings": {
    "locale":     "en-US",
    "dateFormat": "MMM D, YYYY",
    "timezone":   "America/New_York",
    "approvalPanel": {
      "enabled":                  true,
      "headingLabel":             "Approval & Verification",
      "verificationUrl":          "https://example.com/verify/{{documentId}}",
      "includeDigitalThumbprint": true
    }
  },
  "theme": {
    "primary": "#1a56db"
  },
  "requestNumber":   "CAPEX-2026-042",
  "requestDate":     "2026-03-18",
  "department":      "IT Infrastructure",
  "projectName":     "Server Infrastructure Upgrade",
  "requestedBy":     "Michael Torres",
  "requestedAmount":  245000.00,
  "currency":        "USD",
  "justification":   "Replace aging hardware reaching end of support in Q3 2026. Current infrastructure cannot support planned capacity growth.",
  "signatures": {
    "preparer": { "name": "Michael Torres", "date": "2026-03-10" },
    "manager":  { "name": "Sarah Kim",      "date": "2026-03-12" },
    "cfo":      { "name": "",               "date": "" }
  }
}

Design Decisions Summary

DecisionWhy
layout_group for summaryRequester info and financial value are independent titled blocks
Boxed section for justificationVisually separates narrative content from structured fields and signatures
Three separate signature nodesEach approver in a multi-stage workflow is a distinct zone with its own role key
approvalPanel in templateSettingsOne configuration key appends the full verification page - no extra layout nodes needed
Empty name/date for pending signersBlank values in signatures still reserve the zone - the platform fills them after signing

Next Steps

On this page