Skip to main content

Working with Templates

Templates let you create reusable document structures with predefined signature fields, making it easy to send consistent documents at scale.

When to Use Templates

Use CaseRecommendation
Same document sent frequentlyTemplate - Define once, reuse
Different document each timeDirect upload - Use documentBase64
Consistent field placementTemplate - Predefined positions
Dynamic field positionsAnchor tags - Text-based positioning
High-volume sendingTemplate - Better performance

Template Lifecycle

Creating a Template

Step 1: Upload the Template Document

# Base64 encode your template PDF
TEMPLATE_BASE64=$(base64 -i employment-template.pdf)

curl -X POST "https://api.propper.ai/restapi/v2.1/accounts/{accountId}/templates" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"Employment Contract\",
\"description\": \"Standard employment agreement template\",
\"documents\": [{
\"documentId\": \"1\",
\"name\": \"Employment Contract.pdf\",
\"documentBase64\": \"$TEMPLATE_BASE64\"
}],
\"recipients\": {
\"signers\": [
{
\"roleName\": \"Employee\",
\"recipientId\": \"1\",
\"routingOrder\": \"1\",
\"tabs\": {
\"signHereTabs\": [{
\"documentId\": \"1\",
\"pageNumber\": \"1\",
\"xPosition\": \"100\",
\"yPosition\": \"600\",
\"width\": \"200\",
\"height\": \"50\"
}],
\"dateSignedTabs\": [{
\"documentId\": \"1\",
\"pageNumber\": \"1\",
\"xPosition\": \"350\",
\"yPosition\": \"600\"
}],
\"textTabs\": [{
\"documentId\": \"1\",
\"pageNumber\": \"1\",
\"xPosition\": \"100\",
\"yPosition\": \"200\",
\"tabLabel\": \"employeeName\",
\"width\": \"200\"
}]
}
},
{
\"roleName\": \"Manager\",
\"recipientId\": \"2\",
\"routingOrder\": \"2\",
\"tabs\": {
\"signHereTabs\": [{
\"documentId\": \"1\",
\"pageNumber\": \"1\",
\"xPosition\": \"100\",
\"yPosition\": \"700\"
}]
}
}
]
}
}"

Response:

{
"templateId": "tpl_abc123xyz",
"name": "Employment Contract",
"uri": "/restapi/v2.1/accounts/.../templates/tpl_abc123xyz"
}

Field Types Reference

TypeDescriptionCommon Properties
signHereTabsSignature fieldxPosition, yPosition, width, height
initialHereTabsInitials fieldxPosition, yPosition
dateSignedTabsAuto-filled signing datexPosition, yPosition
textTabsFree-form text inputtabLabel, value, required, width
checkboxTabsCheckboxtabLabel, selected
dropdownTabsDropdown selectiontabLabel, listItems
numberTabsNumeric inputtabLabel, validationPattern
emailTabsEmail inputtabLabel

Field Positioning

Coordinate-Based Positioning

Fields are positioned using x/y coordinates from the bottom-left corner of the page:

┌─────────────────────────────────────┐
│ │ ↑
│ (100, 600) │ │
│ ┌──────────────┐ │ │
│ │ Signature │ │ │ Y increases
│ └──────────────┘ │ │
│ │ │
│ ← X increases → │ │
└─────────────────────────────────────┘
(0, 0) Bottom-left

Use text anchors in your document for dynamic positioning:

{
"signHereTabs": [{
"anchorString": "/sig1/",
"anchorXOffset": "0",
"anchorYOffset": "-10",
"anchorUnits": "pixels"
}]
}

Place /sig1/ in your document where you want the signature field. The anchor text can be hidden using white text on white background.

Anchor Best Practices
  • Use unique anchor strings (e.g., /sig_employee/, /sig_manager/)
  • Include anchors in headers/footers for consistent placement
  • Use negative anchorYOffset to position fields above the anchor

Creating Documents from Templates

curl -X POST "https://api.propper.ai/restapi/v2.1/accounts/{accountId}/envelopes" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tpl_abc123xyz",
"templateRoles": [
{
"roleName": "Employee",
"email": "john.smith@example.com",
"name": "John Smith",
"tabs": {
"textTabs": [{
"tabLabel": "employeeName",
"value": "John Smith"
}]
}
},
{
"roleName": "Manager",
"email": "sarah.manager@company.com",
"name": "Sarah Manager"
}
],
"status": "sent"
}'

Pre-filling Template Fields

Populate text fields with data when creating from a template:

{
"templateId": "tpl_abc123xyz",
"templateRoles": [{
"roleName": "Employee",
"email": "john@example.com",
"name": "John Smith",
"tabs": {
"textTabs": [
{ "tabLabel": "employeeName", "value": "John Smith" },
{ "tabLabel": "startDate", "value": "2024-02-01" },
{ "tabLabel": "salary", "value": "$85,000" },
{ "tabLabel": "department", "value": "Engineering" }
],
"checkboxTabs": [
{ "tabLabel": "benefitsOptIn", "selected": "true" }
]
}
}]
}

Template Variables (Document Placeholders)

Use {{variableName}} placeholders in your PDF template document:

EMPLOYMENT AGREEMENT

This agreement is entered into by {{employeeName}}
with a start date of {{startDate}} and an annual salary of {{salary}}.

Employee Signature: _______________
Date: _______________

Variables are replaced when creating an envelope:

{
"templateId": "tpl_abc123xyz",
"customFields": {
"textCustomFields": [
{ "name": "employeeName", "value": "John Smith" },
{ "name": "startDate", "value": "February 1, 2024" },
{ "name": "salary", "value": "$85,000" }
]
}
}

Listing Templates

curl "https://api.propper.ai/restapi/v2.1/accounts/{accountId}/templates" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Updating Templates

Update an existing template's properties or fields:

curl -X PUT "https://api.propper.ai/restapi/v2.1/accounts/{accountId}/templates/{templateId}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Employment Contract v2",
"description": "Updated employment agreement with new terms"
}'

Best Practices

Template Organization

templates/
├── hr/
│ ├── employment-contract.pdf
│ ├── nda.pdf
│ └── offer-letter.pdf
├── sales/
│ ├── service-agreement.pdf
│ └── sow.pdf
└── legal/
└── master-services-agreement.pdf

Naming Conventions

Use clear, descriptive names:

  • HR - Employment Contract - Full Time
  • Sales - MSA - Enterprise
  • Legal - NDA - Mutual

Version Control

Include version in template names or descriptions:

{
"name": "Employment Contract",
"description": "Version 2.1 - Updated January 2024"
}

Field Validation

Use validation patterns for data integrity:

{
"textTabs": [{
"tabLabel": "ssn",
"validationPattern": "^\\d{3}-\\d{2}-\\d{4}$",
"validationMessage": "Please enter SSN as XXX-XX-XXXX"
}]
}

Next Steps