mirror of
https://github.com/documenso/documenso.git
synced 2026-08-20 05:21:51 +10:00
## Description
The rate limits page claimed "No rate limit headers are currently
provided" and advised a fixed 60-second wait. The middleware has been
setting standard headers on every API response.
## Changes Made
- Documented `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and
`X-RateLimit-Reset` (Unix epoch seconds) on every `/api/v1`, `/api/v2`,
and `/api/v2-beta` response, and `Retry-After` (seconds, min 1) on 429s.
- Explained that windows are fixed epoch-aligned 1-minute buckets, so
the real wait is 1–60s — clients should honor `Retry-After` instead of
sleeping a fixed 60s.
- Showed both 429 body shapes: the global per-IP limiter's `{ "error":
... }` vs AppError-based `code`/`message`/`statusCode`.
- Covered the three distinct 429 sources: global per-IP limit,
organisation windowed limits, and monthly envelope quota (which sends no
rate-limit headers).
- Added `/api/v2-beta/*` to the documented scope; left the
verified-correct 1000/min figure and plan-limits table untouched.
## Testing Performed
Docs-only change. Verified against `rate-limit-middleware.ts`,
`rate-limit.ts`, `check-organisation-rate-limits.ts`,
`check-monthly-quota.ts`, and the remix server router.
123 lines
4.8 KiB
Plaintext
123 lines
4.8 KiB
Plaintext
---
|
|
title: Rate Limits
|
|
description: Learn about the rate limits for the Documenso Public API.
|
|
---
|
|
|
|
import { Callout } from 'fumadocs-ui/components/callout';
|
|
|
|
## Overview
|
|
|
|
Documenso enforces rate limits on all API endpoints to ensure service stability.
|
|
|
|
## HTTP Rate Limits
|
|
|
|
The rate limit applies to:
|
|
|
|
- `/api/v1/*`
|
|
- `/api/v2/*`
|
|
- `/api/v2-beta/*`
|
|
|
|
**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>
|
|
|
|
### Global per-IP 429 Response
|
|
|
|
```json
|
|
{
|
|
"error": "Too many requests, please try again later."
|
|
}
|
|
```
|
|
|
|
### Rate Limit Headers
|
|
|
|
Responses from `/api/v1/*`, `/api/v2/*`, and `/api/v2-beta/*` include these headers. The only
|
|
exception is CORS preflight (`OPTIONS`) requests, which are answered before the rate limiter runs
|
|
and carry no rate limit headers:
|
|
|
|
| Header | Description |
|
|
| ----------------------- | ---------------------------------------------------------------------- |
|
|
| `X-RateLimit-Limit` | Maximum requests allowed in the current global window |
|
|
| `X-RateLimit-Remaining` | Requests remaining in the current global window |
|
|
| `X-RateLimit-Reset` | End of the current global window, as a Unix epoch timestamp in seconds |
|
|
|
|
A 429 response from a windowed limiter also includes `Retry-After`, in seconds, with a minimum
|
|
value of `1`. The global API limit uses fixed, epoch-aligned one-minute buckets, so the actual wait
|
|
until the next window is between 1 and 60 seconds. Honor `Retry-After` exactly instead of sleeping
|
|
for a fixed 60 seconds. See the [Retry-After handling example](/docs/developers/examples/common-workflows#error-handling-patterns).
|
|
|
|
## Resource Limits
|
|
|
|
Beyond HTTP rate limits, your account has usage limits based on your subscription plan.
|
|
|
|
### Plan Limits
|
|
|
|
| Resource | Free | Paid | Self-hosted | Enterprise |
|
|
| ---------------- | ---- | --------- | ----------- | ---------- |
|
|
| Documents/month | 5 | Unlimited | Unlimited | Unlimited |
|
|
| Total Recipients | 10 | Unlimited | Unlimited | Unlimited |
|
|
| Direct Templates | 3 | Unlimited | Unlimited | Unlimited |
|
|
|
|
### Organisation Limit 429 Responses
|
|
|
|
Organisation windowed limits and organisation monthly quotas produce 429 responses whose body
|
|
shape depends on the API version, and neither matches the global per-IP limiter's
|
|
`{ "error": "..." }` body.
|
|
|
|
On `/api/v1/*`, the body contains only a message:
|
|
|
|
```json
|
|
{
|
|
"message": "Too many requests, please try again later. Contact support if you require higher limits."
|
|
}
|
|
```
|
|
|
|
On `/api/v2/*` and `/api/v2-beta/*`, the body is a structured error object:
|
|
|
|
```json
|
|
{
|
|
"message": "Too many requests, please try again later. Contact support if you require higher limits.",
|
|
"code": "TOO_MANY_REQUESTS",
|
|
"data": {
|
|
"code": "TOO_MANY_REQUESTS",
|
|
"httpStatus": 429,
|
|
"appError": {
|
|
"code": "TOO_MANY_REQUESTS",
|
|
"message": "Too many requests, please try again later. Contact support if you require higher limits."
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Organisation windowed limit responses include the `X-RateLimit-*` headers and `Retry-After` for
|
|
their own window. Monthly quota responses carry no quota-specific rate limit headers or
|
|
`Retry-After` because the quota is not a time window; rely on the status code and message instead.
|
|
|
|
## Error Codes
|
|
|
|
| Code | Status | Description |
|
|
| ------------------- | ------ | ------------------------------------------------------------------ |
|
|
| `TOO_MANY_REQUESTS` | 429 | Global per-IP, organisation windowed, or monthly quota exceeded |
|
|
| `LIMIT_EXCEEDED` | 400 | Resource usage limit exceeded |
|
|
|
|
There are three sources of `TOO_MANY_REQUESTS` responses:
|
|
|
|
1. The global per-IP limit, returning the `{ "error": "..." }` body shown above.
|
|
2. Organisation windowed rate limits for the `api`, `document`, and `email` counters.
|
|
3. Organisation monthly quotas for the same three counters. Every authenticated API request
|
|
consumes the `api` counter, so any endpoint can return this 429 once the monthly API quota is
|
|
exhausted — not just envelope-related ones.
|
|
|
|
---
|
|
|
|
## See Also
|
|
|
|
- [Authentication](/docs/developers/getting-started/authentication) - API authentication guide
|
|
- [API Versioning](/docs/developers/api/versioning) - API version management
|
|
- [First API Call](/docs/developers/getting-started/first-api-call) - Getting started with the API
|
|
- [Organisation Limits](/docs/self-hosting/configuration/organisation-limits) - Admins: set per-organisation resource quotas and rate limits (the HTTP rate limit above is separate and not admin-settable)
|