API v1 is deprecated. For new integrations, please use API v2.
Overview
Templates allow you to create reusable document structures with predefined recipients and fields. Instead of adding recipients and fields every time, you can generate documents from templates and override specific values.
Template Object
{
"id": 123,
"externalId": "template-nda-2024",
"type": "PRIVATE",
"title": "Standard NDA Template",
"userId": 456,
"teamId": 789,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"templateMeta": {
"subject": "Please sign: NDA",
"message": "Please review and sign this NDA.",
"timezone": "America/New_York",
"signingOrder": "PARALLEL"
},
"templateDocumentData": {
"id": "data_abc123",
"type": "S3_PATH",
"data": "s3://bucket/path/to/template.pdf"
},
"Recipient": [
{
"id": 1,
"email": "signer@example.com",
"name": "Template Signer",
"role": "SIGNER",
"signingOrder": null
}
],
"Field": [
{
"id": 1,
"recipientId": 1,
"type": "SIGNATURE",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5
}
]
}
List Templates
Retrieve a paginated list of templates.
Query Parameters
| Parameter | Type | Default | Description |
|---|
page | number | 1 | Page number (1-indexed) |
perPage | number | 10 | Results per page (1-100) |
Code Examples
curl -X GET "https://app.documenso.com/api/v1/templates" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx"
# Paginate
curl -X GET "https://app.documenso.com/api/v1/templates?page=1&perPage=20" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx"
import { initClient } from '@ts-rest/core';
import { ApiContractV1 } from '@documenso/api/v1/contract';
const client = initClient(ApiContractV1, {
baseUrl: 'https://app.documenso.com/api/v1',
baseHeaders: {
authorization: 'Bearer api_xxxxxxxxxxxxxxxx',
},
});
const { status, body } = await client.getTemplates({
query: { page: 1, perPage: 10 },
});
if (status === 200) {
console.log(`Total pages: ${body.totalPages}`);
body.templates.forEach((template) => {
console.log(`${template.id}: ${template.title}`);
});
}
Response
{
"templates": [
{
"id": 123,
"externalId": "template-nda-2024",
"type": "PRIVATE",
"title": "Standard NDA Template",
"userId": 456,
"teamId": 789,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"Recipient": [],
"Field": []
}
],
"totalPages": 3
}
Get Template
Retrieve a single template by ID, including all recipients and fields.
GET /api/v1/templates/:id
Path Parameters
| Parameter | Type | Description |
|---|
id | number | The template ID |
Code Examples
curl -X GET "https://app.documenso.com/api/v1/templates/123" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx"
const { status, body } = await client.getTemplate({
params: { id: '123' },
});
if (status === 200) {
console.log(`Title: ${body.title}`);
console.log(`Recipients: ${body.Recipient.length}`);
console.log(`Fields: ${body.Field.length}`);
}
Response
Returns the full template object including templateMeta, templateDocumentData, Recipient, and Field arrays.
Create Template
Create a new template and get a presigned URL for uploading the PDF.
Request Body
| Field | Type | Required | Description |
|---|
title | string | Yes | Template title |
externalId | string | No | Your custom identifier |
type | string | No | PRIVATE or PUBLIC (default: PRIVATE) |
recipients | array | No | Predefined recipients |
fields | array | No | Predefined fields |
meta | object | No | Email and signing settings |
Code Examples
curl -X POST "https://app.documenso.com/api/v1/templates" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Standard NDA Template",
"externalId": "template-nda-2024",
"type": "PRIVATE"
}'
const { status, body } = await client.createTemplate({
body: {
title: 'Standard NDA Template',
externalId: 'template-nda-2024',
type: 'PRIVATE',
},
});
if (status === 200) {
const { uploadUrl, templateId } = body;
// Upload PDF to presigned URL
await fetch(uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/octet-stream' },
body: pdfBuffer,
});
console.log(`Template created: ${templateId}`);
}
Response
{
"uploadUrl": "https://s3.amazonaws.com/bucket/presigned-url...",
"templateId": 123
}
After creating a template, upload your PDF to the uploadUrl using a PUT request with Content-Type: application/octet-stream.
Delete Template
Delete a template.
DELETE /api/v1/templates/:id
Code Examples
curl -X DELETE "https://app.documenso.com/api/v1/templates/123" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx"
const { status, body } = await client.deleteTemplate({
params: { id: '123' },
body: null,
});
if (status === 200) {
console.log(`Deleted template ${body.id}`);
}
Generate Document from Template
Create a new document from an existing template. This is the recommended way to use templates in v1.
POST /api/v1/templates/:templateId/generate-document
Path Parameters
| Parameter | Type | Description |
|---|
templateId | number | The template ID |
Request Body
| Field | Type | Required | Description |
|---|
title | string | No | Override template title |
externalId | string | No | Your custom identifier |
folderId | string | No | Folder to create document in |
recipients | array | No | Override template recipients |
meta | object | No | Override email/signing settings |
authOptions | object | No | Authentication options |
formValues | object | No | Prefill form field values |
prefillFields | array | No | Prefill specific fields |
Recipients Override Schema
When providing recipients, you must match them to template recipients by ID:
{
"recipients": [
{
"id": 1, // Template recipient ID
"email": "actual@example.com",
"name": "Actual Name",
"signingOrder": 1
}
]
}
Code Examples
curl -X POST "https://app.documenso.com/api/v1/templates/123/generate-document" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "NDA for John Doe",
"externalId": "nda-john-2024",
"recipients": [
{
"id": 1,
"email": "john@example.com",
"name": "John Doe"
}
],
"meta": {
"subject": "Please sign: NDA",
"redirectUrl": "https://example.com/thank-you"
}
}'
const { status, body } = await client.generateDocumentFromTemplate({
params: { templateId: '123' },
body: {
title: 'NDA for John Doe',
externalId: 'nda-john-2024',
recipients: [
{
id: 1, // Template recipient ID
email: 'john@example.com',
name: 'John Doe',
},
],
meta: {
subject: 'Please sign: NDA',
redirectUrl: 'https://example.com/thank-you',
},
},
});
if (status === 200) {
const { documentId, recipients } = body;
console.log(`Document created from template: ${documentId}`);
console.log('Signing URLs:');
recipients.forEach((r) => {
console.log(` ${r.email}: ${r.signingUrl}`);
});
}
Response
{
"documentId": 456,
"externalId": "nda-john-2024",
"recipients": [
{
"recipientId": 10,
"name": "John Doe",
"email": "john@example.com",
"token": "abc123xyz",
"role": "SIGNER",
"signingOrder": null,
"signingUrl": "https://app.documenso.com/sign/abc123xyz"
}
]
}
The document is created in DRAFT status. You must still send it using the Send Document endpoint.
Complete Template Workflow
import { initClient } from '@ts-rest/core';
import { ApiContractV1 } from '@documenso/api/v1/contract';
import fs from 'fs';
const client = initClient(ApiContractV1, {
baseUrl: 'https://app.documenso.com/api/v1',
baseHeaders: {
authorization: 'Bearer api_xxxxxxxxxxxxxxxx',
},
});
async function createAndUseTemplate() {
// 1. Create template
const createResponse = await client.createTemplate({
body: {
title: 'Standard NDA Template',
type: 'PRIVATE',
},
});
if (createResponse.status !== 200) {
throw new Error('Failed to create template');
}
const { uploadUrl, templateId } = createResponse.body;
// 2. Upload PDF
const pdfBuffer = fs.readFileSync('./nda-template.pdf');
await fetch(uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/octet-stream' },
body: pdfBuffer,
});
console.log(`Template created: ${templateId}`);
// 3. Get template to find recipient IDs
const getResponse = await client.getTemplate({
params: { id: templateId.toString() },
});
const templateRecipientId = getResponse.body.Recipient[0].id;
// 4. Generate document from template
const generateResponse = await client.generateDocumentFromTemplate({
params: { templateId: templateId.toString() },
body: {
title: 'NDA for John Doe',
recipients: [
{
id: templateRecipientId,
email: 'john@example.com',
name: 'John Doe',
},
],
},
});
const { documentId } = generateResponse.body;
// 5. Send the document
await client.sendDocument({
params: { id: documentId.toString() },
body: { sendEmail: true },
});
console.log('Document sent!');
}
createAndUseTemplate().catch(console.error);
Template Types
| Type | Description |
|---|
PRIVATE | Only you and your team can use this template |
PUBLIC | Template can be shared publicly (if enabled) |
Prefilling Fields
You can prefill field values when generating a document from a template:
const { status, body } = await client.generateDocumentFromTemplate({
params: { templateId: '123' },
body: {
recipients: [
{
id: 1,
email: 'john@example.com',
name: 'John Doe',
},
],
// Prefill specific fields
prefillFields: [
{
id: 'field_123',
value: 'Senior Developer',
},
{
id: 'field_456',
value: 'Engineering',
},
],
// Or use form values for all form fields
formValues: {
jobTitle: 'Senior Developer',
department: 'Engineering',
startDate: '2024-01-15',
},
},
});
Best Practices
1. Use External IDs
Always set externalId to track which business entity the template represents:
{
title: 'Standard NDA',
externalId: 'template-nda-v2024.1',
}
Include comprehensive metadata in templates:
{
title: 'Employee Onboarding',
meta: {
subject: 'Welcome to {company.name}!',
message: 'Please review and sign these onboarding documents.',
timezone: 'America/New_York',
signingOrder: 'SEQUENTIAL',
},
}
3. Recipient Mapping
When generating documents, always verify template recipient IDs:
// First, get the template
const template = await client.getTemplate({ params: { id: '123' } });
// Map recipients by role or order
const signerRecipient = template.body.Recipient.find(r => r.role === 'SIGNER');
// Generate document with correct recipient mapping
await client.generateDocumentFromTemplate({
params: { templateId: '123' },
body: {
recipients: [
{
id: signerRecipient.id,
email: 'actual@example.com',
name: 'Actual Name',
},
],
},
});
See Also