Skip to Content
GuidesTemplates

Templates

Templates let you define a reusable document layout — signer roles, field positions, and merge variables — so you can generate ready-to-sign documents without reconfiguring fields each time.

How Templates Work

  1. Upload a PDF or DOCX file as the base document
  2. Define signer roles (e.g., “Client”, “Approver”) — these are placeholders that get assigned to real people when you create a document
  3. Place fields on the template and assign each to a signer role
  4. Create documents from the template by mapping real signers to roles

Creating a Template

Template creation follows the same two-step upload flow as documents:

import { KoralaClient } from '@korala/api-client'; import fs from 'fs'; const korala = new KoralaClient({ apiKeyId: 'your-api-key-id', apiSecret: 'your-api-secret', }); // Step 1: Get upload URL const { templateId, uploadUrl, key } = await korala.templates.createUploadUrl({ filename: 'nda-template.pdf', contentType: 'application/pdf', }); // Step 2: Upload the file const pdfBuffer = fs.readFileSync('nda-template.pdf'); await fetch(uploadUrl, { method: 'PUT', body: pdfBuffer, headers: { 'Content-Type': 'application/pdf' }, }); // Step 3: Confirm and set metadata const template = await korala.templates.confirmUpload(templateId, { name: 'NDA Template', description: 'Standard non-disclosure agreement', }); console.log(`Template created: ${template.id}`);

Templates support both PDF and DOCX files. DOCX files are automatically converted to PDF for preview, and merge fields ({{placeholder}}) are detected automatically.

Signer Roles

Signer roles are named placeholders that define who needs to sign, without specifying the actual person. When you create a document from a template, you map real signers to these roles.

Adding Roles

// Add roles with signing order const client = await korala.templates.addSignerRole(templateId, { name: 'Client', signingOrder: 1, }); const approver = await korala.templates.addSignerRole(templateId, { name: 'Approver', signingOrder: 2, });

Managing Roles

// List all roles const roles = await korala.templates.getSignerRoles(templateId); // Update a role await korala.templates.updateSignerRole(templateId, roleId, { name: 'Company Representative', signingOrder: 2, }); // Delete a role await korala.templates.deleteSignerRole(templateId, roleId);

Template Fields

Fields define where signers need to fill in information. Each field is positioned on a specific page and assigned to a signer role.

Adding Fields

// Add a signature field for the Client role await korala.templates.addField(templateId, { signerRoleId: clientRoleId, fieldType: 'signature', pageNumber: 1, xPosition: 100, yPosition: 650, width: 200, height: 50, }); // Add a date field await korala.templates.addField(templateId, { signerRoleId: clientRoleId, fieldType: 'date', pageNumber: 1, xPosition: 350, yPosition: 650, width: 150, height: 30, }); // Add a text field with a merge variable await korala.templates.addField(templateId, { signerRoleId: clientRoleId, fieldType: 'text', pageNumber: 1, xPosition: 100, yPosition: 200, width: 300, height: 30, mergeFieldName: 'company_name', defaultValue: 'Acme Corp', });

Field Types

TypeDescription
signatureDrawn or uploaded signature image
initialsSigner’s initials
dateDate value
textFree-text input
checkboxBoolean checkbox

Managing Fields

// List all fields const fields = await korala.templates.getFields(templateId); // Update field position or assigned role await korala.templates.updateField(templateId, fieldId, { xPosition: 150, yPosition: 700, signerRoleId: newRoleId, }); // Delete a field await korala.templates.deleteField(templateId, fieldId);

DOCX Merge Fields

When you upload a DOCX template, Korala automatically detects {{placeholder}} merge fields in the document text. These are substituted with real values when generating documents.

// Get detected merge fields const mergeFields = await korala.templates.getMergeFields(templateId); console.log(mergeFields); // [ // { name: 'company_name', occurrences: 3 }, // { name: 'effective_date', occurrences: 1 }, // { name: 'client_address', occurrences: 2 }, // ]

Merge fields are only available for DOCX templates. PDF templates use positioned fields instead.

Creating Documents from Templates

Map real signers to template roles and optionally fill merge field variables:

const document = await korala.templates.createDocument(templateId, { name: 'NDA — Acme Corp', signers: [ { roleId: clientRoleId, name: 'Jane Smith', email: '[email protected]', }, { roleId: approverRoleId, name: 'Bob Johnson', email: '[email protected]', }, ], variables: { company_name: 'Acme Corp', effective_date: '2024-03-01', client_address: '123 Main St', }, }); console.log(`Document created: ${document.id}`); console.log(`Status: ${document.status}`); // 'draft'

The created document is in draft status. Send it for signing to start the signing workflow.

Generating PDFs Without Signing

Generate a filled PDF from a template without starting a signing workflow. Useful for previews or non-signing document generation:

const result = await korala.templates.generate(templateId, { variables: { company_name: 'Acme Corp', effective_date: '2024-03-01', }, }); console.log(`Download: ${result.downloadUrl}`);

Managing Templates

// List all templates const templates = await korala.templates.list(); // Get template with full details (roles + fields) const template = await korala.templates.get(templateId); console.log(`Roles: ${template.signerRoles.length}`); console.log(`Fields: ${template.fields.length}`); // Update name, description, or active status await korala.templates.update(templateId, { name: 'Updated NDA Template', description: 'Revised for 2024', isActive: true, }); // Deactivate a template await korala.templates.update(templateId, { isActive: false }); // Delete a template await korala.templates.delete(templateId);

Replacing the Template File

Replace the underlying PDF/DOCX without losing signer roles or field positions:

// Step 1: Get replacement upload URL const { uploadUrl, key } = await korala.templates.replaceFile(templateId, { filename: 'nda-v2.pdf', contentType: 'application/pdf', }); // Step 2: Upload new file await fetch(uploadUrl, { method: 'PUT', body: fs.readFileSync('nda-v2.pdf'), headers: { 'Content-Type': 'application/pdf' }, }); // Step 3: Confirm replacement await korala.templates.confirmReplaceFile(templateId, { key });

After replacing a template file, verify that existing field positions still align with the new document layout.

Last updated on