feat: docs v2 (#2460)

Co-authored-by: Catalin Pit <catalinpit@gmail.com>
This commit is contained in:
Lucas Smith
2026-02-27 22:05:27 +11:00
committed by GitHub
parent f8ac782f2e
commit b92c53dbb2
290 changed files with 32521 additions and 266 deletions
@@ -0,0 +1,37 @@
---
title: Developer Mode
description: Advanced development tools for debugging field coordinates and integrating with the Documenso API.
---
## Overview
Developer mode provides additional tools and features to help you integrate and debug Documenso.
## Field Coordinates
Field coordinates represent the position of a field in a document. They are returned in the `pageX`, `pageY`, `width` and `height` properties of the field.
To enable field coordinates, add the `devmode=true` query parameter to the editor URL.
```bash
# Legacy editor
https://app.documenso.com/t/<team-url>/documents/<envelope-id>/legacy_editor?devmode=true
```
![Field Coordinates Legacy Editor](/developer-mode/field-coordinates-legacy-editor.webp)
```bash
# New editor
https://app.documenso.com/t/<team-url>/documents/<envelope-id>/edit?step=addFields&devmode=true
```
![Field Coordinates New Editor](/developer-mode/field-coordinates-new-editor.webp)
---
## See Also
- [Fields API](/docs/developers/api/fields) - Create and position fields via API
- [Field Types](/docs/concepts/field-types) - Detailed field type reference
@@ -0,0 +1,815 @@
---
title: Documents API
description: Create, manage, and send documents for signing via the 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>
## Overview
[Documents](/docs/users/documents) (called "envelopes" in the API) are the core resource in Documenso. You can:
1. create documents with recipients and fields
2. send them for signing
3. track their status
4. retrieve the completed PDFs
Each document contains one or more PDF files, a list of recipients, and the fields they need to fill.
## Document Object
A document object contains the following properties:
| Property | Type | Description |
| --------------- | -------------- | -------------------------------------------------------------- |
| `id` | string | Unique identifier (e.g., `envelope_abc123`) |
| `type` | string | `DOCUMENT` or `TEMPLATE` |
| `status` | string | Current status: `DRAFT`, `PENDING`, `COMPLETED`, or `REJECTED` |
| `title` | string | Document title |
| `source` | string | How the document was created: `DOCUMENT`, `TEMPLATE`, `API` |
| `visibility` | string | Who can view: `EVERYONE`, `ADMIN`, `MANAGER_AND_ABOVE` |
| `externalId` | string \| null | Your custom identifier for the document |
| `createdAt` | string | ISO 8601 timestamp |
| `updatedAt` | string | ISO 8601 timestamp |
| `completedAt` | string \| null | Timestamp when all recipients completed signing |
| `deletedAt` | string \| null | Timestamp if soft-deleted |
| `recipients` | array | List of recipients and their signing status |
| `fields` | array | Signature and form fields on the document |
| `envelopeItems` | array | PDF files attached to the document |
| `documentMeta` | object | Email settings, redirect URL, signing options |
### Example Document Object
```json
{
"id": "envelope_abc123xyz",
"type": "DOCUMENT",
"status": "PENDING",
"source": "API",
"visibility": "EVERYONE",
"title": "Service Agreement",
"externalId": "contract-2025-001",
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:35:00.000Z",
"completedAt": null,
"deletedAt": null,
"recipients": [
{
"id": 1,
"email": "signer@example.com",
"name": "John Smith",
"role": "SIGNER",
"signingStatus": "NOT_SIGNED",
"signingOrder": 1
}
],
"fields": [
{
"id": "field_123",
"type": "SIGNATURE",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5,
"recipientId": 1
}
],
"envelopeItems": [
{
"id": "envelope_item_xyz",
"title": "contract.pdf",
"order": 1
}
],
"documentMeta": {
"subject": "Please sign this document",
"message": "Hi, please review and sign this agreement.",
"timezone": "America/New_York",
"redirectUrl": "https://example.com/thank-you"
}
}
```
## List Documents
Retrieve a paginated list of documents.
```
GET /envelope
```
### Query Parameters
| Parameter | Type | Description |
| ------------------ | ------- | ------------------------------------------------------------- |
| `page` | integer | Page number (default: 1) |
| `perPage` | integer | Results per page (default: 10, max: 100) |
| `type` | string | Filter by `DOCUMENT` or `TEMPLATE` |
| `status` | string | Filter by status: `DRAFT`, `PENDING`, `COMPLETED`, `REJECTED` |
| `source` | string | Filter by creation source |
| `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 documents
curl -X GET "https://app.documenso.com/api/v2/envelope" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
# Filter by status and paginate
curl -X GET "https://app.documenso.com/api/v2/envelope?status=PENDING&page=1&perPage=20" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
# List only documents (not templates)
curl -X GET "https://app.documenso.com/api/v2/envelope?type=DOCUMENT" \
-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 documents
const response = await fetch(`${BASE_URL}/envelope`, {
method: 'GET',
headers: {
Authorization: API_TOKEN,
},
});
const { data, pagination } = await response.json();
console.log(`Found ${pagination.totalItems} documents`);
// Filter by status
const pendingResponse = await fetch(
`${BASE_URL}/envelope?status=PENDING&page=1&perPage=20`,
{
method: 'GET',
headers: {
Authorization: API_TOKEN,
},
}
);
const pendingDocs = await pendingResponse.json();
````
</Tab>
</Tabs>
### Response
```json
{
"data": [
{
"id": "envelope_abc123",
"type": "DOCUMENT",
"status": "PENDING",
"title": "Service Agreement",
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:35:00.000Z",
"recipients": [
{
"id": 1,
"email": "signer@example.com",
"name": "John Smith",
"role": "SIGNER",
"signingStatus": "NOT_SIGNED"
}
]
}
],
"pagination": {
"page": 1,
"perPage": 10,
"totalPages": 5,
"totalItems": 42
}
}
```
---
## Get Document
Retrieve a single document by ID.
```
GET /envelope/{envelopeId}
```
### Path Parameters
| Parameter | Type | Description |
| ------------ | ------ | ----------------------------------------- |
| `envelopeId` | string | The document ID (e.g., `envelope_abc123`) |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X GET "https://app.documenso.com/api/v2/envelope/envelope_abc123" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
```
</Tab>
<Tab value="TypeScript">
```typescript
const envelopeId = 'envelope_abc123';
const response = await fetch(`https://app.documenso.com/api/v2/envelope/${envelopeId}`, {
method: 'GET',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
},
});
const document = await response.json();
console.log(document.title, document.status);
````
</Tab>
</Tabs>
### Response
Returns the full document object including recipients, fields, and envelope items.
```json
{
"id": "envelope_abc123",
"type": "DOCUMENT",
"status": "PENDING",
"title": "Service Agreement",
"recipients": [...],
"fields": [...],
"envelopeItems": [...],
"documentMeta": {...}
}
````
---
## Create Document
Create a new document with optional recipients and fields in a single request.
```
POST /envelope/create
Content-Type: multipart/form-data
```
### Request Body
The request uses `multipart/form-data` with two parts:
| Part | Type | Description |
| --------- | ------- | ---------------------- |
| `payload` | JSON | Document configuration |
| `files` | File(s) | One or more PDF files |
### Payload Schema
| Field | Type | Required | Description |
| ------------ | ------ | -------- | ------------------------------------------- |
| `type` | string | Yes | Must be `DOCUMENT` |
| `title` | string | Yes | Document title |
| `externalId` | string | No | Your custom identifier |
| `visibility` | string | No | `EVERYONE`, `ADMIN`, or `MANAGER_AND_ABOVE` |
| `folderId` | string | No | Folder ID to create the document in |
| `recipients` | array | No | Recipients with optional fields |
| `meta` | object | No | Email subject, message, redirect URL, etc. |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/create" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: multipart/form-data" \
-F 'payload={
"type": "DOCUMENT",
"title": "Service Agreement",
"externalId": "contract-2025-001",
"recipients": [
{
"email": "signer@example.com",
"name": "John Smith",
"role": "SIGNER",
"fields": [
{
"identifier": 0,
"type": "SIGNATURE",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5
},
{
"identifier": 0,
"type": "DATE",
"page": 1,
"positionX": 50,
"positionY": 80,
"width": 20,
"height": 3
}
]
}
],
"meta": {
"subject": "Please sign this agreement",
"message": "Hi John, please review and sign the attached agreement.",
"redirectUrl": "https://example.com/thank-you"
}
}' \
-F "files=@./contract.pdf;type=application/pdf"
```
</Tab>
<Tab value="TypeScript">
```typescript
import fs from 'fs';
import FormData from 'form-data';
const form = new FormData();
const payload = {
type: 'DOCUMENT',
title: 'Service Agreement',
externalId: 'contract-2025-001',
recipients: [
{
email: 'signer@example.com',
name: 'John Smith',
role: 'SIGNER',
fields: [
{
identifier: 0,
type: 'SIGNATURE',
page: 1,
positionX: 10,
positionY: 80,
width: 30,
height: 5,
},
{
identifier: 0,
type: 'DATE',
page: 1,
positionX: 50,
positionY: 80,
width: 20,
height: 3,
},
],
},
],
meta: {
subject: 'Please sign this agreement',
message: 'Hi John, please review and sign the attached agreement.',
redirectUrl: 'https://example.com/thank-you',
},
};
form.append('payload', JSON.stringify(payload));
form.append('files', fs.createReadStream('./contract.pdf'), {
contentType: 'application/pdf',
});
const response = await fetch('https://app.documenso.com/api/v2/envelope/create', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
},
body: form,
});
const { id } = await response.json();
console.log('Created document:', id);
````
</Tab>
</Tabs>
### Response
```json
{
"id": "envelope_abc123xyz"
}
````
### Field Positioning
Field positions use percentage values (0-100) relative to the PDF page:
| Parameter | Description |
| ------------ | ---------------------------------------------------------- |
| `positionX` | Horizontal position from left edge (0 = left, 100 = right) |
| `positionY` | Vertical position from top edge (0 = top, 100 = bottom) |
| `width` | Field width as percentage of page width |
| `height` | Field height as percentage of page height |
| `page` | Page number (1-indexed) |
| `identifier` | File index (0 for first file) or filename |
### Field Types
| Type | Description |
| ----------- | --------------------------- |
| `SIGNATURE` | Signature field |
| `INITIALS` | Initials field |
| `NAME` | Auto-filled recipient name |
| `EMAIL` | Auto-filled recipient email |
| `DATE` | Signing date |
| `TEXT` | Free text input |
| `NUMBER` | Numeric input |
| `CHECKBOX` | Checkbox selection |
| `RADIO` | Radio button group |
| `DROPDOWN` | Dropdown selection |
### Recipient Roles
| Role | Description |
| ---------- | ----------------------------------------- |
| `SIGNER` | Must sign the document |
| `APPROVER` | Must approve before signers can sign |
| `CC` | Receives a copy but doesn't sign |
| `VIEWER` | Can view the document but takes no action |
---
## Update Document
Update a document's properties. Only works on documents in `DRAFT` status.
```
POST /envelope/update
```
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | ------------------------------------ |
| `envelopeId` | string | Yes | Document ID |
| `data` | object | No | Document 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/envelope/update" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "envelope_abc123",
"data": {
"title": "Updated Service Agreement",
"externalId": "contract-2025-001-v2"
},
"meta": {
"subject": "Updated: Please sign this agreement",
"redirectUrl": "https://example.com/signed"
}
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/update', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'envelope_abc123',
data: {
title: 'Updated Service Agreement',
externalId: 'contract-2025-001-v2',
},
meta: {
subject: 'Updated: Please sign this agreement',
redirectUrl: 'https://example.com/signed',
},
}),
});
const document = await response.json();
```
</Tab>
</Tabs>
---
## Send Document
Send a document to recipients for signing. This changes the status from `DRAFT` to `PENDING`.
```
POST /envelope/distribute
````
### Request Body
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `envelopeId` | string | Yes | Document ID |
| `meta` | object | No | Override email settings for this send |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
# Basic send
curl -X POST "https://app.documenso.com/api/v2/envelope/distribute" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "envelope_abc123"
}'
# Send with custom email settings
curl -X POST "https://app.documenso.com/api/v2/envelope/distribute" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "envelope_abc123",
"meta": {
"subject": "Action Required: Sign Agreement",
"message": "Please sign this document by end of day.",
"timezone": "America/New_York"
}
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/distribute', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'envelope_abc123',
meta: {
subject: 'Action Required: Sign Agreement',
message: 'Please sign this document by end of day.',
},
}),
});
const { id, recipients } = await response.json();
// Recipients now include signing URLs
recipients.forEach((r) => {
console.log(`${r.email}: ${r.signingUrl}`);
});
````
</Tab>
</Tabs>
### Response
The response includes signing URLs for each recipient:
```json
{
"success": true,
"id": "envelope_abc123",
"recipients": [
{
"id": 1,
"name": "John Smith",
"email": "signer@example.com",
"token": "abc123xyz",
"role": "SIGNER",
"signingOrder": 1,
"signingUrl": "https://app.documenso.com/sign/abc123xyz"
}
]
}
````
<Callout type="info">
Use the `signingUrl` to redirect recipients directly to the signing page, or let them use the
email link.
</Callout>
---
## Delete Document
Delete a document. Completed documents cannot be deleted.
```
POST /envelope/delete
```
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | ----------- |
| `envelopeId` | string | Yes | Document ID |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "envelope_abc123"
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/delete', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'envelope_abc123',
}),
});
const { success } = await response.json();
````
</Tab>
</Tabs>
### Response
```json
{
"success": true
}
````
---
## Get Multiple Documents
Retrieve multiple documents by their IDs in a single request.
```
POST /envelope/get-many
```
### Request Body
| Field | Type | Required | Description |
| ------------- | ----- | -------- | --------------------- |
| `envelopeIds` | array | Yes | Array of document IDs |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/get-many" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeIds": ["envelope_abc123", "envelope_def456", "envelope_ghi789"]
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/get-many', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeIds: ['envelope_abc123', 'envelope_def456', 'envelope_ghi789'],
}),
});
const documents = await response.json();
````
</Tab>
</Tabs>
---
## Document Statuses
| Status | Description |
| --- | --- |
| `DRAFT` | Document is being prepared. Recipients have not been notified. |
| `PENDING` | Document has been sent. Waiting for recipients to sign. |
| `COMPLETED` | All recipients have signed. Document is sealed. |
| `REJECTED` | A recipient rejected the document. |
### Status Transitions
```mermaid
flowchart LR
DRAFT --> PENDING --> COMPLETED
PENDING --> REJECTED
```
- **DRAFT to PENDING**: Call the distribute endpoint
- **PENDING to COMPLETED**: All recipients complete their signing
- **PENDING to REJECTED**: A recipient rejects the document
<Callout type="warn">
You cannot modify recipients or fields after a document moves to `PENDING` status.
</Callout>
---
## Filtering and Pagination
### Pagination Parameters
| Parameter | Type | Default | Description |
| --------- | ------- | ------- | --------------------------- |
| `page` | integer | 1 | Page number |
| `perPage` | integer | 10 | Results per page (max: 100) |
### Filter Parameters
| Parameter | Values | Description |
| ---------- | ------------------------------------------- | ------------------------- |
| `type` | `DOCUMENT`, `TEMPLATE` | Filter by envelope type |
| `status` | `DRAFT`, `PENDING`, `COMPLETED`, `REJECTED` | Filter by status |
| `source` | `DOCUMENT`, `TEMPLATE`, `API` | Filter by creation source |
| `folderId` | string | Filter by folder |
### Sorting
| Parameter | Values | Description |
| ------------------ | ------------- | -------------------------------- |
| `orderByColumn` | `createdAt` | Field to sort by |
| `orderByDirection` | `asc`, `desc` | Sort direction (default: `desc`) |
### Example: Fetch All Pending Documents
```typescript
async function getAllPendingDocuments() {
const documents = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`https://app.documenso.com/api/v2/envelope?status=PENDING&page=${page}&perPage=100`,
{
headers: { Authorization: 'api_xxxxxxxxxxxxxxxx' },
},
);
const { data, pagination } = await response.json();
documents.push(...data);
hasMore = page < pagination.totalPages;
page++;
}
return documents;
}
```
---
## See Also
- [Recipients API](/docs/developers/api/recipients) - Add and manage document recipients
- [Fields API](/docs/developers/api/fields) - Add signature and form fields
- [Templates API](/docs/developers/api/templates) - Create reusable document templates
- [Webhooks](/docs/developers/webhooks) - Get notified when documents are signed
@@ -0,0 +1,738 @@
---
title: Fields API
description: Add signature and form fields to documents 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>
## Field Object
| Property | Type | Description |
| ---------------- | -------------- | -------------------------------------------- |
| `id` | number | Unique field identifier |
| `secondaryId` | string | Secondary identifier for audit logs |
| `type` | string | Field type (see [Field Types](#field-types)) |
| `recipientId` | number | ID of the recipient assigned to this field |
| `envelopeId` | number | ID of the parent envelope |
| `envelopeItemId` | string | ID of the PDF item the field is placed on |
| `page` | number | Page number (1-indexed) |
| `positionX` | number | X coordinate as percentage (0-100) |
| `positionY` | number | Y coordinate as percentage (0-100) |
| `width` | number | Width as percentage of page (0-100) |
| `height` | number | Height as percentage of page (0-100) |
| `customText` | string | Value entered by the recipient |
| `inserted` | boolean | Whether the field has been completed |
| `fieldMeta` | object \| null | Type-specific configuration options |
### Example Field Object
```json
{
"id": 456,
"secondaryId": "field_abc123",
"type": "SIGNATURE",
"recipientId": 123,
"envelopeId": 789,
"envelopeItemId": "envelope_item_xyz",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5,
"customText": "",
"inserted": false,
"fieldMeta": {
"type": "signature",
"required": true
}
}
```
---
## Field Types
| Type | Description | Auto-filled |
| ---------------- | ----------------------------------------- | ----------- |
| `SIGNATURE` | Drawn, typed, or uploaded signature | No |
| `FREE_SIGNATURE` | Unrestricted signature without validation | No |
| `INITIALS` | Recipient's initials | No |
| `NAME` | Recipient's full name | Yes |
| `EMAIL` | Recipient's email address | Yes |
| `DATE` | Date the field was completed | Yes |
| `TEXT` | Free-form text input | No |
| `NUMBER` | Numeric input with optional validation | No |
| `RADIO` | Single selection from options | No |
| `CHECKBOX` | Multiple selections from options | No |
| `DROPDOWN` | Single selection from a dropdown menu | No |
---
## Get Field
Retrieve a single field by ID.
```
GET /envelope/field/{fieldId}
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ------------ |
| `fieldId` | number | The field ID |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X GET "https://app.documenso.com/api/v2/envelope/field/456" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/field/456',
{
method: 'GET',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
},
}
);
const field = await response.json();
console.log(field.type, field.page);
```
</Tab>
</Tabs>
### Response
Returns the field object.
---
## Create Fields
Add one or more fields to a document.
```
POST /envelope/field/create-many
````
### Request Body
| Field | Type | Required | Description |
| ----------- | ------ | -------- | ------------------------------- |
| `documentId`| number | Yes | The document ID |
| `fields` | array | Yes | Array of field configurations |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/field/create-many" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"documentId": 123,
"fields": [
{
"type": "SIGNATURE",
"recipientId": 456,
"pageNumber": 1,
"pageX": 10,
"pageY": 80,
"width": 30,
"height": 5
},
{
"type": "DATE",
"recipientId": 456,
"pageNumber": 1,
"pageX": 50,
"pageY": 80,
"width": 20,
"height": 3
},
{
"type": "TEXT",
"recipientId": 456,
"pageNumber": 1,
"pageX": 10,
"pageY": 70,
"width": 40,
"height": 4,
"fieldMeta": {
"type": "text",
"label": "Job Title",
"placeholder": "Enter your job title",
"required": true
}
}
]
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/field/create-many',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
documentId: 123,
fields: [
{
type: 'SIGNATURE',
recipientId: 456,
pageNumber: 1,
pageX: 10,
pageY: 80,
width: 30,
height: 5,
},
{
type: 'DATE',
recipientId: 456,
pageNumber: 1,
pageX: 50,
pageY: 80,
width: 20,
height: 3,
},
{
type: 'TEXT',
recipientId: 456,
pageNumber: 1,
pageX: 10,
pageY: 70,
width: 40,
height: 4,
fieldMeta: {
type: 'text',
label: 'Job Title',
placeholder: 'Enter your job title',
required: true,
},
},
],
}),
}
);
const { fields } = await response.json();
console.log(`Created ${fields.length} fields`);
````
</Tab>
</Tabs>
### Response
```json
{
"fields": [
{
"id": 101,
"type": "SIGNATURE",
"recipientId": 456,
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5
},
{
"id": 102,
"type": "DATE",
"recipientId": 456,
"page": 1,
"positionX": 50,
"positionY": 80,
"width": 20,
"height": 3
},
{
"id": 103,
"type": "TEXT",
"recipientId": 456,
"page": 1,
"positionX": 10,
"positionY": 70,
"width": 40,
"height": 4
}
]
}
````
---
## Update Fields
Update one or more fields in a single request.
```
POST /envelope/field/update-many
```
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | ----------------------------- |
| `documentId` | number | Yes | The document ID |
| `fields` | array | Yes | Array of field update objects |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/field/update-many" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"documentId": 123,
"fields": [
{
"id": 101,
"type": "SIGNATURE",
"pageY": 85
},
{
"id": 102,
"type": "DATE",
"pageY": 85
}
]
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/field/update-many',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
documentId: 123,
fields: [
{ id: 101, type: 'SIGNATURE', pageY: 85 },
{ id: 102, type: 'DATE', pageY: 85 },
],
}),
}
);
const { fields } = await response.json();
````
</Tab>
</Tabs>
### Response
```json
{
"fields": [
{ "id": 101, "type": "SIGNATURE", "positionY": 85 },
{ "id": 102, "type": "DATE", "positionY": 85 }
]
}
````
---
## Delete Field
Remove a field from a document.
```
POST /envelope/field/delete
```
### Request Body
| Field | Type | Required | Description |
| --------- | ------ | -------- | ------------ |
| `fieldId` | number | Yes | The field ID |
### Code Examples
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/field/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"fieldId": 456
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/field/delete',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
fieldId: 456,
}),
}
);
const { success } = await response.json();
````
</Tab>
</Tabs>
### Response
```json
{
"success": true
}
````
---
## Field Positioning
Fields use percentage-based coordinates relative to the PDF page dimensions.
| Property | Range | Description |
| ----------- | ----- | -------------------------------------------------- |
| `positionX` | 0-100 | Horizontal position from left edge (0 = left edge) |
| `positionY` | 0-100 | Vertical position from top edge (0 = top edge) |
| `width` | 0-100 | Field width as percentage of page width |
| `height` | 0-100 | Field height as percentage of page height |
| `page` | 1+ | Page number (1-indexed) |
### Coordinate System
```
(0,0) ─────────────────────────── (100,0)
│ │
│ ┌─────────┐ │
│ │ Field │ (pageX: 10, │
│ │ │ pageY: 20, │
│ └─────────┘ width: 30, │
│ height: 5) │
│ │
(0,100) ─────────────────────────(100,100)
```
### Example: Position a Signature at Bottom Right
```typescript
const field = {
type: 'SIGNATURE',
recipientId: 123,
pageNumber: 1,
pageX: 60, // 60% from left
pageY: 85, // 85% from top (near bottom)
width: 30, // 30% of page width
height: 8, // 8% of page height
};
```
---
## Placeholder-Based Field Positioning
Instead of specifying exact coordinates, you can position fields using placeholder text embedded in your PDF. Include placeholder markers such as `{{signature, r1}}` in your document, and Documenso will create fields at those locations when the document is uploaded.
This approach is useful when generating PDFs programmatically or using templates with consistent layouts.
See the [PDF Placeholders](/docs/users/documents/advanced/pdf-placeholders) guide for the full placeholder format reference, including supported field types, recipient identifiers, and field options.
---
## Field Meta Options
Each field type supports specific configuration through `fieldMeta`.
### Common Options
All field types support these base options:
| Option | Type | Description |
| ------------- | ------- | --------------------------------------- |
| `label` | string | Display text shown near the field |
| `placeholder` | string | Hint text when field is empty |
| `required` | boolean | Whether field must be completed |
| `readOnly` | boolean | Lock field with a pre-filled value |
| `fontSize` | number | Text size in pixels (8-96, default: 12) |
### Signature Field
```json
{
"type": "SIGNATURE",
"fieldMeta": {
"type": "signature",
"required": true
}
}
```
### Text Field
```json
{
"type": "TEXT",
"fieldMeta": {
"type": "text",
"label": "Company Name",
"placeholder": "Enter company name",
"text": "Default value",
"characterLimit": 100,
"textAlign": "left",
"required": true
}
}
```
| Option | Type | Description |
| ---------------- | ------ | ---------------------------------- |
| `text` | string | Default value |
| `characterLimit` | number | Maximum characters allowed |
| `textAlign` | string | `left`, `center`, or `right` |
| `lineHeight` | number | Spacing between lines (1-10) |
| `letterSpacing` | number | Spacing between characters (0-100) |
### Number Field
```json
{
"type": "NUMBER",
"fieldMeta": {
"type": "number",
"label": "Quantity",
"minValue": 1,
"maxValue": 100,
"value": "10",
"required": true
}
}
```
| Option | Type | Description |
| -------------- | ------ | --------------------- |
| `value` | string | Default value |
| `minValue` | number | Minimum allowed value |
| `maxValue` | number | Maximum allowed value |
| `numberFormat` | string | Display format |
### Date Field
```json
{
"type": "DATE",
"fieldMeta": {
"type": "date",
"textAlign": "left",
"required": true
}
}
```
### Checkbox Field
```json
{
"type": "CHECKBOX",
"fieldMeta": {
"type": "checkbox",
"label": "Agreements",
"values": [
{ "id": 1, "value": "Terms of Service", "checked": false },
{ "id": 2, "value": "Privacy Policy", "checked": false }
],
"validationRule": "min",
"validationLength": 1,
"direction": "vertical",
"required": true
}
}
```
| Option | Type | Description |
| ------------------ | ------ | --------------------------------- |
| `values` | array | List of checkbox options |
| `validationRule` | string | Validation type for selections |
| `validationLength` | number | Number for validation rule |
| `direction` | string | `vertical` or `horizontal` layout |
### Radio Field
```json
{
"type": "RADIO",
"fieldMeta": {
"type": "radio",
"label": "Payment Method",
"values": [
{ "id": 1, "value": "Credit Card", "checked": false },
{ "id": 2, "value": "Bank Transfer", "checked": true },
{ "id": 3, "value": "Check", "checked": false }
],
"direction": "vertical",
"required": true
}
}
```
### Dropdown Field
```json
{
"type": "DROPDOWN",
"fieldMeta": {
"type": "dropdown",
"label": "Country",
"values": [{ "value": "United States" }, { "value": "Canada" }, { "value": "United Kingdom" }],
"defaultValue": "United States",
"required": true
}
}
```
| Option | Type | Description |
| -------------- | ------ | ------------------------ |
| `values` | array | List of dropdown options |
| `defaultValue` | string | Pre-selected option |
---
## Complete Example
Create a document with a signature block containing multiple field types:
```typescript
async function addSignatureBlock(documentId: number, recipientId: number) {
const fields = [
// Signature
{
type: 'SIGNATURE',
recipientId,
pageNumber: 1,
pageX: 10,
pageY: 80,
width: 30,
height: 8,
fieldMeta: {
type: 'signature',
required: true,
},
},
// Printed name
{
type: 'NAME',
recipientId,
pageNumber: 1,
pageX: 10,
pageY: 90,
width: 30,
height: 4,
fieldMeta: {
type: 'name',
label: 'Printed Name',
},
},
// Date
{
type: 'DATE',
recipientId,
pageNumber: 1,
pageX: 50,
pageY: 80,
width: 20,
height: 4,
fieldMeta: {
type: 'date',
label: 'Date',
},
},
// Job title
{
type: 'TEXT',
recipientId,
pageNumber: 1,
pageX: 50,
pageY: 90,
width: 30,
height: 4,
fieldMeta: {
type: 'text',
label: 'Title',
placeholder: 'Enter your job title',
},
},
];
const response = await fetch('https://app.documenso.com/api/v2/envelope/field/create-many', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({ documentId, fields }),
});
return response.json();
}
```
---
## Error Responses
| Status | Description |
| ------ | ---------------------------------------------------- |
| `400` | Invalid field configuration or document already sent |
| `401` | Invalid or missing API key |
| `404` | Document, recipient, or field not found |
| `500` | Server error |
<Callout type="warn">
Fields cannot be modified after a document is sent for signing. Make all field changes while the
document is in `DRAFT` status.
</Callout>
---
## See Also
- [Documents API](/docs/developers/api/documents) - Create and manage documents
- [Recipients API](/docs/developers/api/recipients) - Add signers to documents
- [Field Types](/docs/concepts/field-types) - Detailed field type reference
@@ -0,0 +1,72 @@
---
title: API Reference
description: Complete reference for the Documenso REST API.
---
import { Callout } from 'fumadocs-ui/components/callout';
<Callout type="warn">
The guides below cover common API patterns but may not reflect the latest endpoints or parameters.
For an always up-to-date reference, see the [OpenAPI Reference](https://openapi.documenso.com).
</Callout>
## Base URL
```
https://app.documenso.com/api/v2
```
For self-hosted instances, replace with your instance URL.
---
## Authentication
All requests require an API key in the `Authorization` header:
```
Authorization: api_xxxxxxxxxxxxxxxx
```
<Callout type="info">
See [Authentication](/docs/developers/getting-started/authentication) for details.
</Callout>
---
## Endpoints
<Cards>
<Card
title="Documents"
description="Create, retrieve, update, and delete documents."
href="/docs/developers/api/documents"
/>
<Card
title="Recipients"
description="Manage document recipients and signers."
href="/docs/developers/api/recipients"
/>
<Card
title="Fields"
description="Add and configure signature fields."
href="/docs/developers/api/fields"
/>
<Card
title="Templates"
description="Work with document templates."
href="/docs/developers/api/templates"
/>
<Card
title="Teams"
description="Manage teams and team members."
href="/docs/developers/api/teams"
/>
</Cards>
---
## See Also
- [First API Call](/docs/developers/getting-started/first-api-call) - Quick start example
- [Webhooks](/docs/developers/webhooks) - Get notified about document events
@@ -0,0 +1,13 @@
{
"title": "API Reference",
"pages": [
"documents",
"recipients",
"fields",
"templates",
"teams",
"rate-limits",
"versioning",
"developer-mode"
]
}
@@ -0,0 +1,67 @@
---
title: Rate Limits
description: Learn about the rate limits for the Documenso Public API.
---
import { Callout } from 'fumadocs-ui/components/callout';
## Overview
Documenso enforces rate limits on all API endpoints to ensure service stability.
## HTTP Rate Limits
**Limit:** 100 requests per minute per IP address
**Response:** 429 Too Many Requests
### Rate Limit Response
```json
{
"error": "Too many requests, please try again later."
}
```
<Callout type="warn">
No rate limit headers are currently provided. When you receive a 429 response, wait at least 60
seconds before retrying.
</Callout>
## Resource Limits
Beyond HTTP rate limits, your account has usage limits based on your subscription plan.
### Plan Limits
| Resource | Free | Paid | Self-hosted | Enterprise |
| ---------------- | ---- | --------- | ----------- | ---------- |
| Documents/month | 5 | Unlimited | Unlimited | Unlimited |
| Total Recipients | 10 | Unlimited | Unlimited | Unlimited |
| Direct Templates | 3 | Unlimited | Unlimited | Unlimited |
### Error Response
When you exceed a resource limit:
```json
{
"error": "You have reached your document limit for this month. Please upgrade your plan.",
"code": "LIMIT_EXCEEDED",
"statusCode": 400
}
```
## Error Codes
| Code | Status | Description |
| ------------------- | ------ | ----------------------------- |
| `TOO_MANY_REQUESTS` | 429 | HTTP rate limit exceeded |
| `LIMIT_EXCEEDED` | 400 | Resource usage limit exceeded |
---
## See Also
- [Authentication](/docs/developers/getting-started/authentication) - API authentication guide
- [API Versioning](/docs/developers/api/versioning) - API version management
- [First API Call](/docs/developers/getting-started/first-api-call) - Getting started with the API
@@ -0,0 +1,504 @@
---
title: Recipients API
description: Add and manage envelope recipients 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>
## Recipient Object
```json
{
"id": 123,
"envelopeId": "clu1abc2def3ghi4jkl",
"email": "signer@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingOrder": 1,
"token": "abc123...",
"signedAt": "2024-01-15T10:30:00Z",
"readStatus": "OPENED",
"signingStatus": "SIGNED",
"sendStatus": "SENT"
}
```
| Field | Type | Description |
| --------------- | -------------- | ------------------------------------- |
| `id` | number | Unique recipient identifier |
| `envelopeId` | string | ID of the associated envelope |
| `email` | string | Recipient's email address |
| `name` | string | Recipient's display name |
| `role` | string | Recipient role (see below) |
| `signingOrder` | number \| null | Order in sequential signing |
| `token` | string | Unique token for signing URL |
| `signedAt` | string \| null | ISO timestamp when signed |
| `readStatus` | string | `NOT_OPENED` or `OPENED` |
| `signingStatus` | string | `NOT_SIGNED`, `SIGNED`, or `REJECTED` |
| `sendStatus` | string | `NOT_SENT` or `SENT` |
---
## Recipient Roles
| Role | Description |
| ----------- | -------------------------------------------------------------- |
| `SIGNER` | Must sign the document. Required fields must be completed. |
| `APPROVER` | Must approve the document before signers can proceed. |
| `VIEWER` | Can view the document but takes no action. |
| `CC` | Receives a copy of the completed document. No action required. |
| `ASSISTANT` | Can fill in fields on behalf of another recipient. |
---
## Get Recipient
Retrieve a single recipient by ID.
```
GET /api/v2/envelope/recipient/{recipientId}
```
### Example
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl "https://app.documenso.com/api/v2/envelope/recipient/789" \
-H "Authorization: api_xxxxxxxxxxxxxxxx"
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/recipient/789',
{
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
},
},
);
const recipient = await response.json();
```
</Tab>
</Tabs>
### Response
Returns the full recipient object including fields.
---
## Create Recipients
Add one or more recipients to an envelope.
```
POST /api/v2/envelope/recipient/create-many
````
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | --------------------------------------- |
| `envelopeId` | string | Yes | ID of the envelope to add recipients to |
| `data` | array | Yes | Array of recipient objects |
Each item in the `data` array:
| Field | Type | Required | Description |
| -------------- | -------- | -------- | ------------------------------------------ |
| `email` | string | Yes | Recipient's email address |
| `name` | string | Yes | Recipient's display name (max 255 chars) |
| `role` | string | Yes | Recipient role (see Recipient Roles above) |
| `signingOrder` | number | No | Position in sequential signing |
| `accessAuth` | string[] | No | Access authentication types |
| `actionAuth` | string[] | No | Action authentication types |
### Example
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/recipient/create-many" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "clu1abc2def3ghi4jkl",
"data": [
{
"email": "signer@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingOrder": 1
},
{
"email": "approver@example.com",
"name": "Jane Smith",
"role": "APPROVER",
"signingOrder": 0
}
]
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/recipient/create-many',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'clu1abc2def3ghi4jkl',
data: [
{
email: 'signer@example.com',
name: 'John Doe',
role: 'SIGNER',
signingOrder: 1,
},
{
email: 'approver@example.com',
name: 'Jane Smith',
role: 'APPROVER',
signingOrder: 0,
},
],
}),
},
);
const { data: recipients } = await response.json();
````
</Tab>
</Tabs>
### Response
```json
{
"data": [
{
"id": 789,
"envelopeId": "clu1abc2def3ghi4jkl",
"email": "signer@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingOrder": 1,
"token": "abc123def456",
"signedAt": null,
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "NOT_SENT"
},
{
"id": 790,
"envelopeId": "clu1abc2def3ghi4jkl",
"email": "approver@example.com",
"name": "Jane Smith",
"role": "APPROVER",
"signingOrder": 0,
"token": "def456ghi789",
"signedAt": null,
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "NOT_SENT"
}
]
}
````
---
## Update Recipients
Update one or more recipients on an envelope. Only available for envelopes that are not yet completed.
```
POST /api/v2/envelope/recipient/update-many
```
### Request Body
| Field | Type | Required | Description |
| ------------ | ------ | -------- | -------------------------------------------- |
| `envelopeId` | string | Yes | ID of the envelope containing the recipients |
| `data` | array | Yes | Array of recipient update objects |
Each item in the `data` array:
| Field | Type | Required | Description |
| -------------- | -------- | -------- | ---------------------------------- |
| `id` | number | Yes | ID of the recipient to update |
| `email` | string | No | New email address |
| `name` | string | No | New display name (max 255 chars) |
| `role` | string | No | New recipient role |
| `signingOrder` | number | No | New position in sequential signing |
| `accessAuth` | string[] | No | Access authentication types |
| `actionAuth` | string[] | No | Action authentication types |
### Example
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/recipient/update-many" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"envelopeId": "clu1abc2def3ghi4jkl",
"data": [
{
"id": 789,
"name": "Jane Doe",
"signingOrder": 2
}
]
}'
```
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/recipient/update-many',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'clu1abc2def3ghi4jkl',
data: [
{
id: 789,
name: 'Jane Doe',
signingOrder: 2,
},
],
}),
},
);
const { data: updatedRecipients } = await response.json();
```
</Tab>
</Tabs>
### Response
Returns the updated recipient objects in a `data` array.
---
## Delete Recipient
Remove a recipient from an envelope. Only available for envelopes that are not yet completed.
```
POST /api/v2/envelope/recipient/delete
````
### Request Body
| Field | Type | Required | Description |
| ------------- | ------ | -------- | ------------------------------- |
| `recipientId` | number | Yes | ID of the recipient to remove |
### Example
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/envelope/recipient/delete" \
-H "Authorization: api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"recipientId": 789
}'
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch(
'https://app.documenso.com/api/v2/envelope/recipient/delete',
{
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
recipientId: 789,
}),
},
);
const result = await response.json();
// { "success": true }
````
</Tab>
</Tabs>
### Response
```json
{
"success": true
}
````
---
## Signing Order
When an envelope uses sequential signing, recipients sign in a specific order defined by `signingOrder`.
### Setting Signing Order
When creating recipients, assign `signingOrder` values to control the sequence:
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/recipient/create-many', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'clu1abc2def3ghi4jkl',
data: [
{
email: 'approver@example.com',
name: 'Approver',
role: 'APPROVER',
signingOrder: 0, // Approvers typically go first
},
{
email: 'first@example.com',
name: 'First Signer',
role: 'SIGNER',
signingOrder: 1,
},
{
email: 'second@example.com',
name: 'Second Signer',
role: 'SIGNER',
signingOrder: 2,
},
],
}),
});
```
<Callout type="info">
To enable sequential signing, set `signingOrder` to `SEQUENTIAL` in the envelope metadata when
creating or updating the envelope. See the [Documents API](/docs/developers/api/documents) for
details.
</Callout>
### Signing Order Behavior
- Recipients with lower `signingOrder` values sign first
- Recipients with the same `signingOrder` can sign simultaneously
- `CC` recipients receive the document after all signing is complete
- `APPROVER` recipients must approve before signers with higher order values
---
## Authentication Options
For enhanced security, you can require additional authentication when recipients access or sign a document.
### Access Authentication
Controls who can view the document:
| Type | Description |
| ----------------- | ------------------------------ |
| `ACCOUNT` | Recipient must be logged in |
| `TWO_FACTOR_AUTH` | Recipient must verify with 2FA |
### Action Authentication
Controls who can sign the document:
| Type | Description |
| ----------------- | ---------------------------------------- |
| `ACCOUNT` | Recipient must be logged in |
| `PASSKEY` | Require passkey authentication |
| `TWO_FACTOR_AUTH` | Require 2FA code |
| `PASSWORD` | Require password verification |
| `EXPLICIT_NONE` | Explicitly disable action authentication |
### Example
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope/recipient/create-many', {
method: 'POST',
headers: {
Authorization: 'api_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
envelopeId: 'clu1abc2def3ghi4jkl',
data: [
{
email: 'signer@example.com',
name: 'John Doe',
role: 'SIGNER',
accessAuth: ['ACCOUNT'],
actionAuth: ['PASSKEY', 'TWO_FACTOR_AUTH'],
},
],
}),
});
```
---
## Error Responses
| Status | Description |
| ------ | ------------------------------------------------ |
| `400` | Invalid request body or recipient already exists |
| `400` | Envelope is already completed |
| `401` | Invalid or missing API key |
| `404` | Envelope or recipient not found |
| `500` | Server error |
### Example Error Response
```json
{
"message": "Recipient already exists"
}
```
---
## See Also
- [Documents API](/docs/developers/api/documents) - Create and manage envelopes
- [Fields API](/docs/developers/api/fields) - Add signature fields for recipients
@@ -0,0 +1,373 @@
---
title: Teams API
description: Manage team resources, documents, and templates with team-scoped API tokens.
---
import { Callout } from 'fumadocs-ui/components/callout';
import { Step, Steps } from 'fumadocs-ui/components/steps';
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>
## Team Object
A team object contains the following properties:
| 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"
}
```
## Team-Scoped API Tokens
API tokens in Documenso are always scoped to a specific team. When you create an API token, it is associated with the team you're currently working in.
### How Team Scoping Works
- Each API token belongs to exactly one team
- All API operations using that token automatically access that team's resources
- Documents, templates, and other resources created via the API belong to the token's team
- You cannot access resources from other teams with a single token
### Creating Team-Scoped Tokens
{/* prettier-ignore */}
<Steps>
<Step>
Navigate to your team's settings
</Step>
<Step>
Go to **API Tokens**
</Step>
<Step>
Click **Create Token**
</Step>
<Step>
The token will be scoped to the current team
</Step>
</Steps>
<Callout type="info">
To work with multiple teams via API, create separate tokens for each team.
</Callout>
### Token Permissions
Your API token inherits permissions based on your role in the team:
| Role | Permissions |
| --------- | ------------------------------------------------ |
| `ADMIN` | Full access to all team resources and settings |
| `MANAGER` | Create, edit, and delete documents and templates |
| `MEMBER` | Create and manage own documents |
## Working with Team Documents
When you use a team-scoped API token, all document operations are automatically scoped to that team.
### Create a Team Document
Documents created with a team token belong to that team:
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
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": "DOCUMENT",
"title": "Team Contract",
"recipients": [
{
"email": "signer@example.com",
"name": "John Smith",
"role": "SIGNER"
}
]
}' \
-F "files=@./contract.pdf;type=application/pdf"
```
</Tab>
<Tab value="TypeScript">
```typescript
const TEAM_API_TOKEN = process.env.DOCUMENSO_TEAM_API_TOKEN;
const form = new FormData();
const payload = {
type: 'DOCUMENT',
title: 'Team Contract',
recipients: [
{
email: 'signer@example.com',
name: 'John Smith',
role: 'SIGNER',
},
],
};
form.append('payload', JSON.stringify(payload));
form.append('files', fs.createReadStream('./contract.pdf'), {
contentType: 'application/pdf',
});
const response = await fetch('https://app.documenso.com/api/v2/envelope/create', {
method: 'POST',
headers: {
Authorization: TEAM_API_TOKEN,
},
body: form,
});
const { id } = await response.json();
console.log('Created team document:', id);
````
</Tab>
</Tabs>
### List Team Documents
Retrieve all documents belonging to the team:
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
# List all team documents
curl -X GET "https://app.documenso.com/api/v2/envelope" \
-H "Authorization: api_team_xxxxxxxxxxxxxxxx"
# Filter by status
curl -X GET "https://app.documenso.com/api/v2/envelope?status=PENDING" \
-H "Authorization: api_team_xxxxxxxxxxxxxxxx"
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/envelope', {
method: 'GET',
headers: {
Authorization: TEAM_API_TOKEN,
},
});
const { data, pagination } = await response.json();
console.log(`Found ${pagination.totalItems} team documents`);
````
</Tab>
</Tabs>
## Working with Team Templates
Templates created with a team token are shared across the team.
### Create a Team Template
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X POST "https://app.documenso.com/api/v2/template/create" \
-H "Authorization: api_team_xxxxxxxxxxxxxxxx" \
-H "Content-Type: multipart/form-data" \
-F 'payload={
"title": "NDA Template",
"recipients": [
{
"email": "placeholder@example.com",
"name": "Signer",
"role": "SIGNER",
"fields": [
{
"identifier": 0,
"type": "SIGNATURE",
"page": 1,
"positionX": 10,
"positionY": 80,
"width": 30,
"height": 5
}
]
}
]
}' \
-F "files=@./nda-template.pdf;type=application/pdf"
````
</Tab>
<Tab value="TypeScript">
```typescript
const form = new FormData();
const payload = {
title: 'NDA Template',
recipients: [
{
email: 'placeholder@example.com',
name: 'Signer',
role: 'SIGNER',
fields: [
{
identifier: 0,
type: 'SIGNATURE',
page: 1,
positionX: 10,
positionY: 80,
width: 30,
height: 5,
},
],
},
],
};
form.append('payload', JSON.stringify(payload));
form.append('files', fs.createReadStream('./nda-template.pdf'), {
contentType: 'application/pdf',
});
const response = await fetch('https://app.documenso.com/api/v2/template/create', {
method: 'POST',
headers: {
Authorization: TEAM_API_TOKEN,
},
body: form,
});
const template = await response.json();
console.log('Created team template:', template.id);
````
</Tab>
</Tabs>
### List Team Templates
<Tabs items={['curl', 'TypeScript']}>
<Tab value="curl">
```bash
curl -X GET "https://app.documenso.com/api/v2/template" \
-H "Authorization: api_team_xxxxxxxxxxxxxxxx"
````
</Tab>
<Tab value="TypeScript">
```typescript
const response = await fetch('https://app.documenso.com/api/v2/template', {
method: 'GET',
headers: {
Authorization: TEAM_API_TOKEN,
},
});
const { data } = await response.json();
console.log('Team templates:', data);
````
</Tab>
</Tabs>
## Team Member Roles
| Role | Description |
| --------- | ------------------------------------------------------------------- |
| `ADMIN` | Full control over team settings, members, and all resources |
| `MANAGER` | Can manage documents, templates, and view team resources |
| `MEMBER` | Can create and manage their own documents within the team |
### Document Visibility
Team documents have visibility settings that control who can access them:
| Visibility | Description |
| ------------------ | ------------------------------------------------ |
| `EVERYONE` | All team members can view the document |
| `MANAGER_AND_ABOVE`| Only managers and admins can view |
| `ADMIN` | Only admins can view |
Set visibility when creating a document:
```typescript
const payload = {
type: 'DOCUMENT',
title: 'Confidential Agreement',
visibility: 'ADMIN', // Only team admins can view
recipients: [...],
};
````
## Multi-Team Workflow
To work with multiple teams, create and manage separate API tokens for each team.
### Example: Sync Documents Across Teams
```typescript
// Tokens for different teams
const SALES_TEAM_TOKEN = process.env.SALES_TEAM_API_TOKEN;
const LEGAL_TEAM_TOKEN = process.env.LEGAL_TEAM_API_TOKEN;
// Get pending documents from sales team
const salesResponse = await fetch('https://app.documenso.com/api/v2/envelope?status=PENDING', {
headers: { Authorization: SALES_TEAM_TOKEN },
});
const salesDocs = await salesResponse.json();
// Get completed documents from legal team
const legalResponse = await fetch('https://app.documenso.com/api/v2/envelope?status=COMPLETED', {
headers: { Authorization: LEGAL_TEAM_TOKEN },
});
const legalDocs = await legalResponse.json();
console.log(`Sales team: ${salesDocs.pagination.totalItems} pending`);
console.log(`Legal team: ${legalDocs.pagination.totalItems} completed`);
```
## Error Responses
| Status | Description |
| ------ | ------------------------------------------------- |
| `401` | Invalid or expired API token |
| `403` | Token doesn't have permission for this operation |
| `404` | Resource not found or not accessible by this team |
### Example Error Response
```json
{
"message": "You do not have permission to access this resource"
}
```
<Callout type="warn">
API tokens can only access resources belonging to their associated team. Attempting to access
resources from another team returns a 403 or 404 error.
</Callout>
## See Also
- [Documents API](/docs/developers/api/documents) - Create and manage documents
- [Templates API](/docs/developers/api/templates) - Work with document templates
- [Authentication](/docs/developers/getting-started/authentication) - Create and manage API tokens
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
---
title: API Versioning
description: Versioning information for the Documenso public API.
---
import { Callout } from 'fumadocs-ui/components/callout';
## Overview
Documenso uses API versioning to manage changes to the public API. This allows us to introduce new features, fix bugs, and make other changes without breaking existing integrations.
<Callout type="info">The current version of the API is `v2`.</Callout>
The API version is specified in the URL. For example, the base URL for the `v2` API is `https://app.documenso.com/api/v2`.
We may make changes to the API without incrementing the version number. We will always try to avoid breaking changes, but in some cases, it may be necessary to make changes that are not backward compatible. In these cases, we will increment the version number and provide information about the changes in the release notes.
Also, we may deprecate certain features or endpoints in the API. When we deprecate a feature or endpoint, we will provide information about the deprecation in the release notes and give a timeline for when the feature or endpoint will be removed.
---
## See Also
- [Authentication](/docs/developers/getting-started/authentication) - API authentication guide
- [Rate Limits](/docs/developers/api/rate-limits) - API rate limit details