Rate Limits
The SpAItial Developer API enforces per-key rate limits using fixed-window counters.
Defaults
| Bucket | Default | Applies to |
|---|---|---|
| General | 60 requests / minute | Every authenticated request, regardless of method. |
| World create | 10 requests / minute | POST /v1/worlds only. Consumed in addition to the general bucket. |
| Downloads | 120 requests / minute | GET /v1/worlds/requests/{id}/splat, GET /v1/worlds/requests/{id}/panorama, and GET /v1/panoramas/{id}/download. Runs on its own bucket so polling a download does not lock out status/result/cancel. |
A POST /v1/worlds therefore decrements both the general and the world-create buckets in the same window. Panorama edits (POST /v1/panoramas/edit) use the general bucket. Downloads decrement only the dedicated download bucket.
Response headers
Every rate-limited response (success or 429) includes:
| Header | Description |
|---|---|
X-RateLimit-Limit | The bucket's ceiling for this request, in requests per minute. |
X-RateLimit-Remaining | Requests remaining in the current window. Clamped to 0. |
X-RateLimit-Reset | Unix timestamp (seconds) at which the current window expires. |
Retry-After | Present on 429 responses; seconds to wait before retrying. |
When you hit the limit
A blocked request returns 429 Too Many Requests with the standard error codes:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 17 seconds."
}
}
Recommended client behavior:
- Read
Retry-Afteron429responses, or fall back toX-RateLimit-Reset. - Apply jitter so a fleet of clients does not synchronize against the same window boundary.
- Pair retries on
POST /v1/worldsandPOST /v1/panoramas/editwith anIdempotency-Keyso the retry does not create duplicate work.