Errors
All errors share one envelope:
{ "error": { "code": "invalid_url", "message": "Must be a https://www.zillow.com property URL", "request_id": "8f7a3b..." }}error.code is stable and machine-readable. Match on it; do not parse
message. Include request_id when reporting issues.
Status code mapping
| HTTP | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (e.g. webhook) |
| 202 | Accepted, async job started |
| 204 | No content (e.g. webhook revoke) |
| 400 | Client validation failed |
| 401 | Missing or invalid API key |
| 402 | Out of credits |
| 403 | Account suspended or operation not allowed on current plan |
| 404 | Resource not found |
| 409 | Job not in expected state |
| 429 | Rate limit hit |
| 502 | Upstream call failed |
| 504 | Upstream call timed out |
Common error codes
| Code | When |
|---|---|
missing_api_key | No Authorization header |
invalid_api_key | Bad format, unknown, or revoked |
out_of_credits | Account credit balance reached 0, top up at /app/billing or upgrade |
rate_limited | Per-minute rate limit hit |
invalid_url | URL doesn’t match the expected Zillow pattern |
invalid_address | Address too short or malformed |
invalid_zpid | Non-numeric zpid |
missing_input | A required body/query field is absent (e.g. POST /v1/search with no filters and no searchUrls; by-url with no url) |
invalid_filters | filters is present but unusable, most commonly a search with no bbox (a free-text location/city alone is not enough), or a malformed bbox/range object |
invalid_search_url | A searchUrls[].url is not a usable Zillow search URL, it must contain a ?searchQueryState=... query parameter (pretty URLs like /austin-tx/houses/ are rejected) |
invalid_status | Bad value for status |
invalid_extract_units | Bad value for extract_units |
not_found | Property/job/webhook not found |
job_not_ready | Job is not in succeeded |
job_not_found | UUID does not match an account-owned job |
upstream_timeout | Provider call exceeded timeout |
upstream_error | Provider returned non-2xx |
invalid_json | Body could not be parsed as JSON |
Search validation errors (worked examples)
A search must carry a bounding box or a pre-built Zillow URL. These are the
three ways a search request fails validation before it ever reaches upstream
(all return 400):
// missing_input, nothing to search onPOST /v1/search { "maxItems": 50 }→ { "error": { "code": "missing_input", "message": "..." } }
// invalid_filters, free-text location only, no bboxPOST /v1/search { "filters": { "location": "Austin, TX", "status": "for_sale" } }→ { "error": { "code": "invalid_filters", "message": "..." } }
// invalid_search_url, URL has no searchQueryStatePOST /v1/search { "searchUrls": [{ "url": "https://www.zillow.com/austin-tx/houses/" }] }→ { "error": { "code": "invalid_search_url", "message": "..." } }Fix: supply filters.bbox (or bbox=w,s,e,n on the GET wrapper), or a
searchUrls[].url that contains ?searchQueryState=.... See
Search for how to obtain a bbox.
Idempotency and retries
- Reads (
GET) are safe to retry on 5xx and 429. - Writes (
POSTasync) create new jobs, retrying creates a new job. Userequest_idcorrelation in your logs to match attempts. - Webhooks include a per-attempt counter (
attempt) and a timestamp; treat any single delivery as at-least-once.