Rate Limits & Quotas
To guarantee service availability, API requests are subject to rate limiting and quotas based on your plan level.
Limits by Plan
| Plan | Monthly Quota (PDFs) | Monthly Generated Volume | Max File Size | Requests / Minute (RPM) | Concurrent Jobs |
|---|---|---|---|---|---|
| Free | 100 | 0.5 GB | 150 MB | 10 | 3 |
| Starter | 5,000 | 10 GB | 150 MB | 100 | 15 |
| Pro | 50,000 | 50 GB | 150 MB | 500 | 50 |
| Business | 500,000 | 300 GB | 150 MB | 2,000 | 150 |
- Monthly Generated Volume counts the bytes of the PDFs you generate in a billing
window; downloading a file never debits it. Exceeding the volume quota returns
429quota-bytes-exceeded. Business accounts can purchase additional +1 GB/month blocks from the Billing page; for larger needs contact [email protected]. - Max File Size applies to a single rendered PDF. A render that exceeds it fails with the job error file-too-large. If you need larger files, contact [email protected] — the limit can be raised per account.
- Rate limits and concurrency are aggregated per account across all API keys — creating more keys does not multiply the limit.
- Test mode (
"test": true) is free — it debits neither quota — and instead has its own per-account caps: 60 test calls/minute and 2,000/day. Exceeding them returns429test-rate-limit-exceeded. See Testing.
File Retention & Downloads
| Rule | Value |
|---|---|
| Retention | Each generated PDF is available for download for 24 hours after generation; files are physically deleted within 48 hours. |
expires_at | The exact expiry timestamp (ISO-8601, finished_at + 24 h) is returned in GET /jobs/{id} and in the webhook payload; null until the job finishes. |
| After expiry | The download endpoint returns 410 file-expired. Re-render to get a new file. |
| Download attempts | Maximum 3 per file, counted when the stream starts (an interrupted download consumes an attempt). Exhausted → 429 download-attempts-exhausted. |
| Concurrent streams | Maximum 1 active download stream per file. A concurrent duplicate is rejected with 429 download-busy without consuming an attempt — the lock doubles as request deduplication. |
Download and persist the PDF on your side as soon as the job finishes — PDFik storage is a delivery buffer, not an archive.
Rate Limit Headers
Every response from the PDFik API contains headers showing your rate limit status:
X-RateLimit-Limit: Maximum requests allowed per minute.X-RateLimit-Remaining: Number of requests remaining for the current window.X-RateLimit-Reset: Epoch UNIX timestamp when the current rate limit window resets.Retry-After: (Only on 429 errors) Minimum seconds to wait before retrying.
Handling Rate Limits
When you exceed the limit, the API returns an HTTP 429 Too Many Requests error. We recommend implementing a retry mechanism with Exponential Backoff and Jitter.
Python Exponential Backoff Example
import time
import random
import requests
def request_with_retry(url, headers, json_data, max_retries=5):
for attempt in range(max_retries):
response = requests.post(url, headers=headers, json=json_data)
if response.status_code == 429:
# Respect Retry-After header if present, otherwise calculate backoff
retry_after = response.headers.get("Retry-After")
if retry_after:
delay = int(retry_after)
else:
delay = (2 ** attempt) + random.uniform(0, 1)
print(f"Rate limited (429). Retrying in {delay:.2f} seconds...")
time.sleep(delay)
continue
return response
raise Exception("Max retries exceeded.")
Monthly Quota Calculation & Billing Periods
Your monthly PDF quota (Monthly Quota (PDFs)) is calculated dynamically based on your subscription's anchor date (current_period_start), ensuring exact alignment with your billing cycle regardless of whether you are billed monthly or annually.
1. Anchor-Date Windows
Instead of resetting on the 1st of every calendar month, quota windows run from the exact day and time your subscription started (e.g., if your subscription begins on August 17th at 14:30 UTC, your quota resets on the 17th of each subsequent month at 14:30 UTC).
2. End-of-Month & February Clamping (Short Month Handling)
If your subscription begins on the 29th, 30th, or 31st of a month, subsequent monthly quota windows automatically clamp to the last valid day of shorter months without shifting your permanent billing anchor:
- February Clamping: If your anchor date is December 29th, 30th, or 31st, your quota window for February will reset on February 28th (or February 29th during leap years).
- 30-Day Months: For subscriptions starting on the 31st (such as January 31st), the window for April, June, September, and November resets on the 30th of those respective months.
3. Annual Subscriptions
For annual plans (Starter Annual, Pro Annual, Business Annual), your monthly quota resets every month exactly on your monthly anchor date (current_period_start synced via Stripe webhooks). Each month of your 12-month annual plan grants the full monthly allocation (5,000, 50,000, or 500,000 PDFs) independently.
4. Atomic Quota Enforcement Engine
To guarantee ultra-low latency (< 5ms) across distributed multi-node clusters:
- When a PDF conversion job is submitted,
pdf-apiverifies and increments your quota using an atomic Redis Lua script (quota:usage:{period_end}:{user_id}). - Warm-up & Fallback: If the Redis key is absent (such as right after entering a new monthly billing window after the 17th or after cache expiration),
pdf-apiperforms a fast, accurate fallback query against PostgreSQL for all jobs within your current active anchor window (created_at >= current_period_start), initializes the Redis counter with exact TTL (2,678,400s), and processes your request without delay.