Error response format
All errors follow this structure:{
"error": {
"code": "INVALID_PARAMS",
"message": "Parameter 'maxPrice' must be a positive integer.",
"status": 400
}
}
error object:
| Field | Present on | Description |
|---|---|---|
retryAfter | Per-key RATE_LIMIT_EXCEEDED (429) and UPSTREAM_ERROR (503) | Seconds to wait before retrying |
quotaContext | QUOTA_EXCEEDED (429) for monthly quota or a batch lookup, not the watcher cap | Your tier and quota, the next tier up, and an upgrade link. See Rate Limits |
upgrade | TIER_RESTRICTED, per-key RATE_LIMIT_EXCEEDED, and quota QUOTA_EXCEEDED, when a higher tier would lift the error | The tier required and where to upgrade |
401 responses from API key authentication also carry a WWW-Authenticate header.
Error codes
| Code | HTTP Status | Description |
|---|---|---|
INVALID_PARAMS | 400, 422 | Invalid or missing parameters (400). Unknown area IDs in areas return 422 |
MISSING_API_KEY | 401 | No Authorization header where a key is required. On REST endpoints a keyless request runs as anonymous Free, so a keyless call to a paid-only endpoint (such as property or building detail) returns 403 TIER_RESTRICTED instead |
INVALID_API_KEY | 401 | Unknown, revoked, or disabled key, or a key with no active Borough subscription (including a cancelled plan) |
EXPIRED_API_KEY | 401 | The license key has passed its expiry date |
TIER_RESTRICTED | 403 | Endpoint requires a higher tier |
NOT_FOUND | 404 | Resource not found, including a missing webhook subscription or watcher |
WEBHOOK_NOT_FOUND | 404 | A webhook subscription disappeared while an update to it was being applied (for example, it was deleted concurrently) |
QUOTA_EXCEEDED | 429 | Monthly request quota exceeded (including overage cap), or a batch lookup needs more units than remain. Also returned when creating a watcher would pass the active-watcher cap (50, or 5 listing watchers) |
RATE_LIMIT_EXCEEDED | 429 | Per-minute rate limit exceeded |
INTERNAL_ERROR | 500 | Unexpected server error |
UPSTREAM_ERROR | 503, 502 | 503: your subscription could not be verified momentarily; your key is fine. 502: the photo proxy could not fetch an image |
SERVICE_DISABLED | 503 | API temporarily disabled via kill switch |
Watcher request errors
| Condition | Response |
|---|---|
pollInterval below the minimum for the watch type (Business: 3600 seconds for listing watchers, 300 for building and search) | 400 INVALID_PARAMS |
Search watcher filters match more than 500 active listings, at create or when resumed with {"active": true} | 400 INVALID_PARAMS. At create, narrow the filters. PATCH cannot change filters, so on resume delete the watcher and create a narrower one; retrying unchanged will not help |
| Creating a watcher past the 50-active or 5-active-listing-watcher cap | 429 QUOTA_EXCEEDED |
| Resuming a paused watcher past either cap | 400 INVALID_PARAMS |
Retry guidance
| Status | Action |
|---|---|
| 400 | Fix the request parameters and retry |
| 401 | Check your API key |
| 403 | Upgrade your tier |
| 404 | Verify the resource ID exists |
| 422 | Fix the area IDs (resolve them with GET /v1/areas) |
429 RATE_LIMIT_EXCEEDED | Wait for Retry-After seconds, then retry |
429 QUOTA_EXCEEDED | Do not retry. There is no Retry-After; wait for your quota period to reset or upgrade (read quotaContext). For the watcher cap, pause or delete a watcher first |
| 500 | Retry with exponential backoff |
| 502 | Retry after a brief delay |
503 UPSTREAM_ERROR | Retry after a few seconds (retryAfter) with exponential backoff; do not rotate your key |
503 SERVICE_DISABLED | Service is temporarily down; retry later |
Request tracing
Every response includes anX-Request-Id header (UUID v4). Include this ID in support requests for log correlation.