Per-module buckets
Rate limits are enforced per module bucket, not on a single global limit. This means a burst of read traffic on the Invoices bucket cannot starve out a small burst of write traffic on the Rates bucket. Buckets refill continuously at the per-second rate (token-bucket algorithm) with a burst capacity equal to the per-minute limit.
| Bucket | Per second (sustained) | Burst (per minute) |
|---|---|---|
| Modules (read) | 10 | 200 |
| Modules (write) | 2 | 60 |
| Rates (read) | 20 | 400 |
| Rates (write — suggestion approve/reject) | 5 | 150 |
| Reservations (sync + read) | 5 | 100 |
| Invoices (read) | 10 | 200 |
| Invoices (write — issue/correct) | 3 | 90 |
| Reviews (read + reply) | 5 | 150 |
| Webhooks (management) | 1 | 20 |
HTTP 429 handling
When a bucket is exhausted the API returns HTTP 429 with the error body { "error": "rate_limited", "code": "RP-1004", "retry_after_seconds": <n> }. The Retry-After HTTP header is also set to the same integer number of seconds. Do not retry sooner than that.
X-RateLimit-* headers
Every response — successful or not — carries three headers so you can budget calls without probing:
X-RateLimit-Bucket: the name of the bucket that gated this call, e.g.rates.write.X-RateLimit-Remaining: tokens remaining in the burst window at request time.X-RateLimit-Reset: unix timestamp when the burst window fully refills.
Per-plan quotas
The tables above are the technical limits. On top of them we apply a monthly logical quota per plan for a subset of high-value write endpoints:
| Plan | Rate suggestions written/month | Invoices issued/month | Webhook deliveries/month |
|---|---|---|---|
| Starter | 3,000 | 4,000 | 50,000 |
| Growth | 15,000 | 25,000 | 250,000 |
| Estate | 60,000 | 100,000 | 1,000,000 |
Hitting a monthly quota returns HTTP 429 with error code RP-1005 and the header X-RateLimit-Quota-Reset set to the first day of the next month. If you're bumping into a monthly quota, email support@suiteprofit.org and we'll uplift the specific bucket rather than force a plan change.
Best practices
- Batch reads where possible. The
/rates/suggestionsendpoint accepts up to 200 items per page; use it before you consider parallelising N single-item requests. - Back off with jitter on HTTP 429 to avoid thundering-herd retries.
- Prefer webhooks over polling. If you're polling
/rates/suggestionsevery minute, subscribe torate.suggestedinstead. - Use idempotency keys on writes so retries after a network error don't double-write.
Shared vs dedicated buckets
Buckets are per Suite Profit account, not per token. Multiple integrations sharing one account share one bucket. If you have two independent teams building against the same account, request separate accounts through support@suiteprofit.org.