Skip to main content

Rate Limiting

PrairieCloud enforces two types of limits:

  • Monthly quota — total requests per billing period
  • Per-minute burst limit — requests per 60-second rolling window

Both limits are enforced per API key.


Tier Limits

See prairiecloud.io/pricing for a full comparison of what's included at each tier.

PlanPriceMonthly QuotaPer-Minute BurstConcurrent Requests
Free$01,000102
Pioneer$19/mo50,00030010
Pro$49/mo500,0001,50025
Business$299/mo2,000,0003,00050
EnterpriseCustom10,000,00010,000100

When any limit is reached, the API returns 429 Too Many Requests. Rate limiting is applied at three levels: monthly quota, per-minute burst, and concurrent connections. Need higher limits? Upgrade your plan.


Rate Limit Response Headers

Every API response includes rate limit headers:

HeaderDescription
X-RateLimit-LimitYour monthly quota
X-RateLimit-RemainingRequests remaining this billing period
X-RateLimit-ResetUnix timestamp when the monthly quota resets

Example response headers:

HTTP/2 200
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1743379200

Convert the X-RateLimit-Reset timestamp to a human-readable date:

date -d @1743379200
# → Sat Mar 1 00:00:00 UTC 2026

Request Cost

Not all requests cost the same against your quota. Most requests cost 1 unit, but requests involving many variables, geographies, or wildcard expansions cost more.

Requests to /v1/variables, /v1/geographies, /v1/topics, /v1/boundaries, and /v1/centroids endpoints are free and never count against your quota.

Base Cost

ScenarioCost
Standard request (≤10 variables, ≤10 geos)1 unit
>10 variables or >10 geographies1 + ceil(overrun / 10) units
Wildcard geography (e.g. county:48*)ceil(expanded_geos / 10) units

Examples

RequestExpanded SizeCost
?variables=pop&geo=state:481 variable, 1 geo1 unit
?variables=pop,income,... (15 vars)15 variables2 units
?geo=county:48* (254 TX counties)254 geos26 units
?geo=county:06* (58 CA counties)58 geos6 units
Monitor your usage

Wildcard queries are powerful but consume quota quickly. Check your remaining quota via the Dashboard or the /v1/account/usage endpoint.


429 Response Format

When you exceed a rate limit, you receive a 429 Too Many Requests response with an RFC 7807 body and a Retry-After header:

HTTP/2 429
Content-Type: application/problem+json
Retry-After: 12
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1743379200
{
"type": "https://prairiecloud.io/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Per-minute burst limit of 10 exceeded for tier 'free'.",
"instance": "/v1/data",
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"limit_type": "burst",
"plan": "free",
"upgrade_url": "https://dashboard.prairiecloud.io/dashboard/billing/"
}

The response now includes three additional fields:

FieldDescription
planYour current plan name (e.g., free, pioneer, pro)
quotaYour monthly request quota
upgrade_urlDirect link to upgrade your plan for higher limits

The Retry-After header is always present on 429 responses and indicates the number of seconds to wait before retrying.


Checking Your Current Usage

Monitor your current usage in the Dashboard — daily usage charts and quota progress are visible on the Usage page.

You can also check your remaining quota programmatically via the API:

curl -H "X-API-Key: YOUR_KEY" \
"https://api.prairiecloud.io/v1/account/usage"
{
"data": {
"tier": "free",
"quota_limit": 1000,
"quota_used": 153,
"quota_remaining": 847,
"period_start": "2026-02-01",
"period_end": "2026-02-28",
"burst_limit": 10
}
}

Retry Strategy with Exponential Backoff

When you receive a 429, always respect the Retry-After header before retrying. For robustness, combine this with exponential backoff:

import time
import random
import requests

def request_with_retry(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)

if response.status_code == 429:
# Respect Retry-After header
retry_after = int(response.headers.get("Retry-After", 1))
# Add jitter to avoid thundering herd
wait = retry_after + random.uniform(0, 1)
print(f"Rate limited. Waiting {wait:.1f}s before retry {attempt + 1}/{max_retries}")
time.sleep(wait)
continue

if response.status_code >= 500:
# Exponential backoff for server errors
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"Server error {response.status_code}. Waiting {wait:.1f}s")
time.sleep(wait)
continue

return response

raise Exception(f"Request failed after {max_retries} retries")

Key Principles

  1. Always check Retry-After — this is the minimum wait time. Never retry before it elapses.
  2. Add jitter — a small random offset (0–1 seconds) prevents multiple clients from retrying simultaneously.
  3. Use exponential backoff for 5xx errors — double the wait time on each retry attempt.
  4. Set a maximum retry count — don't retry forever; surface the error to the caller after N attempts.
  5. Don't retry 4xx errors (except 429) — a 400 Bad Request or 404 Not Found won't succeed on retry.

Optimizing Your Usage

To stay within your quota:

  • Batch variables: Request multiple variables in one call instead of one per request. The variables parameter accepts a comma-separated list.
  • Batch geographies: Similarly, request multiple geo values in a single call.
  • Cache responses: ACS data doesn't change mid-month. Cache responses locally for frequently requested variable/geography combinations.
  • Use the largest geographic unit you need: County-level data is available in one request; iterating over all tracts in a county could use hundreds of requests.

Tier-Gated Features

Some API features are only available on higher-tier plans. If you attempt to use a Pro-tier feature on a Free or Pioneer plan, the API returns 403 Forbidden with a feature-requires-upgrade error type:

{
"type": "https://prairiecloud.io/errors/feature-requires-upgrade",
"title": "Feature Requires Upgrade",
"status": 403,
"detail": "CSV export requires a Pro plan or higher.",
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"upgrade_url": "https://dashboard.prairiecloud.io/dashboard/billing/"
}

Features by Tier

FeatureFreePioneerProBusinessEnterprise
CSV export (format=csv)
Wildcard geography (geo=county:48*)
Pagination limit >200✅ (5,000)✅ (10,000)✅ (10,000)

Free and Pioneer users can access all other endpoints and features. See Error Handling for the full error response format.


Next Steps

  • Error Handling — Full RFC 7807 error response format and error code reference
  • API Keys — Key management, rotation, and security best practices
  • Quickstart — See the full quickstart for your first API call