Why caps exist
Because paperplane is keyless (no accounts), it can’t identify callers by credential. So it enforces abuse limits on two dimensions, keyed by how it can attribute the request.The two caps
number
Friendly cap per sender identity (caller + declared sender email). This is the number a normal user notices.
- 5 letters/day, 20/month
number
Enforcement cap per actor (API key id, else the client IP). Nothing the caller supplies varies the key, so changing the email can’t escape it. Sits higher so a shared office NAT still works.
- 15 letters/day, 60/month, 200/month spend
What a cap hit looks like
Verifying a caller
Attribution strategies:- Any
emailyou pass works as part of the sender fingerprint. - A verified account (launch-phase feature) lifts these caps; until then it’s per-IP with the ceilings above.
If a request can’t be attributed at all, it’s refused with a clear error rather than let through unlimited (fail-closed), because we can’t apply limits we can’t attribute.
Per-instance throttles
Separately from the sender/actor caps above, a handful of routes carry their own simple per-minute throttle — a speed bump against scripted abuse, not the billing-abuse boundary the caps above are for. Each is keyed on the API key when one is present, else the caller’s IP, and returnsrate_limited with
Retry-After like any other 429.
Sandbox is not exempt from throttling
Sandbox orders skip the sender/actor caps above entirely — they cost no postage, so they don’t count against your 5/day or 15/day sending limits. But a sandbox order still runs the real (billed) content screener and renders or fetches a PDF, and the endpoint is reachable with no API key at all, so it carries its own 20/minute throttle (the first row of the table above) as a floor against generating unlimited billed screening calls for free. That throttle is a different code path from the sender/actor caps, and does not share their daily/monthly windows.Do this
- Build perks/bulk in mind: stay under 15/day or contact for a verified account.
- Handle
velocity_limitin code — surface thenextmessage, don’t silently retry forever. - Sandbox testing is generous (20 sandbox orders/minute) but not unlimited — see above.