API v1 is deprecated. For new integrations, please use API v2.
Overview
Recipients are the people who need to take action on a document. Each recipient has a role that determines what they can do (sign, approve, view, etc.).
In v1, recipients are typically added during document creation, but you can also add, update, or remove them before sending the document.
Recipient Object
{
"id": 1,
"documentId": 123,
"email": "john@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingOrder": 1,
"token": "abc123xyz",
"expiresAt": null,
"expirationNotifiedAt": null,
"signedAt": null,
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "NOT_SENT",
"signingUrl": "https://app.documenso.com/sign/abc123xyz"
}
Properties
| Field | Type | Description |
|---|
id | number | Unique recipient identifier |
documentId | number | ID of the parent document |
email | string | Recipient’s email address |
name | string | Recipient’s full name |
role | string | Recipient role (see Recipient Roles) |
signingOrder | number | null | Order for sequential signing |
token | string | Unique token for signing URL |
expiresAt | string | null | Expiration timestamp |
expirationNotifiedAt | string | null | When expiration notice was sent |
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 |
signingUrl | string | URL for recipient to sign the document |
Recipient Roles
| Role | Description |
|---|
SIGNER | Must sign the document. This is the default role. |
APPROVER | Must approve the document before signers can proceed. |
CC | Receives a copy of the completed document. No action required. |
VIEWER | Can view the document but takes no action. |
ASSISTANT | Can fill in fields on behalf of another recipient. |
Add Recipient
Add a single recipient to a document in DRAFT status.
POST /api/v1/documents/:id/recipients
Path Parameters
| Parameter | Type | Description |
|---|
id | number | The document ID |
Request Body
| Field | Type | Required | Description |
|---|
name | string | Yes | Recipient’s full name |
email | string | Yes | Recipient’s email address |
role | string | No | Default: SIGNER |
signingOrder | number | No | Position in sequential signing |
authOptions | object | No | Authentication options (Enterprise only) |
Auth Options Schema
| Field | Type | Description |
|---|
actionAuth | array | Authentication methods required for actions |
Available authentication methods:
ACCOUNT - Must be logged in
PASSKEY - Must use passkey authentication
TWO_FACTOR_AUTH - Must provide 2FA code
Code Examples
# Basic recipient
curl -X POST "https://app.documenso.com/api/v1/documents/123/recipients" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"role": "SIGNER"
}'
# With signing order
curl -X POST "https://app.documenso.com/api/v1/documents/123/recipients" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"role": "APPROVER",
"signingOrder": 1
}'
# With auth options (Enterprise)
curl -X POST "https://app.documenso.com/api/v1/documents/123/recipients" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Johnson",
"email": "alice@example.com",
"role": "SIGNER",
"authOptions": {
"actionAuth": ["ACCOUNT", "TWO_FACTOR_AUTH"]
}
}'
import { initClient } from '@ts-rest/core';
import { ApiContractV1 } from '@documenso/api/v1/contract';
const client = initClient(ApiContractV1, {
baseUrl: 'https://app.documenso.com/api/v1',
baseHeaders: {
authorization: 'Bearer api_xxxxxxxxxxxxxxxx',
},
});
// Add a basic signer
const { status, body } = await client.createRecipient({
params: { id: '123' },
body: {
name: 'John Doe',
email: 'john@example.com',
role: 'SIGNER',
},
});
if (status === 200) {
console.log(`Recipient added: ${body.id}`);
console.log(`Signing URL: ${body.signingUrl}`);
}
// Add an approver with signing order
const approverResponse = await client.createRecipient({
params: { id: '123' },
body: {
name: 'Jane Smith',
email: 'jane@example.com',
role: 'APPROVER',
signingOrder: 1,
},
});
Response
{
"id": 2,
"documentId": 123,
"email": "john@example.com",
"name": "John Doe",
"role": "SIGNER",
"signingOrder": null,
"token": "def456uvw",
"expiresAt": null,
"expirationNotifiedAt": null,
"signedAt": null,
"readStatus": "NOT_OPENED",
"signingStatus": "NOT_SIGNED",
"sendStatus": "NOT_SENT",
"signingUrl": "https://app.documenso.com/sign/def456uvw"
}
You can only add recipients to documents in DRAFT status. Once a document is sent (PENDING), recipients cannot be added or removed.
Update Recipient
Update a recipient’s details before the document is sent.
PATCH /api/v1/documents/:id/recipients/:recipientId
Path Parameters
| Parameter | Type | Description |
|---|
id | number | The document ID |
recipientId | number | The recipient ID |
Request Body
All fields are optional. Only include the fields you want to update:
| Field | Type | Description |
|---|
name | string | Recipient’s full name |
email | string | Recipient’s email address |
role | string | Recipient role |
signingOrder | number | Position in sequential signing |
authOptions | object | Authentication options |
Code Examples
# Update email
curl -X PATCH "https://app.documenso.com/api/v1/documents/123/recipients/2" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"email": "newemail@example.com"
}'
# Update name and role
curl -X PATCH "https://app.documenso.com/api/v1/documents/123/recipients/2" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "John Smith",
"role": "APPROVER"
}'
# Update signing order
curl -X PATCH "https://app.documenso.com/api/v1/documents/123/recipients/2" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"signingOrder": 2
}'
// Update recipient email
const { status, body } = await client.updateRecipient({
params: { id: '123', recipientId: '2' },
body: {
email: 'newemail@example.com',
},
});
if (status === 200) {
console.log(`Updated recipient: ${body.id}`);
console.log(`New email: ${body.email}`);
}
// Update multiple fields
const updateResponse = await client.updateRecipient({
params: { id: '123', recipientId: '2' },
body: {
name: 'John Smith',
role: 'APPROVER',
signingOrder: 2,
},
});
Response
Returns the updated recipient object.
Remove Recipient
Remove a recipient from a document in DRAFT status.
DELETE /api/v1/documents/:id/recipients/:recipientId
Path Parameters
| Parameter | Type | Description |
|---|
id | number | The document ID |
recipientId | number | The recipient ID |
Code Examples
curl -X DELETE "https://app.documenso.com/api/v1/documents/123/recipients/2" \
-H "Authorization: Bearer api_xxxxxxxxxxxxxxxx"
const { status, body } = await client.deleteRecipient({
params: { id: '123', recipientId: '2' },
body: null,
});
if (status === 200) {
console.log(`Removed recipient ${body.id}`);
}
Response
Returns the deleted recipient object.
Removing a recipient also removes all fields assigned to that recipient.
Sequential Signing
For workflows where recipients must sign in a specific order, use the signingOrder field:
// First, set document signing order to SEQUENTIAL
await client.createDocument({
body: {
title: 'Contract',
recipients: [
{
name: 'Approver',
email: 'approver@example.com',
role: 'APPROVER',
signingOrder: 1, // Signs first
},
{
name: 'Manager',
email: 'manager@example.com',
role: 'SIGNER',
signingOrder: 2, // Signs second
},
{
name: 'Employee',
email: 'employee@example.com',
role: 'SIGNER',
signingOrder: 3, // Signs last
},
],
meta: {
signingOrder: 'SEQUENTIAL',
},
},
});
How Sequential Signing Works
- Only the recipient with
signingOrder: 1 receives the initial email
- After they sign, the recipient with
signingOrder: 2 receives an email
- This continues until all recipients have signed
- Recipients with
signingOrder: null can sign at any time (parallel)
Signing URLs
Every recipient has a unique signing URL that can be shared directly:
const { body } = await client.createDocument({
body: {
title: 'Contract',
recipients: [{ name: 'John', email: 'john@example.com', role: 'SIGNER' }],
},
});
// Get signing URL from response
const signingUrl = body.recipients[0].signingUrl;
console.log(`Send this to recipient: ${signingUrl}`);
// https://app.documenso.com/sign/abc123xyz
// Or send via email automatically
await client.sendDocument({
params: { id: body.documentId.toString() },
body: { sendEmail: true },
});
Recipient Status
Recipients have three status fields:
Read Status
| Status | Description |
|---|
NOT_OPENED | Recipient hasn’t opened the document |
OPENED | Recipient has viewed the document |
Signing Status
| Status | Description |
|---|
NOT_SIGNED | Recipient hasn’t signed yet |
SIGNED | Recipient has completed signing |
REJECTED | Recipient rejected the document |
Send Status
| Status | Description |
|---|
NOT_SENT | Email hasn’t been sent to recipient |
SENT | Email has been sent to recipient |
Checking Recipient Progress
const { body: document } = await client.getDocument({
params: { id: '123' },
});
document.recipients.forEach((recipient) => {
console.log(`${recipient.name}:`);
console.log(` Sent: ${recipient.sendStatus}`);
console.log(` Opened: ${recipient.readStatus}`);
console.log(` Signed: ${recipient.signingStatus}`);
if (recipient.signedAt) {
console.log(` Signed at: ${recipient.signedAt}`);
}
});
Complete Example
import { initClient } from '@ts-rest/core';
import { ApiContractV1 } from '@documenso/api/v1/contract';
const client = initClient(ApiContractV1, {
baseUrl: 'https://app.documenso.com/api/v1',
baseHeaders: {
authorization: 'Bearer api_xxxxxxxxxxxxxxxx',
},
});
async function manageRecipients() {
// 1. Create document with initial recipient
const { body: createBody } = await client.createDocument({
body: {
title: 'Service Agreement',
recipients: [
{
name: 'John Doe',
email: 'john@example.com',
role: 'SIGNER',
},
],
},
});
const documentId = createBody.documentId;
const { uploadUrl } = createBody;
// Upload PDF...
await fetch(uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': 'application/octet-stream' },
body: pdfBuffer,
});
// 2. Add another recipient
const { body: approver } = await client.createRecipient({
params: { id: documentId.toString() },
body: {
name: 'Jane Smith',
email: 'jane@example.com',
role: 'APPROVER',
signingOrder: 1,
},
});
console.log(`Added approver: ${approver.id}`);
// 3. Update existing recipient signing order
await client.updateRecipient({
params: {
id: documentId.toString(),
recipientId: createBody.recipients[0].recipientId.toString(),
},
body: {
signingOrder: 2, // Signs after approver
},
});
// 4. Add fields for each recipient
await client.createField({
params: { id: documentId.toString() },
body: {
type: 'SIGNATURE',
recipientId: approver.id,
pageNumber: 1,
pageX: 10,
pageY: 80,
pageWidth: 30,
pageHeight: 5,
fieldMeta: {},
},
});
// 5. Send document
await client.sendDocument({
params: { id: documentId.toString() },
body: { sendEmail: true },
});
console.log('Document sent to recipients!');
}
manageRecipients().catch(console.error);
Best Practices
1. Validate Email Addresses
Always validate email addresses before adding recipients:
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
if (!isValidEmail(recipientEmail)) {
throw new Error('Invalid email address');
}
2. Handle Duplicate Recipients
Check for duplicate email addresses before adding recipients:
const { body: document } = await client.getDocument({ params: { id: '123' } });
const emailExists = document.recipients.some(
(r) => r.email === newRecipientEmail
);
if (emailExists) {
console.warn('Recipient already exists');
}
3. Use Appropriate Roles
| Use Case | Recommended Role |
|---|
| Must sign document | SIGNER |
| Must approve before others | APPROVER |
| Just needs a copy | CC |
| Can view but not sign | VIEWER |
4. Sequential Signing Order
When using sequential signing, ensure signingOrder starts at 1 and increments:
const recipients = [
{ name: 'First', email: 'first@example.com', signingOrder: 1 },
{ name: 'Second', email: 'second@example.com', signingOrder: 2 },
{ name: 'Third', email: 'third@example.com', signingOrder: 3 },
];
See Also