---
title: Documents API
description: 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

```json
{
  "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/documents
```

### Required 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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X GET "https://api.seal.nyc/api/v1/documents?limit=20&status=sent" \
  -H "Authorization: Bearer ak_your_api_key_here"
```

### Response

```json
{
  "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

```typescript
const response = await fetch(
  "https://api.seal.nyc/api/v1/documents/get?id=jd7k8l9m0n1p2q3r4s5t6u7v&include_recipients=true",
  {
    headers: {
      Authorization: "Bearer ak_your_api_key_here",
    },
  }
);

const document = await response.json();
```

### cURL Example

```bash
curl -X GET "https://api.seal.nyc/api/v1/documents/get?id=jd7k8l9m0n1p2q3r4s5t6u7v&include_recipients=true" \
  -H "Authorization: Bearer ak_your_api_key_here"
```

### Response

```json
{
  "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://api.seal.nyc/api/v1/documents/download?id=...",
  "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/documents
```

### Required 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

```typescript
const response = await fetch("https://api.seal.nyc/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

```bash
curl -X POST https://api.seal.nyc/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

```json
{
  "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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X PUT "https://api.seal.nyc/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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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 200
```

### cURL Example

```bash
curl -X DELETE "https://api.seal.nyc/api/v1/documents/delete?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
  -H "Authorization: Bearer ak_your_api_key_here"
```

### Response

```json
{
  "deleted": true
}
```

> **Warn**
>
> **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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X POST "https://api.seal.nyc/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.

```json
{
  "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://api.seal.nyc/api/v1/documents/download?id=..."
}
```

## 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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X POST "https://api.seal.nyc/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

```json
{
  "id": "jd7k8l9m0n1p2q3r4s5t6u7v",
  "status": "cancelled",
  "voided_at": "2024-01-27T12:00:00Z",
  "void_reason": "Contract terms changed"
}
```

> **Info**
>
> **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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X GET "https://api.seal.nyc/api/v1/documents/download?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
  -H "Authorization: Bearer ak_your_api_key_here"
```

### Response

```json
{
  "download_url": "https://api.seal.nyc/api/v1/documents/download-file?token=...",
  "expires_at": "2024-01-27T11:00:00Z"
}
```

> **Info**
>
> **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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X GET "https://api.seal.nyc/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
  -H "Authorization: Bearer ak_your_api_key_here"
```

### Response

```json
{
  "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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X PATCH "https://api.seal.nyc/api/v1/documents/access?id=jd7k8l9m0n1p2q3r4s5t6u7v" \
  -H "Authorization: Bearer ak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"sharing_mode": "workspace"}'
```

### Response

```json
{
  "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-void
```

### Required 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

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X POST "https://api.seal.nyc/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

```json
{
  "total_requested": 2,
  "succeeded": 1,
  "failed": 1,
  "results": [
    {
      "id": "jd7k8l9m0n1p2q3r4s5t6u7v",
      "success": true
    },
    {
      "id": "ab1cd2ef3gh4ij5kl6mn7op8",
      "success": false,
      "error": "Cannot void a completed document"
    }
  ]
}
```

> **Warn**
>
> 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-send
```

### Required Scope

`seal:documents:write`

### Request Body

| Field          | Type     | Required | Description                             |
| -------------- | -------- | -------- | --------------------------------------- |
| `document_ids` | string[] | Yes      | IDs of draft documents to send (max 50) |

### TypeScript Example

```typescript
const response = await fetch(
  "https://api.seal.nyc/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

```bash
curl -X POST "https://api.seal.nyc/api/v1/documents/bulk-send" \
  -H "Authorization: Bearer ak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "document_ids": [
      "jd7k8l9m0n1p2q3r4s5t6u7v",
      "ab1cd2ef3gh4ij5kl6mn7op8"
    ]
  }'
```

### Response

```json
{
  "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"
    }
  ]
}
```

> **Info**
>
> 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](/docs/api-reference/recipients)** - Manage document recipients
- **[Uploads API](/docs/api-reference/uploads)** - Generate upload URLs for documents
- **[Analytics API](/docs/api-reference/analytics)** - Completion rates and signing metrics
- **[Webhooks](/docs/webhooks)** - Receive real-time document status updates
