mirror of
https://github.com/documenso/documenso.git
synced 2026-08-26 00:02:43 +10:00
fix(docs): stop requests after quota errors
This commit is contained in:
@@ -28,35 +28,62 @@ Each document contains one or more PDF files, a list of recipients, and the fiel
|
||||
|
||||
A document object contains the following properties:
|
||||
|
||||
| Property | Type | Description |
|
||||
| --------------- | -------------- | -------------------------------------------------------------- |
|
||||
| `id` | string | Unique identifier (e.g., `envelope_abc123`) |
|
||||
| `type` | string | `DOCUMENT` or `TEMPLATE` |
|
||||
| `status` | string | Current status: `DRAFT`, `PENDING`, `COMPLETED`, `REJECTED`, or `CANCELLED` |
|
||||
| `title` | string | Document title |
|
||||
| `source` | string | How the document was created: `DOCUMENT`, `TEMPLATE`, `TEMPLATE_DIRECT_LINK` |
|
||||
| `visibility` | string | Who can view: `EVERYONE`, `ADMIN`, `MANAGER_AND_ABOVE` |
|
||||
| `externalId` | string \| null | Your custom identifier for the document |
|
||||
| `createdAt` | string | ISO 8601 timestamp |
|
||||
| `updatedAt` | string | ISO 8601 timestamp |
|
||||
| `completedAt` | string \| null | Timestamp when all recipients completed signing |
|
||||
| `deletedAt` | string \| null | Timestamp if soft-deleted |
|
||||
| `recipients` | array | List of recipients and their signing status |
|
||||
| `fields` | array | Signature and form fields on the document |
|
||||
| `envelopeItems` | array | PDF files attached to the document |
|
||||
| `documentMeta` | object | Email settings, redirect URL, signing options |
|
||||
| Property | Type | Description |
|
||||
| ------------------- | -------------- | -------------------------------------------------------------------------------------------- |
|
||||
| `id` | string | Unique identifier (e.g., `envelope_abc123`) |
|
||||
| `secondaryId` | string | Legacy identifier in prefixed form (`document_123` for documents, `template_123` for templates) |
|
||||
| `internalVersion` | number | Internal envelope schema version |
|
||||
| `type` | string | `DOCUMENT` or `TEMPLATE` |
|
||||
| `status` | string | Current status: `DRAFT`, `PENDING`, `COMPLETED`, `REJECTED`, or `CANCELLED` |
|
||||
| `title` | string | Document title |
|
||||
| `source` | string | How the document was created: `DOCUMENT`, `TEMPLATE`, `TEMPLATE_DIRECT_LINK` |
|
||||
| `visibility` | string | Who can view: `EVERYONE`, `ADMIN`, `MANAGER_AND_ABOVE` |
|
||||
| `templateType` | string | Template visibility: `PUBLIC`, `PRIVATE`, or `ORGANISATION` (only meaningful for templates) |
|
||||
| `externalId` | string \| null | Your custom identifier for the document |
|
||||
| `userId` | number | ID of the user who owns the document |
|
||||
| `teamId` | number | ID of the team the document belongs to |
|
||||
| `folderId` | string \| null | ID of the folder containing the document |
|
||||
| `templateId` | number \| null | Legacy ID of the template this document was created from |
|
||||
| `authOptions` | object \| null | Access and action authentication requirements |
|
||||
| `formValues` | object \| null | Pre-filled form values |
|
||||
| `publicTitle` | string | Public title shown on profile and direct-link pages |
|
||||
| `publicDescription` | string | Public description shown on profile and direct-link pages |
|
||||
| `createdAt` | string | ISO 8601 timestamp |
|
||||
| `updatedAt` | string | ISO 8601 timestamp |
|
||||
| `completedAt` | string \| null | Timestamp when all recipients completed signing |
|
||||
| `deletedAt` | string \| null | Timestamp if soft-deleted |
|
||||
| `recipients` | array | List of recipients and their signing status |
|
||||
| `fields` | array | Signature and form fields on the document |
|
||||
| `envelopeItems` | array | PDF files attached to the document |
|
||||
| `directLink` | object \| null | Direct-link signing configuration (`id`, `token`, `enabled`, `directTemplateRecipientId`) |
|
||||
| `team` | object | Owning team (`id`, `url`) |
|
||||
| `user` | object | Document owner (`id`, `name`, `email`) |
|
||||
| `documentMeta` | object | Email settings, redirect URL, signing options |
|
||||
|
||||
Documents created through the API have `source: "DOCUMENT"` — there is no separate `API` source value. To tag documents created by your integration, set `externalId` when creating them.
|
||||
|
||||
### Example Document Object
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "envelope_abc123xyz",
|
||||
"secondaryId": "document_123",
|
||||
"internalVersion": 2,
|
||||
"type": "DOCUMENT",
|
||||
"status": "PENDING",
|
||||
"source": "DOCUMENT",
|
||||
"visibility": "EVERYONE",
|
||||
"templateType": "PRIVATE",
|
||||
"title": "Service Agreement",
|
||||
"externalId": "contract-2025-001",
|
||||
"userId": 1,
|
||||
"teamId": 1,
|
||||
"folderId": null,
|
||||
"templateId": null,
|
||||
"authOptions": null,
|
||||
"formValues": null,
|
||||
"publicTitle": "",
|
||||
"publicDescription": "",
|
||||
"createdAt": "2025-01-15T10:30:00.000Z",
|
||||
"updatedAt": "2025-01-15T10:35:00.000Z",
|
||||
"completedAt": null,
|
||||
@@ -74,22 +101,40 @@ A document object contains the following properties:
|
||||
"fields": [
|
||||
{
|
||||
"id": 123,
|
||||
"secondaryId": "field_abc123",
|
||||
"type": "SIGNATURE",
|
||||
"recipientId": 1,
|
||||
"envelopeId": "envelope_abc123xyz",
|
||||
"envelopeItemId": "envelope_item_xyz",
|
||||
"page": 1,
|
||||
"positionX": "10",
|
||||
"positionY": "80",
|
||||
"width": "30",
|
||||
"height": "5",
|
||||
"recipientId": 1
|
||||
"customText": "",
|
||||
"inserted": false,
|
||||
"fieldMeta": null
|
||||
}
|
||||
],
|
||||
"envelopeItems": [
|
||||
{
|
||||
"id": "envelope_item_xyz",
|
||||
"envelopeId": "envelope_abc123xyz",
|
||||
"documentDataId": "doc_data_abc123",
|
||||
"title": "contract.pdf",
|
||||
"order": 1
|
||||
}
|
||||
],
|
||||
"directLink": null,
|
||||
"team": {
|
||||
"id": 1,
|
||||
"url": "your-team"
|
||||
},
|
||||
"user": {
|
||||
"id": 1,
|
||||
"name": "Jane Smith",
|
||||
"email": "jane@example.com"
|
||||
},
|
||||
"documentMeta": {
|
||||
"subject": "Please sign this document",
|
||||
"message": "Hi, please review and sign this agreement.",
|
||||
|
||||
@@ -6,6 +6,8 @@ description: Add signature and form fields to documents via API.
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
<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).
|
||||
@@ -62,7 +64,7 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
| Type | Description | Auto-filled |
|
||||
| ---------------- | ----------------------------------------- | ----------- |
|
||||
| `SIGNATURE` | Drawn, typed, or uploaded signature | No |
|
||||
| `FREE_SIGNATURE` | Unrestricted signature without validation | No |
|
||||
| `FREE_SIGNATURE` | Legacy free-form signature. Accepted by the v2 create schema but rejected by the v1 API and unsupported in the signing UI — avoid in new integrations | No |
|
||||
| `INITIALS` | Recipient's initials | No |
|
||||
| `NAME` | Recipient's full name | Yes |
|
||||
| `EMAIL` | Recipient's email address | Yes |
|
||||
@@ -140,6 +142,8 @@ POST /envelope/field/create-many
|
||||
| `envelopeId` | string | Yes | The envelope ID |
|
||||
| `data` | array | Yes | Array of field configurations |
|
||||
|
||||
Each entry in `data` requires a `type`, a `recipientId`, and a position — either explicit coordinates (`page`, `positionX`, `positionY`, `width`, `height`) or a [text placeholder](#placeholder-based-field-positioning) (`placeholder` with optional `width`, `height`, and `matchAll`). Optional per-entry properties: `envelopeItemId` (which PDF in the envelope to place the field on; defaults to the first item) and `fieldMeta`.
|
||||
|
||||
### Code Examples
|
||||
|
||||
<Tabs items={['curl', 'TypeScript']}>
|
||||
@@ -335,6 +339,8 @@ POST /envelope/field/update-many
|
||||
| `envelopeId` | string | Yes | The envelope ID |
|
||||
| `data` | array | Yes | Array of field update objects |
|
||||
|
||||
Each entry in `data` requires the field `id` and `type`. Position properties (`page`, `positionX`, `positionY`, `width`, `height`), `envelopeItemId`, and `fieldMeta` are optional — only supplied values are updated. Placeholder positioning is not supported when updating; use coordinates.
|
||||
|
||||
### Code Examples
|
||||
|
||||
<Tabs items={['curl', 'TypeScript']}>
|
||||
@@ -551,6 +557,33 @@ This approach is useful when generating PDFs programmatically or using templates
|
||||
|
||||
See the [PDF Placeholders](/docs/users/documents/advanced/pdf-placeholders) guide for the full placeholder format reference, including supported field types, recipient identifiers, and field options.
|
||||
|
||||
### Placeholder Positioning via the API
|
||||
|
||||
`POST /envelope/field/create-many` accepts a placeholder position in place of coordinates. Instead of `page`, `positionX`, `positionY`, `width`, and `height`, pass:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `placeholder` | string | Yes | Text to search for in the PDF (e.g. `{{name}}`). The field is placed at the bounding box of the first match. |
|
||||
| `width` | number | No | Override the field width. Defaults to the width of the matched text. |
|
||||
| `height` | number | No | Override the field height. Defaults to the height of the matched text. |
|
||||
| `matchAll` | boolean | No | Create a field at every occurrence of the placeholder instead of only the first. |
|
||||
|
||||
```json
|
||||
{
|
||||
"envelopeId": "envelope_abcdefhiklmnorst",
|
||||
"data": [
|
||||
{
|
||||
"type": "SIGNATURE",
|
||||
"recipientId": 456,
|
||||
"placeholder": "{{signature}}",
|
||||
"matchAll": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`POST /envelope/field/update-many` does not accept placeholders — field updates are coordinate-only.
|
||||
|
||||
---
|
||||
|
||||
## Field Meta Options
|
||||
|
||||
@@ -441,7 +441,7 @@ The API returns standard HTTP status codes and JSON error responses:
|
||||
| `400` | Bad request - check your request payload |
|
||||
| `401` | Unauthorized - invalid or missing API token |
|
||||
| `404` | Not found - resource doesn't exist |
|
||||
| `429` | Rate limited - wait for the duration in the `Retry-After` header |
|
||||
| `429` | Rate limit or plan quota. If `Retry-After` is present, retry the request. |
|
||||
| `500` | Server error - retry or contact support |
|
||||
|
||||
### Error Response Format
|
||||
@@ -485,7 +485,9 @@ The API returns standard HTTP status codes and JSON error responses:
|
||||
|
||||
### Handling Rate Limits
|
||||
|
||||
The API allows 1000 requests per minute per IP address. Your organisation may have its own lower rate limits. Every response includes `X-RateLimit-Remaining` and `X-RateLimit-Reset` (an epoch timestamp in seconds). When you receive a `429` response, read the `Retry-After` header and wait for that many seconds before retrying. See [Error Handling Patterns](/docs/developers/examples/common-workflows#error-handling-patterns) for a more complete retry strategy.
|
||||
The API has a limit of 1000 requests per minute for each IP address, and your organisation can have a lower limit. Each response includes `X-RateLimit-Remaining` and `X-RateLimit-Reset` (an epoch timestamp in seconds). A windowed rate-limit `429` response includes `Retry-After`. Wait for that number of seconds before you send the request again. A quota `429` response does not include `Retry-After` because a wait cannot correct the quota error. If `Retry-After` is not present, do not send the request again automatically.
|
||||
|
||||
Refer to [Error Handling Patterns](/docs/developers/examples/common-workflows#error-handling-patterns) for more retry information.
|
||||
|
||||
```javascript
|
||||
async function fetchWithRetry(url, options, maxRetries = 3) {
|
||||
@@ -493,8 +495,14 @@ async function fetchWithRetry(url, options, maxRetries = 3) {
|
||||
const response = await fetch(url, options);
|
||||
|
||||
if (response.status === 429) {
|
||||
const retryAfterSeconds = Number.parseInt(response.headers.get('Retry-After') ?? '1', 10);
|
||||
console.log(`Rate limited, waiting ${retryAfterSeconds} seconds...`);
|
||||
const retryAfter = response.headers.get('Retry-After');
|
||||
|
||||
if (!retryAfter) {
|
||||
return response;
|
||||
}
|
||||
|
||||
const retryAfterSeconds = Number.parseInt(retryAfter, 10);
|
||||
console.log(`Rate limit. Wait ${retryAfterSeconds} seconds...`);
|
||||
await new Promise((resolve) => setTimeout(resolve, retryAfterSeconds * 1000));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -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).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -304,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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
"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",
|
||||
"fumadocs-core": "16.14.3",
|
||||
"fumadocs-mdx": "15.2.3",
|
||||
"fumadocs-ui": "16.14.3",
|
||||
"lucide-react": "^0.563.0",
|
||||
"mermaid": "^11.12.2",
|
||||
"next": "16.2.6",
|
||||
"next": "16.3.0",
|
||||
"next-plausible": "^3.12.5",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^19.2.4",
|
||||
|
||||
Reference in New Issue
Block a user