Skip to content

Rate limits & quotas

We enforce two limits independently:

  1. Per-minute rate limit — sliding window, per API key.
  2. Monthly quota — total result units charged in your billing period.

When either trips, calls return 429.

Plan tiers

PlanRate limit (req/min)Monthly result quota
Free20100
Starter605,000
Pro30050,000
Scale1,500500,000

A “result” = one row returned. Cache hits on /v1/properties/{zpid} and its sub-resources count as 0 units — they don’t burn quota.

What counts as a unit

EndpointUnits charged
/v1/properties/by-url (sync, cache miss)1 per result returned (≈ 1)
/v1/properties/by-address1
/v1/properties/{zpid} (cache hit, < 24h)0
/v1/properties/{zpid} (cache miss)1
/v1/properties/{zpid}/... sub-resources0 if cached, 1 on miss
/v1/buildings/by-url (extract_units != disabled)1 per unit returned
/v1/properties/batch (async)1 per result, charged on completion
/v1/search, /v1/listings/*1 per listing returned
/v1/search/with-details1 per search listing + 1 per detail row

429 responses

{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for plan 'starter' (60/min)",
"request_id": "..."
}
}
{
"error": {
"code": "quota_exceeded",
"message": "Plan 'starter' quota of 5000 reached. Used 5012 this period.",
"request_id": "..."
}
}

Best practices

  • Cache aggressively on your side for static fields (zpid, address, year built).
  • Use sub-resources instead of the full detail when you only need photos or schools.
  • Use async + webhooks for any batch over ~50 — sync calls have a 5-min ceiling.
  • Back off on 429 with exponential jitter. Don’t retry faster than once every 2 seconds.