documenso/apps/docs/content/docs/developers/api/templates.mdx

1030 lines
26 KiB
Text

---
title: Templates API
description: Create documents from reusable templates via API.
---
import { Callout } from 'fumadocs-ui/components/callout';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Callout type="warn">
This guide may not reflect the latest endpoints or parameters. For an always up-to-date reference,
see the [OpenAPI Reference](https://openapi.documenso.com).
</Callout>
## 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
```json
{
"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 /template
```
### Query 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
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
# 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"
````
</Tab>
<Tab value="TypeScript">
```typescript
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();
````
</Tab>
</Tabs>
### Response
```json
{
"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
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X GET "https://app.documenso.com/api/v2/template/123" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
```
</Tab>
<Tab value="TypeScript">
```typescript
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);
```
</Tab>
</Tabs>
### 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.
<Callout type="info">
This endpoint does not support [PDF placeholder parsing](/docs/users/documents/advanced/pdf-placeholders). Use `POST /envelope/create` for placeholder-based field positioning.
</Callout>
```
POST /template/use
````
### Request 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
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
# 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
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
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();
````
</Tab>
</Tabs>
### Response
Returns the created document object with recipients and signing URLs.
```json
{
"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:
```typescript
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
```typescript
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
```typescript
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,
}),
});
```
<Callout type="warn">
The field type in `prefillFields` must match the actual field type in the template. A mismatch
will result in an error.
</Callout>
---
## Update Template
Update a template's properties.
```
POST /template/update
```
### Request 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
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
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"
}
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
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();
```
</Tab>
</Tabs>
---
## Duplicate Template
Create a copy of an existing template.
```
POST /template/duplicate
````
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | --------------- |
| `templateId` | number | Yes | Template ID |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/template/duplicate" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
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);
```
</Tab>
</Tabs>
---
## Delete Template
Delete a template.
```
POST /template/delete
````
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | --------------- |
| `templateId` | number | Yes | Template ID |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/template/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
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();
````
</Tab>
</Tabs>
### Response
```json
{
"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 |
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
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
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
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}
````
</Tab>
</Tabs>
### Response
```json
{
"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/toggle
```
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -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
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
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);
```
</Tab>
</Tabs>
### Delete Direct Link
```
POST /template/direct/delete
````
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/template/direct/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"templateId": 123
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
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();
````
</Tab>
</Tabs>
---
## 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:
1. Retrieve the template to get the `envelopeItemId` of the PDF you want to replace
2. Include `customDocumentData` in your `template/use` request, mapping each `envelopeItemId` to 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](https://openapi.documenso.com) 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.
```typescript
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](/docs/developers/api/documents) - Work with created documents
- [Recipients API](/docs/developers/api/recipients) - Manage document recipients
- [Fields API](/docs/developers/api/fields) - Work with signature and form fields
- [Webhooks](/docs/developers/webhooks) - Get notified when documents are signed