Templates API
Create documents from reusable templates via API.
This guide may not reflect the latest endpoints or parameters. For an always up-to-date reference, see the OpenAPI Reference.
Template Object
A template object contains the following properties:
| Property | Type | Description |
|---|---|---|
id | number | Unique template identifier |
envelopeId | string | Associated envelope ID |
type | string | Template type: PRIVATE or PUBLIC |
visibility | string | Who can view: EVERYONE, ADMIN, MANAGER_AND_ABOVE |
title | string | Template title |
externalId | string | null | Your custom identifier |
publicTitle | string | null | Public-facing title (for public templates) |
publicDescription | string | null | Public-facing description (for public templates) |
userId | number | Owner's user ID |
teamId | number | null | Team ID if team-owned |
folderId | string | null | Folder containing the template |
createdAt | string | ISO 8601 timestamp |
updatedAt | string | ISO 8601 timestamp |
recipients | array | Predefined recipients with roles and fields |
fields | array | Signature and form fields on the template |
templateMeta | object | Email settings, signing options, redirect URL |
directLink | object | null | Direct link configuration if enabled |
Example Template Object
{
"id": 123,
"envelopeId": "envelope_abc123xyz",
"type": "PRIVATE",
"visibility": "EVERYONE",
"title": "Employment Contract",
"externalId": "template-emp-001",
"publicTitle": null,
"publicDescription": null,
"userId": 1,
"teamId": 5,
"folderId": null,
"createdAt": "2025-01-10T08:00:00.000Z",
"updatedAt": "2025-01-10T08:30:00.000Z",
"recipients": [
{
"id": 1,
"email": "employee@example.com",
"name": "Employee",
"role": "SIGNER",
"signingOrder": 1
},
{
"id": 2,
"email": "hr@company.com",
"name": "HR Manager",
"role": "SIGNER",
"signingOrder": 2
}
],
"fields": [
{
"id": 101,
"type": "SIGNATURE",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5,
"recipientId": 1
}
],
"templateMeta": {
"subject": "Your Employment Contract",
"message": "Please review and sign your employment contract.",
"redirectUrl": "https://example.com/welcome"
},
"directLink": null
}List Templates
Retrieve a paginated list of templates.
GET /templateQuery Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
perPage | integer | Results per page (default: 10, max: 100) |
type | string | Filter by type: PRIVATE or PUBLIC |
folderId | string | Filter by folder ID |
orderByColumn | string | Sort field (only createdAt supported) |
orderByDirection | string | Sort direction: asc or desc (default: desc) |
Code Examples
# List all templates
curl -X GET "https://app.documenso.com/api/v2/template" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
# Filter by type and paginate
curl -X GET "https://app.documenso.com/api/v2/template?type=PRIVATE&page=1&perPage=20" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"const API_TOKEN = process.env.DOCUMENSO_API_TOKEN;
const BASE_URL = 'https://app.documenso.com/api/v2';
// List all templates
const response = await fetch(`${BASE_URL}/template`, {
method: 'GET',
headers: {
Authorization: API_TOKEN,
},
});
const { data, pagination } = await response.json();
console.log(`Found ${pagination.totalItems} templates`);
// Filter by type
const privateResponse = await fetch(
`${BASE_URL}/template?type=PRIVATE&page=1&perPage=20`,
{
method: 'GET',
headers: {
Authorization: API_TOKEN,
},
}
);
const privateTemplates = await privateResponse.json();Response
{
"data": [
{
"id": 123,
"envelopeId": "envelope_abc123",
"type": "PRIVATE",
"title": "Employment Contract",
"createdAt": "2025-01-10T08:00:00.000Z",
"updatedAt": "2025-01-10T08:30:00.000Z",
"recipients": [
{
"id": 1,
"email": "employee@example.com",
"name": "Employee",
"role": "SIGNER"
}
]
}
],
"pagination": {
"page": 1,
"perPage": 10,
"totalPages": 3,
"totalItems": 25
}
}Get Template
Retrieve a single template by ID.
GET /template/{templateId}Path Parameters
| Parameter | Type | Description |
|---|---|---|
templateId | number | The template ID |
Code Examples
curl -X GET "https://app.documenso.com/api/v2/template/123" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"const templateId = 123;
const response = await fetch(`https://app.documenso.com/api/v2/template/${templateId}`, {
method: 'GET',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
},
});
const template = await response.json();
console.log(template.title, template.recipients.length);Response
Returns the full template object including recipients, fields, and metadata.
Create Document from Template
Create a new document using a template. This is the primary way to use templates programmatically.
POST /template/useRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | number | Yes | The template ID to use |
recipients | array | Yes | Recipient details (maps to template recipients) |
distributeDocument | boolean | No | If true, immediately send the document to recipients |
externalId | string | No | Your custom identifier for the created document |
folderId | string | No | Folder ID to create the document in |
prefillFields | array | No | Pre-fill field values before sending |
override | object | No | Override template settings for this document |
formValues | object | No | PDF form values to insert |
Recipients Array
Each recipient object must include:
| Field | Type | Required | Description |
|---|---|---|---|
id | number | Yes | The recipient ID from the template |
email | string | Yes | Recipient's email address |
name | string | No | Recipient's display name |
Code Examples
# Create document from template
curl -X POST "https://app.documenso.com/api/v2/template/use" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"recipients": [
{
"id": 1,
"email": "john.doe@example.com",
"name": "John Doe"
},
{
"id": 2,
"email": "jane.smith@company.com",
"name": "Jane Smith"
}
],
"distributeDocument": true,
"externalId": "contract-2025-001"
}'
# Create document with field prefilling
curl -X POST "https://app.documenso.com/api/v2/template/use" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"recipients": [
{
"id": 1,
"email": "john.doe@example.com",
"name": "John Doe"
}
],
"prefillFields": [
{
"id": 101,
"type": "text",
"value": "Senior Software Engineer"
},
{
"id": 102,
"type": "number",
"value": "85000"
},
{
"id": 103,
"type": "date",
"value": "2025-02-01"
}
],
"distributeDocument": true
}'const API_TOKEN = process.env.DOCUMENSO_API_TOKEN;
const BASE_URL = 'https://app.documenso.com/api/v2';
// Create document from template
const response = await fetch(`${BASE_URL}/template/use`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
recipients: [
{
id: 1,
email: 'john.doe@example.com',
name: 'John Doe',
},
{
id: 2,
email: 'jane.smith@company.com',
name: 'Jane Smith',
},
],
distributeDocument: true,
externalId: 'contract-2025-001',
}),
});
const document = await response.json();
console.log('Created document:', document.id);
// Create document with prefilled fields
const prefillResponse = await fetch(`${BASE_URL}/template/use`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
recipients: [
{
id: 1,
email: 'john.doe@example.com',
name: 'John Doe',
},
],
prefillFields: [
{
id: 101,
type: 'text',
value: 'Senior Software Engineer',
},
{
id: 102,
type: 'number',
value: '85000',
},
{
id: 103,
type: 'date',
value: '2025-02-01',
},
],
distributeDocument: true,
}),
});
const prefilledDocument = await prefillResponse.json();Response
Returns the created document object with recipients and signing URLs.
{
"id": "envelope_xyz789",
"type": "DOCUMENT",
"status": "PENDING",
"title": "Employment Contract",
"source": "TEMPLATE",
"externalId": "contract-2025-001",
"recipients": [
{
"id": 1,
"email": "john.doe@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingStatus": "NOT_SIGNED",
"signingUrl": "https://app.documenso.com/sign/abc123"
}
]
}Override Template Settings
When creating a document from a template, you can override various settings:
const response = await fetch(`${BASE_URL}/template/use`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
recipients: [{ id: 1, email: 'signer@example.com', name: 'Signer' }],
override: {
title: 'Custom Document Title',
subject: 'Custom email subject',
message: 'Custom email message body',
timezone: 'America/New_York',
dateFormat: 'MM/dd/yyyy',
redirectUrl: 'https://example.com/custom-redirect',
language: 'de',
typedSignatureEnabled: true,
uploadSignatureEnabled: false,
drawSignatureEnabled: true,
},
distributeDocument: true,
}),
});Override Options
| Field | Type | Description |
|---|---|---|
title | string | Document title |
subject | string | Email subject line |
message | string | Email body message |
timezone | string | Timezone for date fields |
dateFormat | string | Date format string |
redirectUrl | string | URL to redirect after signing |
language | string | Document language code |
typedSignatureEnabled | boolean | Allow typed signatures |
uploadSignatureEnabled | boolean | Allow uploaded signature images |
drawSignatureEnabled | boolean | Allow drawn signatures |
Prefill Fields
Prefill field values when creating a document from a template. This is useful for populating known data before sending.
Supported Field Types
| Type | Value Format | Description |
|---|---|---|
text | string | Text field value |
number | string | Numeric value as string |
date | string (ISO 8601) | Date in YYYY-MM-DD format |
radio | string | Selected option value |
checkbox | array of strings | Array of checked option values |
dropdown | string | Selected dropdown value |
Prefill Field Schema
type PrefillField = {
id: number; // Field ID from template
type: string; // Field type (must match template field)
label?: string; // Optional label override
placeholder?: string; // Optional placeholder (text/number only)
value: string | string[]; // Value to prefill
};Example: Prefill Multiple Field Types
const response = await fetch(`${BASE_URL}/template/use`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
recipients: [{ id: 1, email: 'signer@example.com', name: 'Signer' }],
prefillFields: [
// Text field
{
id: 101,
type: 'text',
value: 'John Doe',
},
// Number field
{
id: 102,
type: 'number',
value: '50000',
},
// Date field
{
id: 103,
type: 'date',
value: '2025-03-15',
},
// Radio field (select one option)
{
id: 104,
type: 'radio',
value: 'full-time',
},
// Checkbox field (select multiple options)
{
id: 105,
type: 'checkbox',
value: ['health', 'dental', '401k'],
},
// Dropdown field
{
id: 106,
type: 'dropdown',
value: 'engineering',
},
],
distributeDocument: true,
}),
});The field type in prefillFields must match the actual field type in the template. A mismatch
will result in an error.
Update Template
Update a template's properties.
POST /template/updateRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | number | Yes | Template ID |
data | object | No | Template properties to update |
meta | object | No | Email and signing settings to update |
Code Examples
curl -X POST "https://app.documenso.com/api/v2/template/update" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"data": {
"title": "Updated Employment Contract",
"visibility": "ADMIN"
},
"meta": {
"subject": "Updated: Your Employment Contract",
"redirectUrl": "https://example.com/updated-redirect"
}
}'const response = await fetch(`${BASE_URL}/template/update`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
data: {
title: 'Updated Employment Contract',
visibility: 'ADMIN',
},
meta: {
subject: 'Updated: Your Employment Contract',
redirectUrl: 'https://example.com/updated-redirect',
},
}),
});
const template = await response.json();Duplicate Template
Create a copy of an existing template.
POST /template/duplicateRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | number | Yes | Template ID |
Code Examples
curl -X POST "https://app.documenso.com/api/v2/template/duplicate" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'const response = await fetch(`${BASE_URL}/template/duplicate`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
}),
});
const duplicatedTemplate = await response.json();
console.log('New template ID:', duplicatedTemplate.id);Delete Template
Delete a template.
POST /template/deleteRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
templateId | number | Yes | Template ID |
Code Examples
curl -X POST "https://app.documenso.com/api/v2/template/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'const response = await fetch(`${BASE_URL}/template/delete`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
}),
});
const { success } = await response.json();Response
{
"success": true
}Direct Link Templates
Direct link templates allow recipients to create and sign documents without requiring you to explicitly create each document. When a recipient visits the direct link, a new document is automatically created from the template.
Create Direct Link
POST /template/direct/create| Field | Type | Required | Description |
|---|---|---|---|
templateId | number | Yes | Template ID |
directRecipientId | number | No | Recipient ID to use as the direct link signer |
curl -X POST "https://app.documenso.com/api/v2/template/direct/create" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"directRecipientId": 1
}'const response = await fetch(`${BASE_URL}/template/direct/create`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
directRecipientId: 1,
}),
});
const directLink = await response.json();
console.log('Direct link token:', directLink.token);
// Share: https://app.documenso.com/d/{token}Response
{
"id": 456,
"token": "abc123xyz",
"templateId": 123,
"directTemplateRecipientId": 1,
"enabled": true,
"createdAt": "2025-01-15T10:00:00.000Z"
}Toggle Direct Link
Enable or disable an existing direct link.
POST /template/direct/togglecurl -X POST "https://app.documenso.com/api/v2/template/direct/toggle" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123,
"enabled": false
}'const response = await fetch(`${BASE_URL}/template/direct/toggle`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
enabled: false,
}),
});
const directLink = await response.json();
console.log('Direct link enabled:', directLink.enabled);Delete Direct Link
POST /template/direct/deletecurl -X POST "https://app.documenso.com/api/v2/template/direct/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'const response = await fetch(`${BASE_URL}/template/direct/delete`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 123,
}),
});
const { success } = await response.json();Custom Document Data
When creating a document from a template, you can replace the template's PDF with a custom PDF by using the customDocumentData parameter. This is useful when you need to generate the PDF dynamically while reusing the template's recipient and field configuration.
To use custom document data:
- Retrieve the template to get the
envelopeItemIdof the PDF you want to replace - Include
customDocumentDatain yourtemplate/userequest, mapping eachenvelopeItemIdto a new file
The field positions from the template are preserved on the new PDF. Ensure the replacement PDF has the same page layout to maintain accurate field placement.
See the OpenAPI Reference for the full request schema.
Template Types
| Type | Description |
|---|---|
PRIVATE | Only accessible by owner and team members |
PUBLIC | Can be shared publicly with a direct link |
Complete Example: Contract Workflow
This example demonstrates a complete workflow for using templates to send contracts.
const API_TOKEN = process.env.DOCUMENSO_API_TOKEN;
const BASE_URL = 'https://app.documenso.com/api/v2';
async function sendEmploymentContract(employeeData: {
email: string;
name: string;
position: string;
salary: number;
startDate: string;
}) {
// 1. Get the template to find recipient and field IDs
const templateResponse = await fetch(`${BASE_URL}/template/456`, {
headers: { Authorization: API_TOKEN },
});
const template = await templateResponse.json();
// 2. Find the employee recipient slot
const employeeRecipient = template.recipients.find(
(r) => r.role === 'SIGNER' && r.signingOrder === 1
);
// 3. Find fields to prefill
const positionField = template.fields.find(
(f) => f.fieldMeta?.label === 'Position'
);
const salaryField = template.fields.find(
(f) => f.fieldMeta?.label === 'Salary'
);
const startDateField = template.fields.find(
(f) => f.type === 'DATE'
);
// 4. Create document from template with prefilled data
const documentResponse = await fetch(`${BASE_URL}/template/use`, {
method: 'POST',
headers: {
Authorization: API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: 456,
recipients: [
{
id: employeeRecipient.id,
email: employeeData.email,
name: employeeData.name,
},
],
prefillFields: [
{
id: positionField.id,
type: 'text',
value: employeeData.position,
},
{
id: salaryField.id,
type: 'number',
value: employeeData.salary.toString(),
},
{
id: startDateField.id,
type: 'date',
value: employeeData.startDate,
},
],
override: {
subject: `Employment Contract for ${employeeData.name}`,
message: `Hi ${employeeData.name},\n\nPlease review and sign your employment contract.`,
},
distributeDocument: true,
externalId: `emp-contract-${Date.now()}`,
}),
});
const document = await documentResponse.json();
return {
documentId: document.id,
signingUrl: document.recipients[0].signingUrl,
};
}
// Usage
const result = await sendEmploymentContract({
email: 'john.doe@example.com',
name: 'John Doe',
position: 'Senior Engineer',
salary: 120000,
startDate: '2025-03-01',
});
console.log('Document created:', result.documentId);
console.log('Signing URL:', result.signingUrl);See Also
- Documents API - Work with created documents
- Recipients API - Manage document recipients
- Fields API - Work with signature and form fields
- Webhooks - Get notified when documents are signed