Skip to main content

Rate limits

The DocGen API enforces per-plan throughput limits to keep generation latency predictable for every customer on the platform. Limits apply to the org that owns the API credentials, aggregated across all clients using those credentials.

This page documents the DocGen-specific limits. For the platform-wide request-rate policy that applies to all Propper APIs, see the global rate limits guide.

Per-plan limits

PlanDocuments/hrBurst/minNotes
gen_starter601SMB tier
gen_pro60010Mid-market
gen_hoa60010Burst weighted toward bulk_send
business1,20020Existing full-suite plan
gen_payg6,000100Metered Pay-As-You-Go

A "document" is one successful generation that produces a stored artifact. Failed generations that return a 4xx before any rendering work begins do not count against the hourly budget. Failures that occur after a render starts (template errors, asset fetch failures) do count, because they consume worker capacity.

The burst-per-minute column caps short-window throughput so that a single client cannot drain the hourly budget in seconds and starve other consumers. Hitting the burst cap returns a 429 with a short retryAfterSeconds even when the hourly budget is not exhausted.

429 response shape

When a request is throttled the API returns HTTP 429 Too Many Requests with the following JSON body:

{
"code": "rate_limited",
"message": "Rate limit exceeded for plan gen_starter.",
"details": {
"plan": "gen_starter",
"limit": 60,
"windowSeconds": 3600,
"retryAfterSeconds": 287
}
}

Every 429 response also carries these headers:

HeaderDescription
Retry-AfterSeconds to wait before the next request. Mirrors details.retryAfterSeconds.
X-RateLimit-LimitMaximum documents allowed in the current window.
X-RateLimit-RemainingDocuments remaining in the current window. Will be 0 on a 429.
X-RateLimit-ResetUnix timestamp (seconds) at which the current window resets and the full budget becomes usable.

These headers are also returned on successful (2xx) responses so a well-behaved client can pace itself without ever hitting a 429.

Backoff guidance

When a 429 is returned, use exponential backoff seeded from details.retryAfterSeconds:

  1. Wait retryAfterSeconds before the first retry.
  2. Double the wait on each subsequent retry: retryAfterSeconds * 2^attempt.
  3. Apply ±10% jitter to each wait to avoid synchronized retries across workers.
  4. Cap at 5 retries. After the fifth failure, surface the error to the caller rather than continuing to retry.
async function generateWithBackoff(request: () => Promise<Response>) {
const maxRetries = 5;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await request();
if (response.status !== 429) {
return response;
}
const retryAfter = Number(response.headers.get('Retry-After') ?? '1');
const base = retryAfter * Math.pow(2, attempt);
const jitter = base * (0.9 + Math.random() * 0.2);
await new Promise((resolve) => setTimeout(resolve, jitter * 1000));
}
throw new Error('Rate limit retries exhausted');
}
tip

Batch endpoints (POST /batches) consume a single hourly slot per batch on submission, even though the batch may produce hundreds of documents. Prefer batching for any flow that generates more than ~10 documents at once. See the batch guide for examples.

Requesting a limit increase

If your usage pattern outgrows the limits for your current plan, you have two options:

  1. Self-serve upgrade. Org admins can compare plans and upgrade in the dashboard at https://app.propper.ai/organization/settings/billing. New limits take effect within a minute of the upgrade webhook completing.
  2. Custom limits. For sustained throughput above the gen_payg row, contact your account team or reach out through the support channel listed in your contract. Custom limits are provisioned per-org and do not require a plan change.

Limit increases are not granted as a workaround for a misbehaving integration. If you are hitting limits because of a tight retry loop or polling-instead-of-webhooks pattern, the support team will surface that before changing the cap.