Documents API
Complete API reference for document management endpoints
Documents API
The Documents API allows you to upload, send, track, void, and download signed documents. Documents are the core resource in Seal's signing workflow.
The Document Object
Attributes
| Attribute | Type | Description |
|---|---|---|
id | string | Unique document identifier |
title | string | Document title |
description | string | Optional document description |
status | string | Workflow status: draft, sent, in_progress, completed, cancelled, declined |
created_at | string | ISO 8601 creation timestamp |
updated_at | string | ISO 8601 last update timestamp |
recipients_count | number | Total number of recipients |
signed_count | number | Number of recipients who have signed |
deadline | string | Optional ISO 8601 signing deadline |
Example Object
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"title": "Service Agreement",
"description": "Annual service contract for review and signature",
"status": "sent",
"created_at": "2024-01-27T10:30:00Z",
"updated_at": "2024-01-27T10:31:00Z",
"recipients_count": 2,
"signed_count": 0,
"deadline": "2024-02-10T23:59:59Z"
}List Documents
Retrieve a paginated list of documents for your organization.
Endpoint
GET /api/v1/documentsRequired Scope
seal:documents:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | number | Number of results (max 100, default 20) |
cursor | string | Pagination cursor from previous response |
status | string | Filter by workflow status |
TypeScript Example
const response = await fetch("https://seal.convex.site/api/v1/documents?limit=20&status=sent", {
headers: {
Authorization: "Bearer ak_your_api_key_here",
},
});
const { data, has_more, next_cursor } = await response.json();cURL Example
curl -X GET "https://seal.convex.site/api/v1/documents?limit=20&status=sent" \
-H "Authorization: Bearer ak_your_api_key_here"Response
{
"data": [
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"title": "Service Agreement",
"status": "sent",
"created_at": "2024-01-27T10:30:00Z",
"updated_at": "2024-01-27T10:31:00Z",
"recipients_count": 2,
"signed_count": 0
}
],
"has_more": false,
"next_cursor": null
}Get Document
Retrieve a single document by ID.
Endpoint
GET /api/v1/documents/get?id={id}Required Scope
seal:documents:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
include_recipients | boolean | Include recipient details in response |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/get?id=jd7k8l9m0n1p2q3r4s5t6u7v&include_recipients=true",
{
headers: {
Authorization: "Bearer ak_your_api_key_here",
},
},
);
const document = await response.json();cURL Example
curl -X GET "https://seal.convex.site/api/v1/documents/get?id=jd7k8l9m0n1p2q3r4s5t6u7v&include_recipients=true" \
-H "Authorization: Bearer ak_your_api_key_here"Response
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"title": "Service Agreement",
"description": "Annual service contract",
"status": "sent",
"created_at": "2024-01-27T10:30:00Z",
"updated_at": "2024-01-27T10:31:00Z",
"recipients_count": 2,
"signed_count": 1,
"download_url": "https://storage.convex.cloud/...",
"recipients": [
{
"id": "rec_abc123",
"email": "john@example.com",
"name": "John Doe",
"role": "signer",
"status": "signed",
"signed_at": "2024-01-27T11:00:00Z"
},
{
"id": "rec_def456",
"email": "jane@example.com",
"name": "Jane Smith",
"role": "signer",
"status": "pending"
}
]
}Create Document
Create a new document from an uploaded file.
Endpoint
POST /api/v1/documentsRequired Scope
seal:documents:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Document title |
description | string | No | Document description |
storage_id | string | Yes | Storage ID from upload endpoint |
file_size | number | Yes | File size in bytes |
file_type | string | Yes | MIME type (e.g., "application/pdf") |
page_count | number | No | Number of pages in document |
deadline | string | No | ISO 8601 signing deadline |
TypeScript Example
const response = await fetch("https://seal.convex.site/api/v1/documents", {
method: "POST",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Service Agreement",
description: "Annual service contract",
storage_id: "kg2h4j5k6l7m8n9p0q1r2s3t",
file_size: 245760,
file_type: "application/pdf",
page_count: 5,
deadline: "2024-02-10T23:59:59Z",
}),
});
const document = await response.json();cURL Example
curl -X POST https://seal.convex.site/api/v1/documents \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "Service Agreement",
"description": "Annual service contract",
"storage_id": "kg2h4j5k6l7m8n9p0q1r2s3t",
"file_size": 245760,
"file_type": "application/pdf",
"page_count": 5,
"deadline": "2024-02-10T23:59:59Z"
}'Response
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"title": "Service Agreement",
"description": "Annual service contract",
"status": "draft",
"created_at": "2024-01-27T10:30:00Z",
"updated_at": "2024-01-27T10:30:00Z",
"recipients_count": 0,
"signed_count": 0,
"deadline": "2024-02-10T23:59:59Z"
}Update Document
Update a document's metadata.
Endpoint
PUT /api/v1/documents/update?id={id}Required Scope
seal:documents:write
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
Request Body
| Field | Type | Description |
|---|---|---|
title | string | New document title |
description | string | New document description |
deadline | string | New ISO 8601 signing deadline |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/update?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
method: "PUT",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Updated Service Agreement",
deadline: "2024-02-15T23:59:59Z",
}),
},
);
const document = await response.json();cURL Example
curl -X PUT "https://seal.convex.site/api/v1/documents/update?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Service Agreement",
"deadline": "2024-02-15T23:59:59Z"
}'Delete Document
Permanently delete a document.
Endpoint
DELETE /api/v1/documents/delete?id={id}Required Scope
seal:documents:write
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/delete?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
method: "DELETE",
headers: {
Authorization: "Bearer ak_your_api_key_here",
},
},
);
const result = await response.json();
// Returns { "deleted": true } with status 200cURL Example
curl -X DELETE "https://seal.convex.site/api/v1/documents/delete?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here"Response
{
"deleted": true
}Warning: Deleting a document is permanent and cannot be undone. All associated recipients, signatures, and audit trail data will also be deleted.
Send Document
Send a document to all recipients for signing.
Endpoint
POST /api/v1/documents/send?id={id}Required Scope
seal:documents:write
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
message | string | No | Custom message to include in email notification |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/send?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
method: "POST",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
message: "Please review and sign this agreement at your earliest convenience.",
}),
},
);
const result = await response.json();cURL Example
curl -X POST "https://seal.convex.site/api/v1/documents/send?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"message": "Please review and sign this agreement."
}'Response
Returns the updated document object.
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"title": "Service Agreement",
"status": "sent",
"created_at": "2024-01-27T10:30:00Z",
"updated_at": "2024-01-27T10:31:00Z",
"recipients_count": 2,
"signed_count": 0,
"download_url": "https://storage.convex.cloud/..."
}Void Document
Cancel a document and prevent further signing.
Endpoint
POST /api/v1/documents/void?id={id}Required Scope
seal:documents:write
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No | Reason for voiding the document |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/void?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
method: "POST",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
reason: "Contract terms changed, new version required",
}),
},
);
const result = await response.json();cURL Example
curl -X POST "https://seal.convex.site/api/v1/documents/void?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"reason": "Contract terms changed"
}'Response
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"status": "cancelled",
"voided_at": "2024-01-27T12:00:00Z",
"void_reason": "Contract terms changed"
}Note: Voiding a document prevents recipients from signing but preserves the document and audit trail for record-keeping.
Download Document
Get a temporary download URL for the document PDF.
Endpoint
GET /api/v1/documents/download?id={id}Required Scope
seal:documents:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/download?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
headers: {
Authorization: "Bearer ak_your_api_key_here",
},
},
);
const { download_url, expires_at } = await response.json();
// Download the file
const fileResponse = await fetch(download_url);
const blob = await fileResponse.blob();cURL Example
curl -X GET "https://seal.convex.site/api/v1/documents/download?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here"Response
{
"download_url": "https://storage.convex.cloud/...",
"expires_at": "2024-01-27T11:00:00Z"
}Note: Download URLs are temporary and expire after a short period (typically 1 hour). Generate a new URL if the previous one has expired.
Get Document Access
Retrieve the current sharing mode for a document.
Endpoint
GET /api/v1/documents/access?id={id}Required Scope
seal:documents:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
headers: {
Authorization: "Bearer ak_your_api_key_here",
},
},
);
const access = await response.json();
console.log(access.sharing_mode); // "private" | "workspace" | "specific"cURL Example
curl -X GET "https://seal.convex.site/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here"Response
{
"document_id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"sharing_mode": "private"
}sharing_mode | Description |
|---|---|
private | Only the document owner can access it |
workspace | All workspace members can view the document (Pro) |
specific | Access granted to specific users only |
Update Document Access
Change the sharing mode for a document.
Endpoint
PATCH /api/v1/documents/access?id={id}Required Scope
seal:documents:write
Query Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Required. Document ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
sharing_mode | string | Yes | New sharing mode: private, workspace, or specific |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v",
{
method: "PATCH",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({ sharing_mode: "workspace" }),
},
);
const result = await response.json();
// { "success": true }cURL Example
curl -X PATCH "https://seal.convex.site/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"sharing_mode": "workspace"}'Response
{
"success": true
}Bulk Void Documents
Void (cancel) multiple documents in a single request. Each document is processed independently — failures in one do not block others.
Endpoint
POST /api/v1/documents/bulk-voidRequired Scope
seal:documents:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
document_ids | string[] | Yes | IDs of documents to void (max 50) |
reason | string | No | Cancellation reason shown to recipients |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/bulk-void",
{
method: "POST",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
document_ids: [
"jd7k8l9m0n1p2q3r4s5t6u7v",
"ab1cd2ef3gh4ij5kl6mn7op8",
],
reason: "Contract terms updated — please sign the revised version",
}),
},
);
const result = await response.json();
console.log(`Voided: ${result.succeeded} / ${result.total_requested}`);cURL Example
curl -X POST "https://seal.convex.site/api/v1/documents/bulk-void" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"document_ids": ["jd7k8l9m0n1p2q3r4s5t6u7v", "ab1cd2ef3gh4ij5kl6mn7op8"],
"reason": "Superseded by revised agreement"
}'Response
{
"total_requested": 2,
"succeeded": 1,
"failed": 1,
"results": [
{
"id": "jd7k8l9m0n1p2q3r4s5t6u7v",
"success": true
},
{
"id": "ab1cd2ef3gh4ij5kl6mn7op8",
"success": false,
"error": "Cannot void a completed document"
}
]
}Documents that are already completed, cancelled, or declined cannot be voided and will appear in results with success: false.
Bulk Send Documents
Send multiple draft documents to their recipients in a single request. Each document is processed independently.
Endpoint
POST /api/v1/documents/bulk-sendRequired Scope
seal:documents:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
document_ids | string[] | Yes | IDs of draft documents to send (max 50) |
TypeScript Example
const response = await fetch(
"https://seal.convex.site/api/v1/documents/bulk-send",
{
method: "POST",
headers: {
Authorization: "Bearer ak_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
document_ids: [
"jd7k8l9m0n1p2q3r4s5t6u7v",
"ab1cd2ef3gh4ij5kl6mn7op8",
"cd3ef4gh5ij6kl7mn8op9qr0",
],
}),
},
);
const result = await response.json();
console.log(`Sent: ${result.succeeded} / ${result.total_requested}`);cURL Example
curl -X POST "https://seal.convex.site/api/v1/documents/bulk-send" \
-H "Authorization: Bearer ak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"document_ids": [
"jd7k8l9m0n1p2q3r4s5t6u7v",
"ab1cd2ef3gh4ij5kl6mn7op8"
]
}'Response
{
"total_requested": 3,
"succeeded": 2,
"failed": 1,
"results": [
{ "id": "jd7k8l9m0n1p2q3r4s5t6u7v", "success": true },
{ "id": "ab1cd2ef3gh4ij5kl6mn7op8", "success": true },
{
"id": "cd3ef4gh5ij6kl7mn8op9qr0",
"success": false,
"error": "Document has no recipients"
}
]
}Only draft documents with at least one recipient can be bulk-sent. Documents that are already sent, completed, or cancelled will appear in results with success: false.
Document Status Workflow
Documents progress through the following statuses:
draft → sent → in_progress → completed
↓
cancelled (voided)
↓
declined (recipient declined)| Status | Description |
|---|---|
draft | Document created but not yet sent |
sent | Document sent to recipients |
in_progress | At least one recipient has viewed/signed |
completed | All recipients have completed their actions |
cancelled | Document voided by sender |
declined | Document declined by a recipient |
Next Steps
- Recipients API - Manage document recipients
- Uploads API - Generate upload URLs for documents
- Analytics API - Completion rates and signing metrics
- Webhooks - Receive real-time document status updates
Last updated on