Rate Limits

The SDX API enforces rate limits to ensure fair, reliable access for all integrators. Rate limits are generous and free — there are no paid tiers to unlock higher limits.

Default limits

ScopeLimit
Per API key1,000 requests per minute
Per OAuth2 user300 requests per minute
Bulk endpoints (CSV upload, batch operations)10 requests per minute
Report generation20 requests per minute

These limits apply independently. For example, an API key can make 1,000 general requests and 10 bulk requests in the same minute.

Rate limit headers

Every API response includes headers that show your current rate limit status:

HeaderDescriptionExample
X-RateLimit-LimitMaximum requests allowed per window1000
X-RateLimit-RemainingRequests remaining in the current window847
X-RateLimit-ResetUnix timestamp when the window resets1706100060
X-RateLimit-WindowWindow duration in seconds60

Handling 429 responses

When you exceed the rate limit, the API returns a 429 Too Many Requests response:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 12 seconds.",
    "retry_after": 12
  }
}

The response includes a Retry-After header (in seconds) indicating when you can retry.

Implement exponential backoff with jitter:

import time
import random

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:
            return response
        retry_after = int(response.headers.get("Retry-After", 1))
        jitter = random.uniform(0, retry_after * 0.1)
        time.sleep(retry_after + jitter)
    raise Exception("Max retries exceeded")

Best practices

Batch where possible

Instead of making individual requests for each meter reading, use the batch endpoints:

# Instead of 100 individual POST requests:
POST /v1/buildings/bld_123/meters/mtr_456/readings

# Use one batch request:
POST /v1/buildings/bld_123/meters/mtr_456/readings/batch

Cache responses

Benchmark scores and property details change infrequently. Cache these responses and use the If-None-Match header with the ETag value to check for updates:

curl https://api.sdx.dev/v1/buildings/bld_123/benchmarks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "If-None-Match: \"abc123\""

If the data hasn't changed, the API returns 304 Not Modified with no body, which does not count against your rate limit.

Use webhooks

Instead of polling for updates, subscribe to webhooks to receive real-time notifications when data changes.

Requesting higher limits

If your integration legitimately requires higher limits, contact api-support@sdx.dev with a description of your use case. Limit increases are provided free of charge for genuine integration needs.

Sandbox limits

The sandbox environment has the same rate limits as production. This ensures your integration is tested under realistic conditions.

Next steps