mirror of
https://github.com/documenso/documenso.git
synced 2026-08-22 14:22:21 +10:00
Merge branch 'main' into feature/pdf-placeholder-selection-fields
This commit is contained in:
@@ -6,6 +6,8 @@ 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';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
<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).
|
||||
|
||||
@@ -5,6 +5,8 @@ description: Complete reference for the Documenso REST API.
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
<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).
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"teams",
|
||||
"rate-limits",
|
||||
"versioning",
|
||||
"migrate-to-envelopes",
|
||||
"developer-mode",
|
||||
"common-errors"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
---
|
||||
title: Migrating to Envelopes
|
||||
description: Why Documenso unified documents and templates into envelopes, and how to migrate from the deprecated document and template create endpoints.
|
||||
---
|
||||
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
## Summary
|
||||
|
||||
The following items have been deprecated and will be removed on the <strong>1st of March 2027</strong>:
|
||||
|
||||
- <strong>API V1</strong>
|
||||
- <strong>A subset of SDK/API V2 endpoints</strong>
|
||||
- <strong>Legacy documents and templates</strong>
|
||||
- <strong>EmbedCreateDocumentV1</strong>
|
||||
- <strong>EmbedCreateTemplateV1</strong>
|
||||
- <strong>EmbedUpdateDocumentV1</strong>
|
||||
- <strong>EmbedUpdateTemplateV1</strong>
|
||||
|
||||
The beta endpoint `/api/v2-beta` will also be removed. Use `/api/v2` instead, which is a drop-in replacement.
|
||||
|
||||
Nothing breaks before 1st of March 2027, so you can migrate at your own pace.
|
||||
|
||||
## What are legacy documents and templates
|
||||
|
||||
These are documents and templates created by the following endpoints:
|
||||
|
||||
- `POST /api/v2/document/create`
|
||||
- `POST /api/v2/document/create/beta`
|
||||
- `POST /api/v2/template/create`
|
||||
- `POST /api/v2/template/create/beta`
|
||||
- `POST /api/v1/documents`
|
||||
- `POST /api/v1/templates`
|
||||
- `POST /api/v1/templates/create-document`
|
||||
- `POST /api/v1/templates/generate-document`
|
||||
|
||||
## What replaces legacy documents and templates
|
||||
|
||||
At the end of 2025 we introduced a unified system for documents and templates, called <strong>envelopes</strong>.
|
||||
|
||||
We still reference documents and templates throughout the documentation and application to distinguish them, but internally they are envelopes.
|
||||
|
||||
Moving to the envelope system gives you:
|
||||
|
||||
- **Multiple PDFs in one envelope.** Send several documents to sign in a single request.
|
||||
- **One API for documents and templates.** Learn one set of endpoints instead of two misaligned ones.
|
||||
- **A better editor and signing experience** for you and your recipients.
|
||||
|
||||
## How to migrate
|
||||
|
||||
{/* prettier-ignore */}
|
||||
<Steps>
|
||||
<Step>
|
||||
### Switch to the envelope endpoints
|
||||
|
||||
Replace each deprecated endpoint with its `/api/v2/envelope/*` equivalent from the [mapping tables](#endpoint-mapping-reference) below.
|
||||
</Step>
|
||||
<Step>
|
||||
### Set the envelope `type` on create
|
||||
|
||||
A single endpoint, `POST /api/v2/envelope/create`, can create both documents and templates. Set `type` to `DOCUMENT` or `TEMPLATE`. You can now upload more than one PDF using the `files` field.
|
||||
</Step>
|
||||
<Step>
|
||||
### Update how you store IDs
|
||||
|
||||
Envelope IDs are **strings** (for example `envelope_abc123`), not numbers. Update any code that stores, parses, or compares IDs.
|
||||
</Step>
|
||||
<Step>
|
||||
### Test, then remove the old calls
|
||||
|
||||
Verify the new flow against your account, then delete the deprecated calls.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
The main data differences are as follows:
|
||||
- ID format changed from number to string (e.g. `42` to `envelope_abc123`)
|
||||
- pageNumber becomes page
|
||||
- pageX becomes positionX
|
||||
- pageY becomes positionY
|
||||
|
||||
See the [Documents API](/docs/developers/api/documents) and [Templates API](/docs/developers/api/templates) for the full envelope reference.
|
||||
|
||||
### Deprecated V1 API Endpoints
|
||||
|
||||
Full reference in the [V1 OpenAPI reference](https://openapi-v1.documenso.com).
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| -------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| `GET /api/v1/documents` | `GET /api/v2/envelope` |
|
||||
| `GET /api/v1/documents/{id}` | `GET /api/v2/envelope/{envelopeId}` |
|
||||
| `POST /api/v1/documents` | `POST /api/v2/envelope/create` |
|
||||
| `POST /api/v1/documents/{id}/send` | `POST /api/v2/envelope/distribute` |
|
||||
| `POST /api/v1/documents/{id}/resend` | `POST /api/v2/envelope/redistribute` |
|
||||
| `DELETE /api/v1/documents/{id}` | `POST /api/v2/envelope/delete` |
|
||||
| `GET /api/v1/documents/{id}/download` | `GET /api/v2/envelope/item/{envelopeItemId}/download` |
|
||||
| `POST /api/v1/documents/{id}/recipients` | `POST /api/v2/envelope/recipient/create-many` |
|
||||
| `PATCH /api/v1/documents/{id}/recipients/{recipientId}` | `POST /api/v2/envelope/recipient/update-many` |
|
||||
| `DELETE /api/v1/documents/{id}/recipients/{recipientId}` | `POST /api/v2/envelope/recipient/delete` |
|
||||
| `POST /api/v1/documents/{id}/fields` | `POST /api/v2/envelope/field/create-many` |
|
||||
| `PATCH /api/v1/documents/{id}/fields/{fieldId}` | `POST /api/v2/envelope/field/update-many` |
|
||||
| `DELETE /api/v1/documents/{id}/fields/{fieldId}` | `POST /api/v2/envelope/field/delete` |
|
||||
| `GET /api/v1/templates` | `GET /api/v2/envelope` (with `type=TEMPLATE`) |
|
||||
| `GET /api/v1/templates/{id}` | `GET /api/v2/envelope/{envelopeId}` |
|
||||
| `POST /api/v1/templates` | `POST /api/v2/envelope/create` (`type=TEMPLATE`) |
|
||||
| `DELETE /api/v1/templates/{id}` | `POST /api/v2/envelope/delete` |
|
||||
| `POST /api/v1/templates/{templateId}/create-document` | `POST /api/v2/envelope/use` |
|
||||
| `POST /api/v1/templates/{templateId}/generate-document` | `POST /api/v2/envelope/use` |
|
||||
|
||||
### Deprecated V2 API Endpoints
|
||||
|
||||
Full reference in the [V2 OpenAPI reference](https://openapi.documenso.com).
|
||||
|
||||
#### Documents
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ------------------------------------------------- | ----------------------------------------------------- |
|
||||
| `GET /api/v2/document` | `GET /api/v2/envelope` |
|
||||
| `GET /api/v2/document/{documentId}` | `GET /api/v2/envelope/{envelopeId}` |
|
||||
| `POST /api/v2/document/get-many` | `POST /api/v2/envelope/get-many` |
|
||||
| `POST /api/v2/document/create` | `POST /api/v2/envelope/create` |
|
||||
| `POST /api/v2/document/create/beta` | `POST /api/v2/envelope/create` |
|
||||
| `POST /api/v2/document/update` | `POST /api/v2/envelope/update` |
|
||||
| `POST /api/v2/document/delete` | `POST /api/v2/envelope/delete` |
|
||||
| `POST /api/v2/document/duplicate` | `POST /api/v2/envelope/duplicate` |
|
||||
| `POST /api/v2/document/distribute` | `POST /api/v2/envelope/distribute` |
|
||||
| `POST /api/v2/document/redistribute` | `POST /api/v2/envelope/redistribute` |
|
||||
| `GET /api/v2/document/attachment` | `GET /api/v2/envelope/attachment` |
|
||||
| `POST /api/v2/document/attachment/create` | `POST /api/v2/envelope/attachment/create` |
|
||||
| `POST /api/v2/document/attachment/update` | `POST /api/v2/envelope/attachment/update` |
|
||||
| `POST /api/v2/document/attachment/delete` | `POST /api/v2/envelope/attachment/delete` |
|
||||
| `GET /api/v2/document/{documentId}/download` | `GET /api/v2/envelope/item/{envelopeItemId}/download` |
|
||||
| `GET /api/v2/document/{documentId}/download-beta` | `GET /api/v2/envelope/item/{envelopeItemId}/download` |
|
||||
|
||||
#### Templates
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ------------------------------------- | ------------------------------------------------ |
|
||||
| `GET /api/v2/template` | `GET /api/v2/envelope` (with `type=TEMPLATE`) |
|
||||
| `GET /api/v2/template/{templateId}` | `GET /api/v2/envelope/{envelopeId}` |
|
||||
| `POST /api/v2/template/get-many` | `POST /api/v2/envelope/get-many` |
|
||||
| `POST /api/v2/template/create` | `POST /api/v2/envelope/create` (`type=TEMPLATE`) |
|
||||
| `POST /api/v2/template/create/beta` | `POST /api/v2/envelope/create` (`type=TEMPLATE`) |
|
||||
| `POST /api/v2/template/update` | `POST /api/v2/envelope/update` |
|
||||
| `POST /api/v2/template/duplicate` | `POST /api/v2/envelope/duplicate` |
|
||||
| `POST /api/v2/template/delete` | `POST /api/v2/envelope/delete` |
|
||||
| `POST /api/v2/template/use` | `POST /api/v2/envelope/use` |
|
||||
| `POST /api/v2/template/direct/create` | **Pending replacement** |
|
||||
| `POST /api/v2/template/direct/delete` | **Pending replacement** |
|
||||
| `POST /api/v2/template/direct/toggle` | **Pending replacement** |
|
||||
|
||||
#### Document fields
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ----------------------------------------- | ----------------------------------------- |
|
||||
| `GET /api/v2/document/field/{fieldId}` | `GET /api/v2/envelope/field/{fieldId}` |
|
||||
| `POST /api/v2/document/field/create` | `POST /api/v2/envelope/field/create-many` |
|
||||
| `POST /api/v2/document/field/create-many` | `POST /api/v2/envelope/field/create-many` |
|
||||
| `POST /api/v2/document/field/update` | `POST /api/v2/envelope/field/update-many` |
|
||||
| `POST /api/v2/document/field/update-many` | `POST /api/v2/envelope/field/update-many` |
|
||||
| `POST /api/v2/document/field/delete` | `POST /api/v2/envelope/field/delete` |
|
||||
|
||||
#### Template fields
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ----------------------------------------- | ----------------------------------------- |
|
||||
| `GET /api/v2/template/field/{fieldId}` | `GET /api/v2/envelope/field/{fieldId}` |
|
||||
| `POST /api/v2/template/field/create` | `POST /api/v2/envelope/field/create-many` |
|
||||
| `POST /api/v2/template/field/create-many` | `POST /api/v2/envelope/field/create-many` |
|
||||
| `POST /api/v2/template/field/update` | `POST /api/v2/envelope/field/update-many` |
|
||||
| `POST /api/v2/template/field/update-many` | `POST /api/v2/envelope/field/update-many` |
|
||||
| `POST /api/v2/template/field/delete` | `POST /api/v2/envelope/field/delete` |
|
||||
|
||||
#### Document recipients
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ---------------------------------------------- | ---------------------------------------------- |
|
||||
| `GET /api/v2/document/recipient/{recipientId}` | `GET /api/v2/envelope/recipient/{recipientId}` |
|
||||
| `POST /api/v2/document/recipient/create` | `POST /api/v2/envelope/recipient/create-many` |
|
||||
| `POST /api/v2/document/recipient/create-many` | `POST /api/v2/envelope/recipient/create-many` |
|
||||
| `POST /api/v2/document/recipient/update` | `POST /api/v2/envelope/recipient/update-many` |
|
||||
| `POST /api/v2/document/recipient/update-many` | `POST /api/v2/envelope/recipient/update-many` |
|
||||
| `POST /api/v2/document/recipient/delete` | `POST /api/v2/envelope/recipient/delete` |
|
||||
|
||||
#### Template recipients
|
||||
|
||||
| Deprecated endpoint | Replacement |
|
||||
| ---------------------------------------------- | ---------------------------------------------- |
|
||||
| `GET /api/v2/template/recipient/{recipientId}` | `GET /api/v2/envelope/recipient/{recipientId}` |
|
||||
| `POST /api/v2/template/recipient/create` | `POST /api/v2/envelope/recipient/create-many` |
|
||||
| `POST /api/v2/template/recipient/create-many` | `POST /api/v2/envelope/recipient/create-many` |
|
||||
| `POST /api/v2/template/recipient/update` | `POST /api/v2/envelope/recipient/update-many` |
|
||||
| `POST /api/v2/template/recipient/update-many` | `POST /api/v2/envelope/recipient/update-many` |
|
||||
| `POST /api/v2/template/recipient/delete` | `POST /api/v2/envelope/recipient/delete` |
|
||||
|
||||
### Embedding components
|
||||
|
||||
| Deprecated component | Replacement |
|
||||
| ----------------------- | --------------------- |
|
||||
| `EmbedCreateDocumentV1` | `EmbedCreateEnvelope` |
|
||||
| `EmbedCreateTemplateV1` | `EmbedCreateEnvelope` |
|
||||
| `EmbedUpdateDocumentV1` | `EmbedUpdateEnvelope` |
|
||||
| `EmbedUpdateTemplateV1` | `EmbedUpdateEnvelope` |
|
||||
|
||||
See the [embedding guide](/docs/developers/embedding) for the envelope components.
|
||||
|
||||
## FAQ
|
||||
|
||||
<Accordions>
|
||||
<Accordion title="What happens on 1 March 2027?">
|
||||
The deprecated V1 API, the V2 endpoints listed above, and the V1 embedding components are removed.
|
||||
Requests to them will fail, so migrate to the envelope API before that date.
|
||||
</Accordion>
|
||||
<Accordion title="Will my existing documents and templates keep working?">
|
||||
Yes. Documents and templates you already created remain in your account and continue to work. They will automatically be converted to envelopes. Only
|
||||
the deprecated endpoints you call are going away. Your data is not deleted.
|
||||
</Accordion>
|
||||
<Accordion title="Do I need a new API token?">
|
||||
No. Authentication is unchanged. The same API token works for the envelope endpoints under
|
||||
`https://app.documenso.com/api/v2`.
|
||||
</Accordion>
|
||||
<Accordion title="What is the difference between a document and a template now?">
|
||||
Both are envelopes, distinguished by a `type` field of `DOCUMENT` or `TEMPLATE`. They share the same
|
||||
endpoints, recipients, fields, and attachments.
|
||||
</Accordion>
|
||||
<Accordion title="I use an official SDK, what should I do?">
|
||||
The function calls to the legacy endpoints will break on the 1st of March 2027. Update to the latest SDK version and switch to its envelope methods.
|
||||
The deprecated document and template methods map to the envelope endpoints in the tables above.
|
||||
</Accordion>
|
||||
<Accordion title="I need more time or help migrating">
|
||||
Reach out to [support@documenso.com](mailto:support@documenso.com) with your use case and we will
|
||||
help you plan the migration.
|
||||
</Accordion>
|
||||
</Accordions>
|
||||
|
||||
## Getting help
|
||||
|
||||
- [V2 OpenAPI reference](https://openapi.documenso.com): the up-to-date envelope API.
|
||||
- [V1 OpenAPI reference](https://openapi-v1.documenso.com): the deprecated V1 API.
|
||||
- [support@documenso.com](mailto:support@documenso.com): migration questions and extensions.
|
||||
|
||||
## See also
|
||||
|
||||
- [Documents API](/docs/developers/api/documents): create and manage envelopes
|
||||
- [Templates API](/docs/developers/api/templates): work with templates and direct links
|
||||
- [Fields API](/docs/developers/api/fields) and [Recipients API](/docs/developers/api/recipients)
|
||||
- [API Versioning](/docs/developers/api/versioning): how Documenso versions the public API
|
||||
@@ -11,9 +11,14 @@ Documenso enforces rate limits on all API endpoints to ensure service stability.
|
||||
|
||||
## HTTP Rate Limits
|
||||
|
||||
**Limit:** 100 requests per minute per IP address
|
||||
**Limit:** 1000 requests per minute per IP address
|
||||
**Response:** 429 Too Many Requests
|
||||
|
||||
<Callout type="info">
|
||||
This is the global per-IP ceiling. Your organisation may have its own rate limits configured below
|
||||
this value, in which case you can be rate-limited before reaching the global limit.
|
||||
</Callout>
|
||||
|
||||
### Rate Limit Response
|
||||
|
||||
```json
|
||||
|
||||
@@ -6,6 +6,8 @@ description: Create documents from reusable templates via API.
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
<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).
|
||||
|
||||
@@ -5,6 +5,8 @@ description: Versioning information for the Documenso public API.
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
## 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.
|
||||
@@ -19,7 +21,16 @@ Also, we may deprecate certain features or endpoints in the API. When we depreca
|
||||
|
||||
---
|
||||
|
||||
## Documents, Templates, and Envelopes
|
||||
|
||||
Documenso has unified documents and templates into a single resource called an **envelope**. New integrations should create documents and templates through the `/envelope/*` endpoints. The `POST /document/create` and `POST /template/create` endpoints (including their `/beta` variants) are deprecated in favor of `POST /envelope/create`.
|
||||
|
||||
See [Migrating to the Envelope API](/docs/developers/api/migrate-to-envelopes) for the rationale and step-by-step migration examples.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Migrating to the Envelope API](/docs/developers/api/migrate-to-envelopes) - Move from the document and template create endpoints
|
||||
- [Authentication](/docs/developers/getting-started/authentication) - API authentication guide
|
||||
- [Rate Limits](/docs/developers/api/rate-limits) - API rate limit details
|
||||
|
||||
@@ -8,6 +8,8 @@ import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
## Workflow 1: Send a Document for Signature
|
||||
|
||||
The most common workflow: upload a PDF, add recipients with signature fields, and send for signing.
|
||||
@@ -472,7 +474,7 @@ Send the same document to multiple recipients in parallel. Useful for policy ack
|
||||
<code>distributeDocument: true</code>
|
||||
</Step>
|
||||
<Step>
|
||||
Process in batches with a short delay to respect rate limits (e.g. 100 requests/minute)
|
||||
Process in batches with a short delay to respect rate limits (e.g. 1000 requests/minute)
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -638,8 +640,8 @@ done
|
||||
</Tabs>
|
||||
|
||||
<Callout type="info">
|
||||
The API allows 100 requests per minute. For large batches, implement rate limiting with delays
|
||||
between requests to avoid hitting limits.
|
||||
The API allows 1000 requests per minute (your organisation may have its own lower limit). For large
|
||||
batches, implement rate limiting with delays between requests to avoid hitting limits.
|
||||
</Callout>
|
||||
|
||||
---
|
||||
|
||||
@@ -3,6 +3,8 @@ title: Examples
|
||||
description: Common integration patterns and end-to-end workflows.
|
||||
---
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
title="Common Workflows"
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Documenso account (cloud or self-hosted)
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, you need:
|
||||
@@ -483,7 +485,7 @@ The API returns standard HTTP status codes and JSON error responses:
|
||||
|
||||
### Handling Rate Limits
|
||||
|
||||
The API allows 100 requests per minute per IP address. When rate limited, wait at least 60 seconds before retrying:
|
||||
The API allows 1000 requests per minute per IP address. Your organisation may have its own lower rate limits. When rate limited, wait at least 60 seconds before retrying:
|
||||
|
||||
```javascript
|
||||
async function fetchWithRetry(url, options, maxRetries = 3) {
|
||||
|
||||
@@ -3,6 +3,8 @@ title: Getting Started
|
||||
description: Get your API key and make your first API call.
|
||||
---
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
title="Authentication"
|
||||
|
||||
@@ -3,6 +3,8 @@ title: Developer Guide
|
||||
description: Integrate Documenso into your applications using the REST API, webhooks, and embedding options.
|
||||
---
|
||||
|
||||
<EnvelopeWarning />
|
||||
|
||||
## Getting Started
|
||||
|
||||
<Cards>
|
||||
|
||||
@@ -33,13 +33,14 @@ All webhook events share a common structure:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | --------- | ------------------------------------------------------ |
|
||||
| `id` | number | Document or template ID |
|
||||
| `id` | number | Legacy numeric v1 document or template ID |
|
||||
| `envelopeId` | string | Canonical v2 identifier (`envelope_` + 16 characters) |
|
||||
| `externalId` | string? | External identifier for integration |
|
||||
| `userId` | number | Owner's user ID |
|
||||
| `authOptions` | object? | Document-level authentication options |
|
||||
| `formValues` | object? | PDF form values associated with the document |
|
||||
| `title` | string | Document or template title |
|
||||
| `status` | string | Current status: `DRAFT`, `PENDING`, `COMPLETED` |
|
||||
| `status` | string | Current status: `DRAFT`, `PENDING`, `COMPLETED`, `REJECTED`, `CANCELLED` |
|
||||
| `visibility` | string | Document visibility setting |
|
||||
| `createdAt` | datetime | Document creation timestamp |
|
||||
| `updatedAt` | datetime | Last modification timestamp |
|
||||
@@ -47,8 +48,8 @@ All webhook events share a common structure:
|
||||
| `deletedAt` | datetime? | Deletion timestamp |
|
||||
| `teamId` | number? | Team ID if document belongs to a team |
|
||||
| `templateId` | number? | Template ID if created from a template |
|
||||
| `source` | string | Source: `DOCUMENT` or `TEMPLATE` |
|
||||
| `documentMeta` | object | Document metadata (subject, message, signing options) |
|
||||
| `source` | string | Source: `DOCUMENT`, `TEMPLATE`, or `TEMPLATE_DIRECT_LINK` |
|
||||
| `documentMeta` | object? | Nullable document metadata (subject, message, signing options) |
|
||||
| `recipients` | array | List of recipient objects |
|
||||
| `Recipient` | array | List of recipient objects (legacy, same as recipients) |
|
||||
|
||||
@@ -60,7 +61,6 @@ All webhook events share a common structure:
|
||||
| `subject` | string? | Email subject line |
|
||||
| `message` | string? | Email message body |
|
||||
| `timezone` | string | Timezone for date display |
|
||||
| `password` | string? | Document access password (if set) |
|
||||
| `dateFormat` | string | Date format string |
|
||||
| `redirectUrl` | string? | URL to redirect after signing |
|
||||
| `signingOrder` | string | `PARALLEL` or `SEQUENTIAL` |
|
||||
@@ -77,8 +77,9 @@ All webhook events share a common structure:
|
||||
| Field | Type | Description |
|
||||
| ---------------------- | --------- | ------------------------------------------ |
|
||||
| `id` | number | Recipient ID |
|
||||
| `documentId` | number? | Parent document ID |
|
||||
| `templateId` | number? | Template ID if created from a template |
|
||||
| `envelopeId` | string | Canonical parent envelope ID |
|
||||
| `documentId` | number? | Legacy parent document ID; null for templates |
|
||||
| `templateId` | number? | Legacy parent template ID; null for documents |
|
||||
| `email` | string | Recipient email address |
|
||||
| `name` | string | Recipient name |
|
||||
| `token` | string | Unique signing token |
|
||||
@@ -94,6 +95,8 @@ All webhook events share a common structure:
|
||||
| `sendStatus` | string | `NOT_SENT` or `SENT` |
|
||||
| `rejectionReason` | string? | Reason if recipient rejected |
|
||||
|
||||
Use `recipient.envelopeId` as the reliable parent link. The legacy `documentId` and `templateId` fields depend on the parent envelope type, so one of them is always null.
|
||||
|
||||
---
|
||||
|
||||
## Document Lifecycle Events
|
||||
@@ -111,6 +114,7 @@ Triggered when a new document is created.
|
||||
"event": "DOCUMENT_CREATED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"externalId": null,
|
||||
"userId": 1,
|
||||
"authOptions": null,
|
||||
@@ -129,9 +133,8 @@ Triggered when a new document is created.
|
||||
"id": "doc_meta_123",
|
||||
"subject": "Please sign this document",
|
||||
"message": "Hello, please review and sign this document.",
|
||||
"timezone": "UTC",
|
||||
"password": null,
|
||||
"dateFormat": "MM/DD/YYYY",
|
||||
"timezone": "Etc/UTC",
|
||||
"dateFormat": "yyyy-MM-dd hh:mm a",
|
||||
"redirectUrl": null,
|
||||
"signingOrder": "PARALLEL",
|
||||
"allowDictateNextSigner": false,
|
||||
@@ -145,6 +148,7 @@ Triggered when a new document is created.
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -166,6 +170,7 @@ Triggered when a new document is created.
|
||||
"Recipient": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -203,6 +208,7 @@ The document status changes to `PENDING` and recipients have `sendStatus: "SENT"
|
||||
"event": "DOCUMENT_SENT",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"externalId": null,
|
||||
"userId": 1,
|
||||
"authOptions": null,
|
||||
@@ -221,9 +227,8 @@ The document status changes to `PENDING` and recipients have `sendStatus: "SENT"
|
||||
"id": "doc_meta_123",
|
||||
"subject": "Please sign this document",
|
||||
"message": "Hello, please review and sign this document.",
|
||||
"timezone": "UTC",
|
||||
"password": null,
|
||||
"dateFormat": "MM/DD/YYYY",
|
||||
"timezone": "Etc/UTC",
|
||||
"dateFormat": "yyyy-MM-dd hh:mm a",
|
||||
"redirectUrl": null,
|
||||
"signingOrder": "PARALLEL",
|
||||
"allowDictateNextSigner": false,
|
||||
@@ -237,6 +242,7 @@ The document status changes to `PENDING` and recipients have `sendStatus: "SENT"
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -258,6 +264,7 @@ The document status changes to `PENDING` and recipients have `sendStatus: "SENT"
|
||||
"Recipient": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -295,12 +302,14 @@ The recipient's `readStatus` changes to `OPENED`.
|
||||
"event": "DOCUMENT_OPENED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "PENDING",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
@@ -328,6 +337,7 @@ The recipient's `signingStatus` changes to `SIGNED` and `signedAt` is populated.
|
||||
"event": "DOCUMENT_SIGNED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "COMPLETED",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
@@ -335,6 +345,7 @@ The recipient's `signingStatus` changes to `SIGNED` and `signedAt` is populated.
|
||||
"recipients": [
|
||||
{
|
||||
"id": 51,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
@@ -361,12 +372,14 @@ Triggered when an individual recipient completes their required action (signing,
|
||||
"event": "DOCUMENT_RECIPIENT_COMPLETED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "PENDING",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
@@ -395,6 +408,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
"event": "DOCUMENT_COMPLETED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"externalId": null,
|
||||
"userId": 1,
|
||||
"authOptions": null,
|
||||
@@ -413,9 +427,8 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
"id": "doc_meta_123",
|
||||
"subject": "Please sign this document",
|
||||
"message": "Hello, please review and sign this document.",
|
||||
"timezone": "UTC",
|
||||
"password": null,
|
||||
"dateFormat": "MM/DD/YYYY",
|
||||
"timezone": "Etc/UTC",
|
||||
"dateFormat": "yyyy-MM-dd hh:mm a",
|
||||
"redirectUrl": null,
|
||||
"signingOrder": "PARALLEL",
|
||||
"allowDictateNextSigner": false,
|
||||
@@ -429,6 +442,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
"recipients": [
|
||||
{
|
||||
"id": 50,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "reviewer@example.com",
|
||||
@@ -451,6 +465,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -475,6 +490,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
"Recipient": [
|
||||
{
|
||||
"id": 50,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "reviewer@example.com",
|
||||
@@ -497,6 +513,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -537,12 +554,14 @@ The recipient's `signingStatus` changes to `REJECTED` and `rejectionReason` cont
|
||||
"event": "DOCUMENT_REJECTED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "PENDING",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
@@ -561,7 +580,7 @@ The recipient's `signingStatus` changes to `REJECTED` and `rejectionReason` cont
|
||||
|
||||
### `document.cancelled`
|
||||
|
||||
Triggered when the document owner or a team member deletes a document. Draft and pending documents are hard-deleted, while completed documents are soft-deleted.
|
||||
Triggered when a pending document is explicitly cancelled with `POST /envelope/cancel`, or when a document owner or team member deletes a document. Deleting a draft or pending document hard-deletes it, while deleting a completed document soft-deletes it.
|
||||
|
||||
This event is **not** triggered when a recipient hides a document from their inbox.
|
||||
|
||||
@@ -572,6 +591,7 @@ This event is **not** triggered when a recipient hides a document from their inb
|
||||
"event": "DOCUMENT_CANCELLED",
|
||||
"payload": {
|
||||
"id": 7,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"externalId": null,
|
||||
"userId": 3,
|
||||
"authOptions": null,
|
||||
@@ -591,7 +611,6 @@ This event is **not** triggered when a recipient hides a document from their inb
|
||||
"subject": "",
|
||||
"message": "",
|
||||
"timezone": "Etc/UTC",
|
||||
"password": null,
|
||||
"dateFormat": "yyyy-MM-dd hh:mm a",
|
||||
"redirectUrl": "",
|
||||
"signingOrder": "PARALLEL",
|
||||
@@ -606,6 +625,7 @@ This event is **not** triggered when a recipient hides a document from their inb
|
||||
"recipients": [
|
||||
{
|
||||
"id": 7,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 7,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -627,6 +647,7 @@ This event is **not** triggered when a recipient hides a document from their inb
|
||||
"Recipient": [
|
||||
{
|
||||
"id": 7,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 7,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
@@ -651,6 +672,45 @@ This event is **not** triggered when a recipient hides a document from their inb
|
||||
}
|
||||
```
|
||||
|
||||
### `recipient.expired`
|
||||
|
||||
Triggered when a recipient's signing deadline passes on a pending document before they sign or reject it.
|
||||
|
||||
**Event name:** `RECIPIENT_EXPIRED`
|
||||
|
||||
The recipient's `expiresAt` contains the signing deadline, and `expirationNotifiedAt` is set when the expiration is processed.
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "RECIPIENT_EXPIRED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "PENDING",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
"expiresAt": "2024-04-22T11:51:00.000Z",
|
||||
"expirationNotifiedAt": "2024-04-22T11:52:00.000Z",
|
||||
"readStatus": "OPENED",
|
||||
"signingStatus": "NOT_SIGNED",
|
||||
"sendStatus": "SENT"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": "2024-04-22T11:52:00.000Z",
|
||||
"webhookEndpoint": "https://your-endpoint.com/webhook"
|
||||
}
|
||||
```
|
||||
|
||||
### `document.reminder.sent`
|
||||
|
||||
Triggered when a reminder email is sent to a recipient who has not yet completed their action.
|
||||
@@ -662,12 +722,14 @@ Triggered when a reminder email is sent to a recipient who has not yet completed
|
||||
"event": "DOCUMENT_REMINDER_SENT",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"status": "PENDING",
|
||||
"title": "contract.pdf",
|
||||
"source": "DOCUMENT",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 52,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "SIGNER",
|
||||
@@ -686,7 +748,7 @@ Triggered when a reminder email is sent to a recipient who has not yet completed
|
||||
|
||||
## Template Events
|
||||
|
||||
Template events track changes to reusable document templates. Template payloads use the same structure as document payloads, with `source` set to `TEMPLATE` and `templateId` populated.
|
||||
Template events track changes to reusable document templates. Template payloads use the same structure as document payloads. For `TEMPLATE_CREATED`, `TEMPLATE_UPDATED`, and `TEMPLATE_DELETED` the template's own legacy numeric ID is in `id` and `templateId` is `null`. Only `TEMPLATE_USED` — whose payload describes the new document envelope created from the template — carries the originating template's legacy ID in `templateId`, with `source` set to `TEMPLATE`.
|
||||
|
||||
### `template.created`
|
||||
|
||||
@@ -699,9 +761,10 @@ Triggered when a new template is created.
|
||||
"event": "TEMPLATE_CREATED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"title": "My Template",
|
||||
"status": "DRAFT",
|
||||
"templateId": 10,
|
||||
"templateId": null,
|
||||
"source": "TEMPLATE",
|
||||
"recipients": []
|
||||
},
|
||||
@@ -721,9 +784,10 @@ Triggered when a template's settings, recipients, or fields are modified.
|
||||
"event": "TEMPLATE_UPDATED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"title": "My Updated Template",
|
||||
"status": "DRAFT",
|
||||
"templateId": 10,
|
||||
"templateId": null,
|
||||
"source": "TEMPLATE",
|
||||
"recipients": []
|
||||
},
|
||||
@@ -743,9 +807,10 @@ Triggered when a template is deleted.
|
||||
"event": "TEMPLATE_DELETED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"title": "Deleted Template",
|
||||
"status": "DRAFT",
|
||||
"templateId": 10,
|
||||
"templateId": null,
|
||||
"source": "TEMPLATE",
|
||||
"recipients": []
|
||||
},
|
||||
@@ -765,6 +830,7 @@ Triggered when a document is created from a template. This event fires alongside
|
||||
"event": "TEMPLATE_USED",
|
||||
"payload": {
|
||||
"id": 10,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"title": "Document from Template",
|
||||
"status": "DRAFT",
|
||||
"templateId": 10,
|
||||
@@ -791,7 +857,8 @@ Triggered when a document is created from a template. This event fires alongside
|
||||
| `DOCUMENT_RECIPIENT_COMPLETED` | Recipient completes their action | Recipient `signingStatus: "SIGNED"`, `signedAt` set |
|
||||
| `DOCUMENT_COMPLETED` | All recipients complete actions | `status: "COMPLETED"`, `completedAt` set |
|
||||
| `DOCUMENT_REJECTED` | Recipient rejects document | Recipient `signingStatus: "REJECTED"`, `rejectionReason` set |
|
||||
| `DOCUMENT_CANCELLED` | Owner or team member deletes document | Document cancelled or deleted |
|
||||
| `DOCUMENT_CANCELLED` | Pending document explicitly cancelled, or document deleted | `status: "CANCELLED"` after explicit cancellation; deletion may remove or soft-delete the document |
|
||||
| `RECIPIENT_EXPIRED` | Recipient signing deadline passes | Recipient `expiresAt` passed, `expirationNotifiedAt` set |
|
||||
| `DOCUMENT_REMINDER_SENT` | Reminder email sent to recipient | No status changes |
|
||||
|
||||
### Template Events
|
||||
@@ -821,7 +888,7 @@ When processing webhook events:
|
||||
**Process idempotently** — Webhooks may be retried, so handle duplicate events
|
||||
</Step>
|
||||
<Step>
|
||||
**Respond quickly** — Return a 200 status code within 30 seconds
|
||||
**Respond quickly** — Return a `2xx` status code within 10 seconds
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ description: Receive real-time notifications for document and template events.
|
||||
2. When an event occurs, Documenso sends an HTTP POST to your URL
|
||||
3. Your application processes the event and responds with 200 OK
|
||||
|
||||
Documenso supports webhook events for the full document lifecycle (created, sent, opened, signed, completed, rejected, cancelled) as well as template events (created, updated, deleted, used).
|
||||
Documenso supports webhook events for the full document lifecycle (created, sent, opened, signed, completed, rejected, cancelled), recipient-level events (recipient completed, reminder sent, recipient expired), and template events (created, updated, deleted, used).
|
||||
|
||||
---
|
||||
|
||||
@@ -42,12 +42,14 @@ Documenso supports webhook events for the full document lifecycle (created, sent
|
||||
"event": "DOCUMENT_COMPLETED",
|
||||
"payload": {
|
||||
"id": 123,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"title": "Contract",
|
||||
"status": "COMPLETED",
|
||||
"completedAt": "2024-01-15T10:30:00.000Z",
|
||||
"recipients": [
|
||||
{
|
||||
"id": 1,
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"email": "signer@example.com",
|
||||
"signingStatus": "SIGNED"
|
||||
}
|
||||
@@ -58,6 +60,8 @@ Documenso supports webhook events for the full document lifecycle (created, sent
|
||||
}
|
||||
```
|
||||
|
||||
`payload.id` is the legacy numeric v1 ID. Use `payload.envelopeId` as the canonical v2 identifier. Each recipient repeats `envelopeId` as the reliable parent link because the legacy `documentId` and `templateId` fields depend on the parent envelope type, leaving one of them null.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
@@ -148,7 +148,7 @@ func main() {
|
||||
</Tabs>
|
||||
|
||||
<Callout type="warn">
|
||||
Always respond with a `200 OK` status within 30 seconds. Documenso will retry failed deliveries.
|
||||
Always respond with a `2xx` status within 10 seconds. Documenso will retry failed deliveries according to the configured background-job provider.
|
||||
</Callout>
|
||||
|
||||
## Configuring Webhooks in Documenso via the Dashboard
|
||||
@@ -184,7 +184,7 @@ Fill in the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ----- | ----------- |
|
||||
| **Webhook URL** | The HTTPS endpoint that will receive webhook events |
|
||||
| **Webhook URL** | The HTTP or HTTPS endpoint that will receive webhook events |
|
||||
| **Events** | Select which events should trigger this webhook |
|
||||
| **Secret** (optional) | A secret key used to sign the payload for verification |
|
||||
</Step>
|
||||
@@ -202,12 +202,21 @@ Your webhook endpoint must meet these requirements:
|
||||
|
||||
| Requirement | Details |
|
||||
| ----------- | ------- |
|
||||
| **Protocol** | HTTPS required (HTTP not allowed in production) |
|
||||
| **Response** | Must return `2xx` status code within 30 seconds |
|
||||
| **Protocol** | HTTP and HTTPS are accepted; use HTTPS in production |
|
||||
| **Response** | Must return a `2xx` status code within 10 seconds |
|
||||
| **Method** | Must accept HTTP POST requests |
|
||||
| **Content-Type** | Must accept `application/json` payloads |
|
||||
| **Availability** | Must be publicly accessible from the internet |
|
||||
|
||||
<Callout type="warn">
|
||||
Documenso performs a best-effort check that rejects webhook URLs which use or resolve to private
|
||||
or loopback addresses. This is not a complete SSRF mitigation — it does not cover DNS rebinding
|
||||
and fails open on DNS lookup errors or timeouts — so self-hosted deployments should still enforce
|
||||
network-level egress rules. Self-hosters that need to deliver to a hostname resolving to a
|
||||
private address can add that hostname to the comma-separated
|
||||
`NEXT_PRIVATE_WEBHOOK_SSRF_BYPASS_HOSTS` environment variable.
|
||||
</Callout>
|
||||
|
||||
<Callout type="info">
|
||||
For local development, use a tunneling service like [ngrok](https://ngrok.com) or [localtunnel](https://localtunnel.me) to expose your local server.
|
||||
</Callout>
|
||||
@@ -225,7 +234,8 @@ When creating a webhook, you can subscribe to one or more events:
|
||||
| `DOCUMENT_RECIPIENT_COMPLETED` | A recipient completes their required action |
|
||||
| `DOCUMENT_COMPLETED` | All recipients have completed their actions |
|
||||
| `DOCUMENT_REJECTED` | A recipient rejects the document |
|
||||
| `DOCUMENT_CANCELLED` | The document owner deletes the document |
|
||||
| `DOCUMENT_CANCELLED` | A pending document is explicitly cancelled or a document owner deletes it |
|
||||
| `RECIPIENT_EXPIRED` | A recipient's signing deadline passes before they sign or reject |
|
||||
| `DOCUMENT_REMINDER_SENT` | A reminder email is sent to a recipient |
|
||||
| `TEMPLATE_CREATED` | A new template is created |
|
||||
| `TEMPLATE_UPDATED` | A template is modified |
|
||||
@@ -294,6 +304,7 @@ Each webhook call shows the following details:
|
||||
- Timestamp
|
||||
- Response code
|
||||
- Request and response bodies
|
||||
- Response headers
|
||||
|
||||
Click any call to see full details including headers and response data.
|
||||
</Step>
|
||||
@@ -318,17 +329,17 @@ Documenso will attempt to deliver the same payload again
|
||||
|
||||
## Retry Policy
|
||||
|
||||
When a webhook delivery fails (non-2xx response or timeout), Documenso automatically retries with exponential backoff:
|
||||
A delivery fails when the endpoint returns a non-`2xx` response, the 10-second timeout expires, or the request fails. Redirects are not followed, so `3xx` responses also fail. Network and SSRF-blocked requests are recorded with response code `0`.
|
||||
|
||||
| Attempt | Delay |
|
||||
| ------- | ----- |
|
||||
| 1 | Immediate |
|
||||
| 2 | 1 minute |
|
||||
| 3 | 5 minutes |
|
||||
| 4 | 30 minutes |
|
||||
| 5 | 2 hours |
|
||||
For self-hosted deployments, retries are handled by the background-job provider selected with `NEXT_PRIVATE_JOBS_PROVIDER`:
|
||||
|
||||
After 5 failed attempts, the webhook is marked as failed and no further automatic retries occur. You can manually resend failed webhooks from the dashboard.
|
||||
| Provider | Total attempts | Retry timing |
|
||||
| -------- | -------------- | ------------ |
|
||||
| Local (default) | 4 | Back-to-back, with no backoff |
|
||||
| BullMQ | 3 | Exponential backoff starting at 1 second |
|
||||
| Inngest | 5 | Inngest platform backoff |
|
||||
|
||||
Only the individual delivery (`WebhookCall`) record is marked as failed. Documenso does not automatically disable the webhook or apply a circuit breaker, so future matching events continue to be delivered. After automatic attempts are exhausted, you can manually resend a failed delivery from the dashboard.
|
||||
|
||||
<Callout type="warn">
|
||||
If your endpoint consistently fails, consider reviewing your server logs and ensuring your endpoint meets all [URL requirements](#webhook-url-requirements).
|
||||
|
||||
@@ -255,6 +255,7 @@ const validEvents = [
|
||||
'DOCUMENT_REJECTED',
|
||||
'DOCUMENT_CANCELLED',
|
||||
'DOCUMENT_REMINDER_SENT',
|
||||
'RECIPIENT_EXPIRED',
|
||||
'TEMPLATE_CREATED',
|
||||
'TEMPLATE_UPDATED',
|
||||
'TEMPLATE_DELETED',
|
||||
|
||||
@@ -41,12 +41,17 @@ When a limit is reached, requests return a `429 Too Many Requests` response with
|
||||
|
||||
| Action | Limit | Window |
|
||||
| --- | --- | --- |
|
||||
| API requests (v1 and v2) | 100 requests | 1 minute |
|
||||
| API requests (v1 and v2) | 1000 requests | 1 minute |
|
||||
| File uploads | 20 requests | 1 minute |
|
||||
| AI features | 3 requests | 1 minute |
|
||||
|
||||
Authentication endpoints (login, signup, password reset, etc.) are also rate-limited to protect against abuse.
|
||||
|
||||
<Callout type="info">
|
||||
The API request limit above is the global per-IP ceiling. Individual organisations also have their
|
||||
own rate limits, which may be configured below this value.
|
||||
</Callout>
|
||||
|
||||
<Callout type="info">
|
||||
Rate limits may vary by plan. Enterprise plans can include higher or custom limits. Contact
|
||||
[sales](https://documen.so/sales) for details.
|
||||
|
||||
@@ -13,7 +13,7 @@ There are three distinct kinds of limit:
|
||||
| ---------------------- | ------------------------------------------------- | ----------------------- |
|
||||
| Resource quota | Documents, emails, and API requests **per month** | Yes — per claim and org |
|
||||
| Resource rate limit | The same resources over a short window (e.g. `1h`) | Yes — per claim and org |
|
||||
| Global HTTP rate limit | API requests per IP (100/min, hardcoded) | No — see [Limitations](#limitations) |
|
||||
| Global HTTP rate limit | API requests per IP (1000/min, hardcoded) | No — see [Limitations](#limitations) |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -91,7 +91,7 @@ Monthly quota usage is keyed to the **UTC calendar month**. There is no schedule
|
||||
|
||||
## Limitations
|
||||
|
||||
The **global HTTP rate limit is not configurable.** Documenso enforces a hardcoded **100 requests per minute per IP address** on its API endpoint groups (`/api/v1`, `/api/v2`, and the tRPC API are limited separately), returning `429 Too Many Requests`. It is a per-IP safeguard applied at the HTTP layer — not per-organisation, not stored on any claim, and not adjustable from the admin panel. See [Rate Limits](/docs/developers/api/rate-limits).
|
||||
The **global HTTP rate limit is not configurable.** Documenso enforces a hardcoded **1000 requests per minute per IP address** on its API endpoint groups (`/api/v1`, `/api/v2`, and the tRPC API are limited separately), returning `429 Too Many Requests`. It is a per-IP safeguard applied at the HTTP layer — not per-organisation, not stored on any claim, and not adjustable from the admin panel. See [Rate Limits](/docs/developers/api/rate-limits).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ services:
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?err}
|
||||
- POSTGRES_DB=${POSTGRES_DB:?err}
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER}']
|
||||
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "NEXT_IGNORE_INCORRECT_LOCKFILE=true next build",
|
||||
"build": "next build",
|
||||
"dev": "next dev",
|
||||
"start": "next start",
|
||||
"types:check": "fumadocs-mdx && next typegen && tsc --noEmit",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"fumadocs-core": "16.5.0",
|
||||
"fumadocs-mdx": "14.2.6",
|
||||
"fumadocs-ui": "16.5.0",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
const MIGRATION_GUIDE_HREF = '/docs/developers/api/migrate-to-envelopes';
|
||||
|
||||
/**
|
||||
* Deprecation banner steering API consumers away from the legacy document and
|
||||
* template create endpoints and towards the unified Envelope API.
|
||||
*
|
||||
* Registered globally in `mdx-components.tsx`, so it can be used in any MDX page
|
||||
* as `<EnvelopeWarning />` without an explicit import.
|
||||
*/
|
||||
export function EnvelopeWarning() {
|
||||
return (
|
||||
<Callout type="error">
|
||||
<strong>Documents and templates are being deprecated and replaced by envelopes.</strong>{' '}
|
||||
<a href={MIGRATION_GUIDE_HREF}>Read the migration guide here.</a>
|
||||
</Callout>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as TabsComponents from 'fumadocs-ui/components/tabs';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
import type { MDXComponents } from 'mdx/types';
|
||||
import { EnvelopeWarning } from '@/components/mdx/envelope-warning';
|
||||
import { Mermaid } from '@/components/mdx/mermaid';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -9,6 +10,7 @@ export function getMDXComponents(components?: MDXComponents): any {
|
||||
...defaultMdxComponents,
|
||||
...TabsComponents,
|
||||
Mermaid,
|
||||
EnvelopeWarning,
|
||||
...components,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user