Rate limits

Per-tier matrix

| Tier | Monthly quota | Burst / minute | Per-key concurrency | Overage | |---|---|---|---|---| | Public front door (GET /api/v1, openapi.json) | n/a | per-IP limited | n/a | hard 429 | | Self-serve $49 | 10,000 / mo | 60 / min | 2 in-flight | $0.005 / call | | Self-serve $99 | 50,000 / mo | 300 / min | 2 in-flight | $0.003 / call | | Self-serve $299 | 250,000 / mo | 600 / min | 5 in-flight | $0.0015 / call | | Crate API for Sync $2000 | 1,000,000 / mo | 1000 / min | 10 in-flight | Included; ~5M/mo triggers conversation, not auto-charge |

What the limits mean

Monthly quota: total calls in a calendar month. Resets on the 1st of each month UTC. Visible in your dashboard at any time + via GET /api/v1/usage.

Burst per minute: sliding-window rate limit. Allows steady traffic at the documented rate; bursts above it return 429.

Per-key concurrency: number of in-flight requests on a single key. Designed for batch enrichment workloads — Sync's 10 in-flight × 100 IDs each = 1000 simultaneous enrichments. If you exceed it, you get 429 with reason: 'concurrency'. Slot frees as soon as the in-flight request returns OR within 60s (EXPIRE safety net).

Response headers

EVERY authenticated success response (200) includes:

X-RateLimit-Limit: <tier_burst_per_min>
X-RateLimit-Remaining: <calls_left_in_burst_window>
X-RateLimit-Reset: <unix_epoch_seconds_when_window_resets>

Use these to pace your own throughput. A polite client adjusts its rate down as X-RateLimit-Remaining approaches 0.

429 response shape

HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716625200
Content-Type: application/json

{ "error": "rate_limited", "retry_after_seconds": 23 }

Why batch matters for Sync

The /api/v1/masters/batch endpoint counts as ONE rate-limit unit per request, regardless of how many IDs you include. Sync's 1000/min burst × 500 IDs per batch = 500,000 enrichments / minute effective throughput.

For sync-agency clearance research workflows (typically 500-1000 candidate masters per brief), this is the load-bearing economic argument for the $2k tier. See carrefour#55 for the differentiation rationale.

Fail-open posture

If our rate-limit substrate (Redis) is unreachable, we fail OPEN — your request proceeds without a rate-limit decision. We log this as crate.ratelimit.fail_open + alarm on it; you'll never see a rate-limit-related outage as a customer.

The 15-second wall-clock deadline + the 144 in-flight pool cap are the hard backstops.

Tier upgrades

Self-serve customers upgrade via the Stripe Customer Portal — Plan change takes effect on the next billing cycle, but the new limits apply immediately at the gate (customer.tier flips on invoice.payment_succeeded).

Sync-tier customers email jani@hosaka.fm for contract changes.