--- 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'; 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). ## 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 ```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" ```` ```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(); ```` ### 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 ```bash curl -X GET "https://app.documenso.com/api/v2/template/123" \ -H "Authorization: api_xxxxxxxxxxxxxxxx" ``` ```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); ``` ### 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. This endpoint does not support [PDF placeholder parsing](/docs/users/documents/advanced/pdf-placeholders). Use `POST /envelope/create` for placeholder-based field positioning. ``` 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 ```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 }' ```` ```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(); ```` ### 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, }), }); ``` 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/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 ```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" } }' ``` ```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(); ``` --- ## 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 ```bash curl -X POST "https://app.documenso.com/api/v2/template/duplicate" \ -H "Authorization: api_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "templateId": 123 }' ```` ```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); ``` --- ## Delete Template Delete a template. ``` POST /template/delete ```` ### Request Body | Field | Type | Required | Description | | ------------ | ------ | -------- | --------------- | | `templateId` | number | Yes | Template ID | ### Code Examples ```bash curl -X POST "https://app.documenso.com/api/v2/template/delete" \ -H "Authorization: api_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "templateId": 123 }' ```` ```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(); ```` ### 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 | ```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 }' ``` ```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} ```` ### 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 ``` ```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 }' ``` ```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); ``` ### Delete Direct Link ``` POST /template/direct/delete ```` ```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 }' ```` ```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(); ```` --- ## 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