Skip to main content

Rate Limits

PDFCanon enforces rate limits on authentication and normalization endpoints to protect against abuse and ensure service availability.

Normalization quota

The POST /api/normalize endpoint is subject to a tier-based monthly document quota rather than a per-second rate limit.

PlanMonthly limitMax file sizeConcurrent jobsPrice (monthly)Overage rate
Free100 documents5 MB1$0Hard block
Starter10,000 documents25 MB5$99/mo$0.010/doc
Growth50,000 documents50 MB10$249/mo$0.005/doc
Pro200,000 documents100 MB20$499/mo$0.003/doc

Annual billing is available at a 2-month discount (pay for 10 months).

When the quota is exhausted, Free-tier organizations are hard-blocked (402 Payment Required). Paid plans continue processing with overage charges applied per document. The quota resets at the start of each billing cycle.

Check your current usage at any time with GET /api/billing/info.

Authentication rate limits

Authentication endpoints use fixed-window IP-based rate limiting to prevent brute-force and enumeration attacks.

EndpointLimit
POST /api/auth/register3 requests / hour / IP
POST /api/auth/login5 requests / 15 min / IP
POST /api/auth/forgot-password3 requests / hour / IP

When a rate limit is exceeded, the endpoint returns 429 Too Many Requests.

Handling rate limit errors

When you receive a 429 response, wait before retrying. Use the Retry-After header if present.

import httpx, time

def login_with_retry(email, password, max_attempts=3):
for attempt in range(max_attempts):
resp = httpx.post(
"https://api.pdfcanon.com/api/auth/login",
json={"email": email, "password": password},
)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
time.sleep(retry_after)
continue
resp.raise_for_status()
return resp.json()["access_token"]
raise RuntimeError("Rate limit exceeded after retries")

Idempotency and retries

For normalization requests, use idempotency keys to safely retry without consuming additional quota:

curl -X POST https://api.pdfcanon.com/api/normalize \
-H "X-Api-Key: pdfn_your_api_key_here" \
-F "file=@input.pdf" \
-F "idempotency_key=my-unique-job-id-123"

A request with the same idempotency_key and identical file will return the cached result without consuming quota or reprocessing the document. See Idempotency for details.