From eeae0e1e02e9217b1c1d2243571ee9bee33b97c3 Mon Sep 17 00:00:00 2001 From: ephraimduncan Date: Thu, 30 Jul 2026 21:38:02 +0000 Subject: [PATCH] docs(api): make templates and teams pages envelope-first - lead templates page with POST /envelope/use and /envelope/distribute; label /template/* deprecated - legacy /template/use returns no signingUrl; document the real responses - teams page: /team/* REST endpoints are not exposed; reframe around team-scoped tokens - fix fabricated pagination wrappers; replace false Teams API card on the index page --- .../content/docs/developers/api/index.mdx | 4 +- .../content/docs/developers/api/teams.mdx | 61 ++-- .../content/docs/developers/api/templates.mdx | 287 ++++++++++++++++-- 3 files changed, 281 insertions(+), 71 deletions(-) diff --git a/apps/docs/content/docs/developers/api/index.mdx b/apps/docs/content/docs/developers/api/index.mdx index e8d7139eb..ac64de966 100644 --- a/apps/docs/content/docs/developers/api/index.mdx +++ b/apps/docs/content/docs/developers/api/index.mdx @@ -60,8 +60,8 @@ Authorization: api_xxxxxxxxxxxxxxxx href="/docs/developers/api/templates" /> diff --git a/apps/docs/content/docs/developers/api/teams.mdx b/apps/docs/content/docs/developers/api/teams.mdx index 99d708b41..55d1ac3e5 100644 --- a/apps/docs/content/docs/developers/api/teams.mdx +++ b/apps/docs/content/docs/developers/api/teams.mdx @@ -1,44 +1,29 @@ --- -title: Teams API -description: Manage team resources, documents, and templates with team-scoped API tokens. +title: Team-Scoped API Access +description: Use team-scoped API tokens with document and template envelopes. --- import { Callout } from 'fumadocs-ui/components/callout'; import { Step, Steps } from 'fumadocs-ui/components/steps'; 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). -## Team Object +## Team Context -A team object contains the following properties: + + The V2 REST API does not expose `/team/*` endpoints. Create and manage teams, members, and team + settings in the Documenso web application. This page explains how a team-scoped token applies + that team context to supported API resources. + -| Property | Type | Description | -| ----------------- | -------------- | --------------------------------------------------- | -| `id` | number | Unique team identifier | -| `name` | string | Team display name | -| `url` | string | Unique team URL slug | -| `createdAt` | string | ISO 8601 timestamp | -| `avatarImageId` | string \| null | ID of the team's avatar image | -| `organisationId` | string | ID of the parent organisation | -| `currentTeamRole` | string | Your role in the team: `ADMIN`, `MANAGER`, `MEMBER` | - -### Example Team Object - -```json -{ - "id": 123, - "name": "Engineering", - "url": "engineering", - "createdAt": "2025-01-15T10:30:00.000Z", - "avatarImageId": null, - "organisationId": "org_abc123", - "currentTeamRole": "ADMIN" -} -``` +The API resolves the team from your token. You do not pass a team ID when creating, listing, or +using envelopes. The token's team ID determines which resources the request can access. ## Team-Scoped API Tokens @@ -174,8 +159,8 @@ const response = await fetch('https://app.documenso.com/api/v2/envelope', { }, }); -const { data, pagination } = await response.json(); -console.log(`Found ${pagination.totalItems} team documents`); +const { data, count } = await response.json(); +console.log(`Found ${count} team documents`); ```` @@ -190,10 +175,11 @@ Templates created with a team token are shared across the team. ```bash -curl -X POST "https://app.documenso.com/api/v2/template/create" \ +curl -X POST "https://app.documenso.com/api/v2/envelope/create" \ -H "Authorization: api_team_xxxxxxxxxxxxxxxx" \ -H "Content-Type: multipart/form-data" \ -F 'payload={ + "type": "TEMPLATE", "title": "NDA Template", "recipients": [ { @@ -223,6 +209,7 @@ curl -X POST "https://app.documenso.com/api/v2/template/create" \ const form = new FormData(); const payload = { + type: 'TEMPLATE', title: 'NDA Template', recipients: [ { @@ -249,7 +236,7 @@ form.append('files', fs.createReadStream('./nda-template.pdf'), { contentType: 'application/pdf', }); -const response = await fetch('https://app.documenso.com/api/v2/template/create', { +const response = await fetch('https://app.documenso.com/api/v2/envelope/create', { method: 'POST', headers: { Authorization: TEAM_API_TOKEN, @@ -257,8 +244,8 @@ const response = await fetch('https://app.documenso.com/api/v2/template/create', body: form, }); -const template = await response.json(); -console.log('Created team template:', template.id); +const { id } = await response.json(); +console.log('Created team template envelope:', id); ```` @@ -268,14 +255,14 @@ console.log('Created team template:', template.id); ```bash -curl -X GET "https://app.documenso.com/api/v2/template" \ +curl -X GET "https://app.documenso.com/api/v2/envelope?type=TEMPLATE" \ -H "Authorization: api_team_xxxxxxxxxxxxxxxx" ```` ```typescript -const response = await fetch('https://app.documenso.com/api/v2/template', { +const response = await fetch('https://app.documenso.com/api/v2/envelope?type=TEMPLATE', { method: 'GET', headers: { Authorization: TEAM_API_TOKEN, @@ -341,8 +328,8 @@ const legalResponse = await fetch('https://app.documenso.com/api/v2/envelope?sta }); const legalDocs = await legalResponse.json(); -console.log(`Sales team: ${salesDocs.pagination.totalItems} pending`); -console.log(`Legal team: ${legalDocs.pagination.totalItems} completed`); +console.log(`Sales team: ${salesDocs.count} pending`); +console.log(`Legal team: ${legalDocs.count} completed`); ``` ## Error Responses diff --git a/apps/docs/content/docs/developers/api/templates.mdx b/apps/docs/content/docs/developers/api/templates.mdx index b3f52e146..2d3675100 100644 --- a/apps/docs/content/docs/developers/api/templates.mdx +++ b/apps/docs/content/docs/developers/api/templates.mdx @@ -13,7 +13,194 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs'; see the [OpenAPI Reference](https://openapi.documenso.com). -## Template Object +## Use a Template Envelope + +New integrations should create a document from a template envelope with the Envelope API. + +``` +POST /envelope/use +Content-Type: multipart/form-data +``` + +The request uses `multipart/form-data`: + +| Part | Type | Required | Description | +| --------- | ------- | -------- | ------------------------------------------------------------------ | +| `payload` | JSON | Yes | Template envelope ID, recipient details, and document settings | +| `files` | File(s) | No | Replacement PDFs referenced by entries in `customDocumentData` | + +### Payload Schema + +| Field | Type | Required | Description | +| -------------------- | ------- | -------- | ------------------------------------------------------------------------ | +| `envelopeId` | string | Yes | ID of the template envelope | +| `externalId` | string | No | Your identifier for the created document envelope | +| `recipients` | array | No | Recipient details mapped to recipients in the template | +| `distributeDocument` | boolean | No | If `true`, create the document as pending and distribute it | +| `customDocumentData` | array | No | Maps uploaded replacement PDFs to template envelope items | +| `folderId` | string | No | Folder in which to create the document | +| `prefillFields` | array | No | Field values to prefill before distribution | +| `override` | object | No | Template values to override for the created document | +| `attachments` | array | No | Link attachments to add to the document | +| `formValues` | object | No | PDF form values to apply | + +Each recipient entry accepts the following fields: + +| Field | Type | Required | Description | +| -------------- | ------- | -------- | -------------------------------------------- | +| `id` | number | Yes | Recipient ID from the template envelope | +| `email` | string | Yes | Recipient email address | +| `name` | string | No | Recipient display name | +| `signingOrder` | number | No | Recipient position in sequential signing | + +Each `customDocumentData` entry maps an uploaded file to a template item: + +| Field | Type | Required | Description | +| ---------------- | ---------------- | -------- | --------------------------------------------------------------- | +| `identifier` | string \| number | Yes | Uploaded filename or zero-based file index | +| `envelopeItemId` | string | Yes | Template envelope item whose PDF the uploaded file replaces | + +### Code Examples + + + +```bash +curl -X POST "https://app.documenso.com/api/v2/envelope/use" \ + -H "Authorization: api_xxxxxxxxxxxxxxxx" \ + -F 'payload={ + "envelopeId": "envelope_template123", + "externalId": "contract-2025-001", + "recipients": [ + { + "id": 1, + "email": "john.doe@example.com", + "name": "John Doe" + } + ], + "prefillFields": [ + { + "id": 101, + "type": "text", + "value": "Senior Software Engineer" + } + ], + "distributeDocument": false + }' +``` + + +```typescript +const form = new FormData(); + +form.append( + 'payload', + JSON.stringify({ + envelopeId: 'envelope_template123', + externalId: 'contract-2025-001', + recipients: [ + { + id: 1, + email: 'john.doe@example.com', + name: 'John Doe', + }, + ], + prefillFields: [ + { + id: 101, + type: 'text', + value: 'Senior Software Engineer', + }, + ], + distributeDocument: false, + }), +); + +const response = await fetch('https://app.documenso.com/api/v2/envelope/use', { + method: 'POST', + headers: { + Authorization: 'api_xxxxxxxxxxxxxxxx', + }, + body: form, +}); + +const document = await response.json(); +console.log('Created document envelope:', document.id); +``` + + + +### Response + +```json +{ + "id": "envelope_document123", + "recipients": [ + { + "id": 1, + "name": "John Doe", + "email": "john.doe@example.com", + "token": "recipient_token", + "role": "SIGNER", + "signingOrder": 1, + "signingUrl": "https://app.documenso.com/sign/recipient_token" + } + ] +} +``` + +### Distribute the Created Envelope + +If you leave `distributeDocument` unset or set it to `false`, distribute the created document with +`POST /envelope/distribute`. Its response confirms delivery and includes each recipient's signing URL. + +```typescript +const distributionResponse = await fetch( + 'https://app.documenso.com/api/v2/envelope/distribute', + { + method: 'POST', + headers: { + Authorization: 'api_xxxxxxxxxxxxxxxx', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + envelopeId: document.id, + }), + }, +); + +const distribution = await distributionResponse.json(); +console.log('Signing URL:', distribution.recipients[0].signingUrl); +``` + +```json +{ + "success": true, + "id": "envelope_document123", + "recipients": [ + { + "id": 1, + "name": "John Doe", + "email": "john.doe@example.com", + "token": "recipient_token", + "role": "SIGNER", + "signingOrder": 1, + "signingUrl": "https://app.documenso.com/sign/recipient_token" + } + ] +} +``` + +--- + +## Deprecated Template Endpoint Reference + + + Every `/template/*` endpoint below is deprecated. Use the Envelope API for new integrations and + follow [Migrating to Envelopes](/docs/developers/api/migrate-to-envelopes) to replace existing calls. + The legacy reference remains here to support migrations. + + +## Legacy Template Object A template object contains the following properties: @@ -91,7 +278,7 @@ A template object contains the following properties: } ``` -## List Templates +## List Templates (Deprecated) Retrieve a paginated list of templates. @@ -139,8 +326,8 @@ const response = await fetch(`${BASE_URL}/template`, { }, }); -const { data, pagination } = await response.json(); -console.log(`Found ${pagination.totalItems} templates`); +const { data, count } = await response.json(); +console.log(`Found ${count} templates`); // Filter by type const privateResponse = await fetch( @@ -181,18 +368,16 @@ const privateTemplates = await privateResponse.json(); ] } ], - "pagination": { - "page": 1, - "perPage": 10, - "totalPages": 3, - "totalItems": 25 - } + "count": 25, + "currentPage": 1, + "perPage": 10, + "totalPages": 3 } ``` --- -## Get Template +## Get Template (Deprecated) Retrieve a single template by ID. @@ -238,9 +423,9 @@ Returns the full template object including recipients, fields, and metadata. --- -## Create Document from Template +## Create Document from Template (Deprecated) -Create a new document using a template. This is the primary way to use templates programmatically. +Create a new document using the deprecated template endpoint. This endpoint does not support [PDF placeholder parsing](/docs/users/documents/advanced/pdf-placeholders). Use `POST /envelope/create` for placeholder-based field positioning. @@ -415,32 +600,57 @@ const prefilledDocument = await prefillResponse.json(); ### Response -Returns the created document object with recipients and signing URLs. +The endpoint returns the full legacy document object. The selected fields below show both the numeric +legacy `id` and canonical `envelopeId`. Recipient entries do not include a `signingUrl`. ```json { - "id": "envelope_xyz789", - "type": "DOCUMENT", + "id": 789, + "envelopeId": "envelope_xyz789", "status": "PENDING", - "title": "Employment Contract", "source": "TEMPLATE", + "title": "Employment Contract", "externalId": "contract-2025-001", "recipients": [ { "id": 1, + "envelopeId": "envelope_xyz789", + "documentId": 789, + "templateId": null, "email": "john.doe@example.com", "name": "John Doe", "role": "SIGNER", "signingStatus": "NOT_SIGNED", - "signingUrl": "https://app.documenso.com/sign/abc123" + "signingOrder": 1 } ] } -```` +``` + +To send a document created with `distributeDocument: false` and receive signing links, call +`POST /envelope/distribute` with its `envelopeId`: + +```typescript +const document = await response.json(); + +const distributionResponse = await fetch(`${BASE_URL}/envelope/distribute`, { + method: 'POST', + headers: { + Authorization: API_TOKEN, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + envelopeId: document.envelopeId, + }), +}); + +const distribution = await distributionResponse.json(); +console.log('Signing URL:', distribution.recipients[0].signingUrl); +``` --- -## Override Template Settings +## Override Template Settings (Deprecated) When creating a document from a template, you can override various settings: @@ -488,7 +698,7 @@ const response = await fetch(`${BASE_URL}/template/use`, { --- -## Prefill Fields +## Prefill Fields (Deprecated) Prefill field values when creating a document from a template. This is useful for populating known data before sending. @@ -577,7 +787,7 @@ const response = await fetch(`${BASE_URL}/template/use`, { --- -## Update Template +## Update Template (Deprecated) Update a template's properties. @@ -643,7 +853,7 @@ const template = await response.json(); --- -## Duplicate Template +## Duplicate Template (Deprecated) Create a copy of an existing template. @@ -695,7 +905,7 @@ console.log('New template ID:', duplicatedTemplate.id); --- -## Delete Template +## Delete Template (Deprecated) Delete a template. @@ -754,7 +964,7 @@ const { success } = await response.json(); --- -## Direct Link Templates +## Direct Link Templates (Deprecated) 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. @@ -898,7 +1108,7 @@ const { success } = await response.json(); --- -## Custom Document Data +## Custom Document Data (Deprecated) 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. @@ -913,7 +1123,7 @@ See the [OpenAPI Reference](https://openapi.documenso.com) for the full request --- -## Template Types +## Template Types (Legacy) | Type | Description | | --------- | ------------------------------------------------------------------ | @@ -922,7 +1132,7 @@ See the [OpenAPI Reference](https://openapi.documenso.com) for the full request --- -## Complete Example: Contract Workflow +## Complete Legacy Example: Contract Workflow (Deprecated) This example demonstrates a complete workflow for using templates to send contracts. @@ -996,16 +1206,29 @@ async function sendEmploymentContract(employeeData: { subject: `Employment Contract for ${employeeData.name}`, message: `Hi ${employeeData.name},\n\nPlease review and sign your employment contract.`, }, - distributeDocument: true, + distributeDocument: false, externalId: `emp-contract-${Date.now()}`, }), }); const document = await documentResponse.json(); + // 5. Distribute the envelope and get recipient signing links + const distributionResponse = await fetch(`${BASE_URL}/envelope/distribute`, { + method: 'POST', + headers: { + Authorization: API_TOKEN, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + envelopeId: document.envelopeId, + }), + }); + const distribution = await distributionResponse.json(); + return { - documentId: document.id, - signingUrl: document.recipients[0].signingUrl, + envelopeId: document.envelopeId, + signingUrl: distribution.recipients[0].signingUrl, }; } @@ -1018,7 +1241,7 @@ const result = await sendEmploymentContract({ startDate: '2025-03-01', }); -console.log('Document created:', result.documentId); +console.log('Document created:', result.envelopeId); console.log('Signing URL:', result.signingUrl); ````