get_estaite_zip_metrics
Description
Returns rental metrics for a specific 5-digit US ZIP code, including median price, year-over-year change, listing count, vacancy, saturation, and median household income. Use this when the user provides a ZIP and you want point-of-interest metrics without resolving a submarket id.
Two response shapes:
- Slice mode (when both
property_typeandbedroomsare passed) — a flat per-slice metrics object. - Summary mode (when either is omitted) — a multi-segment grid under
segments.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
zip | string | yes | 5-digit US ZIP code, e.g. "90210". Must be exactly 5 digits. |
property_type | enum (apt, sfr, ct) | no | Apartment, single-family rental, or condo/townhome. Omit for full summary. |
bedrooms | integer 1–5 | no | Bedroom count. Omit for full summary. |
Both property_type and bedrooms must be set together to trigger slice mode. If only one is supplied the tool returns the summary anyway.
Response — Slice mode
{ "attribution": "Data via Estaite Submarket Index", "powered_by": "Estaite.com", "source_domains": [], "api_version": "v1", "request_id": "f0a4e9c2-7f8e-4d11-9a7e-7a2f1b4c8e91", "as_of": "2026-03-01", "data": { "mode": "slice", "zipcode": "90210", "city": "Beverly Hills", "state": "CA", "property_type": "apt", "bedrooms": 2, "median_price": 4250.0, "median_price_yoy_change": 3.4, "num_listings": 87, "vacancy_rate": 4.1, "saturation": 1.62, "median_household_income": 112450.0 }}Response — Summary mode
{ "attribution": "Data via Estaite Submarket Index", "powered_by": "Estaite.com", "source_domains": [], "api_version": "v1", "request_id": "f0a4e9c2-7f8e-4d11-9a7e-7a2f1b4c8e91", "as_of": "2026-03-01", "data": { "mode": "summary", "zipcode": "90210", "city": "Beverly Hills", "state": "CA", "vacancy_rate": 4.1, "saturation": 1.62, "median_household_income": 112450.0, "segments": { "apartments": { "br1": { "median_price": 3100, "yoy_change": 2.8, "listings": 41 }, "br2": { "median_price": 4250, "yoy_change": 3.4, "listings": 87 }, "br3": { "median_price": 5800, "yoy_change": 2.1, "listings": 36 }, "br4": { "median_price": 7200, "yoy_change": 1.5, "listings": 18 } }, "single_family": { "br1": { }, "br2": { }, "br3": { }, "br4": { } }, "condo_townhome": { "br1": { }, "br2": { }, "br3": { }, "br4": { } } } }}Fields
Top level (both modes)
| Field | Type | Description |
|---|---|---|
attribution | string | Required attribution. Echo verbatim. |
powered_by | string | Always "Estaite.com". |
source_domains | string[] | Contributing data-provider domains. |
api_version | string | Always "v1". |
request_id | string | Per-request UUID. |
as_of | string | Latest published month, formatted as YYYY-MM-DD (first of the month). |
data | object | The payload. data.mode is "slice" or "summary". |
data — Slice mode
| Field | Type | Description |
|---|---|---|
mode | string | Always "slice". |
zipcode, city, state | string | ZIP identity. |
property_type, bedrooms | string / number | Echoes the slice. |
median_price | number | Median monthly rent for the slice, USD. |
median_price_yoy_change | number | YoY change in whole-percent. Note the longer field name in slice mode. |
num_listings | number | Listing count for the slice. |
vacancy_rate | number | Vacancy in whole-percent. |
saturation | number | Saturation in whole-percent. |
median_household_income | number | Median household income for the ZIP, USD. |
data — Summary mode
| Path | Type | Description |
|---|---|---|
mode | string | Always "summary". |
zipcode, city, state | string | ZIP identity. |
vacancy_rate, saturation | number | ZIP-level market health (same as slice mode). |
median_household_income | number | ZIP-level income (same as slice mode). |
segments[label][br_key].median_price | number | Median rent for the cell, USD. |
segments[label][br_key].yoy_change | number | YoY change in whole-percent. ⚠️ Field name differs from slice mode — here it’s just yoy_change, not median_price_yoy_change. |
segments[label][br_key].listings | number | Listing count. |
Errors
| Code | HTTP | Meaning |
|---|---|---|
MISSING_ZIP | 400 | zip was not provided or is empty. |
INVALID_ZIP | 400 | zip is not a 5-digit numeric string. |
INVALID_PROPERTY_TYPE | 400 | property_type is not one of apt, sfr, ct. Only thrown when both property_type and bedrooms are passed (slice mode). |
INVALID_BEDROOM_COUNT | 400 | bedrooms is outside 1–5. Only thrown in slice mode. The error response includes valid_values: [1,2,3,4,5]. |
ZIP_NOT_FOUND | 404 | No data exists for the requested ZIP. |
Notes
- All percent values are whole-percent. A
vacancy_rateof4.1means 4.1%, not 410%. - Field names differ between slice and summary modes. Slice uses
median_price_yoy_change; summary uses justyoy_change. Branch ondata.modewhen parsing or you’ll silently readundefined. - A ZIP can have data even when its containing submarket is sparse, and vice versa. This tool reads the underlying
RentalData_Combinedview directly rather than going through submarket aggregation.