# Ziplot > Free API and remote MCP server that returns public-record facts about a US property address for rental investors and their AI agents: FEMA flood zone, HUD rent benchmark by bedrooms, a rough property-tax estimate, and (in covered markets) parcel zoning plus short-term-rental (STR) permit eligibility. Every value carries a source and an as-of date. Informational summary of public records; not legal, tax, insurance, or lending advice. Coverage: Any US address gets the basic check (FEMA flood zone at the geocoded point, HUD rent benchmark by bedrooms, a rough property-tax estimate). Zoning or address-level eligibility plus short-term-rental (STR) rules (level "full"): Nashville / Davidson County TN; Denver (City and County) CO; Scottsdale (city limits) AZ; Chicago (city limits) IL; New York City (five boroughs) NY; Austin (full- and limited-purpose city) TX; Boise (City of Boise and unincorporated Ada County) ID; Miami (City of Miami, Miami Beach, unincorporated Miami-Dade) FL; Orlando (City of Orlando and unincorporated Orange County) FL; and San Diego (City of San Diego) CA. City-wide STR rules plus an address-level permit lookup ("partial"): Phoenix (city limits) AZ; and Tempe (city limits) AZ. Many more cities, counties and resort areas get STR rules and taxes only, with no address layer ("rules_only"). Elsewhere zoning and STR return not_covered. HOA, condo, deed, and covenant restrictions are never checked. The full, current market list with levels and verified dates: GET /v1/coverage. Limits: Free, no key needed: 50 lookups per day per network without a key. With a free API key (POST /v1/keys, shown once): 3,000 lookups per month. MCP initialize and tools/list don't count. Each MCP tools/call counts as 1 lookup, also inside a JSON-RPC batch (at most 25 tools/call per batch), including an answer from the cache; like bulk, a batch runs at most 1 new (uncached) lookup per request, and the other uncached calls return a tool error saying to re-send them (not counted). A request rejected for a bad or missing address or argument (HTTP 400, or an MCP tool input error), or one that ends in an upstream error (HTTP 5xx), is not counted. Answers are cached for up to 6 hours. No paid plans are live. ## API - [Deal check (JSON)](https://ziplot.daderader.workers.dev/v1/deal-check?address=321%2050th%20Ave%20N%2C%20Nashville%2C%20TN&bedrooms=3): `GET /v1/deal-check?address=...&bedrooms=0-4` (default 2). Optional `value` (USD; echoed in query.value; when an Assessor value exists, the estimate at your value is in property_tax.estimate_at_your_value), `include` (comma list of rent, tax, flood, str, zoning), `format=text` for plain English. - [Human view](https://ziplot.daderader.workers.dev/check?address=321%2050th%20Ave%20N%2C%20Nashville%2C%20TN): `GET /check?address=...` - Deal picture (JSON): GET /v1/deal-picture?address=...&price=... (price required; POST a JSON body also works). Same answer as deal-check plus a deal block: illustrative arithmetic on your inputs (monthly payment, monthly cash flow, NOI, cap rate, cash-on-cash, DSCR), with every input, its source (caller, default or deal-check), each assumption and each formula shown. Optional: bedrooms, rent, rate, term_years, down_pct, closing_pct, insurance, hoa, vacancy_pct, management_pct, maintenance_pct, tax. Rent defaults to the HUD benchmark and tax to the deal-check estimate; rate and insurance are never assumed. Counts as one lookup. Not a quote, appraisal, or lending opinion. - Bulk (JSON): Bulk: POST /v1/deal-check/bulk with a JSON body {"addresses": ["...", {"address": "...", "bedrooms": 3, "value": 450000}]} (1 to 25 items, optional top-level bedrooms). Each answered address counts as 1 lookup against your limit; deferred, invalid, and errored items are free. Cached addresses are answered right away, but each call runs at most 1 new (uncached) lookup: this is a limit of the free hosting plan Ziplot runs on, and a paid hosting plan would lift it. Re-send only the deferred items; every call answers at least one new address. - Coverage list: GET /v1/coverage returns every market the API answers today with its level (full, partial, rules_only; everywhere else is not_covered), the date its rule sources were last verified (last_recheck), and, where an address-level permit source is read, that source's own data date. rules_only markets are labeled address_layer "not covered": zoning and per-address permits are not checked there. No key needed; it does not count as a lookup. - Coverage pre-check (free, not a lookup): POST /v1/coverage/check with {"addresses": ["street, city, ST ZIP", ...]} (1 to 100), or GET /v1/coverage/check?address=..., says from the city and state in the text which listed market each address is likely in (matched_on city_state, with the market id, name, state and level), or that the state has no listed market, or that the city name did not match. It uses no geocoding and no outside calls, does not count toward your lookup limit, and has its own limit (30 calls per minute). It is a hint: /v1/deal-check decides from the geocoded location. - Changes feed: GET /v1/changes lists rule and record updates by market, newest verified date first. Each entry has the market (id, name, state, level), the record id and name, the date it was verified, the change type when known (rechecked, updated, or null), and the official source (name, URL, date read). It does not include record values; get those from a lookup or GET /v1/coverage. Optional: market (an id from /v1/coverage), since (YYYY-MM-DD, default the last 90 days), limit (1 to 50, default 50). Informational data only; no key needed, not counted as a lookup. - Chicago: str.registrations_at_address lists the City's APPROVED shared housing unit registrations at the street address (count, plus registration number, unit, status, status date, and expiry; this_unit when your address has a unit number). It is a separate fact from str.existing_permit_on_parcel, which stays null in Chicago because it is not verified whether a registration carries over to a new owner. A registration belongs to a host and unit; no host names are requested or returned. - Denver and Scottsdale: str.permit_status_at_address lists the license rows in the city's STR registry at the address (in Denver without a unit number, every row on the parcel; with a unit number, that unit's rows and this_unit): license number, type, registry status and expiry. status is active or needs_review (a pending application, or a registry value that is not mapped); raw_status is the registry's own value. Owner, manager, and contact fields are never requested, and owner-occupancy is never inferred from a registry row. - Free API key: `POST /v1/keys`. Send it as `Authorization: Bearer ` or `X-API-Key: `. - Health: `GET /health`. Service index: `GET /` with `Accept: application/json`. - HTTP 404 = address not found; 503 = a data source timed out, retry. Both carry only the error, warnings, and a `hint`; no data sections. - Status values. Top-level status: ok = every evaluated section answered; needs_review = partial answer, at least one section needs a person or a retry (read each section's status and the warnings); unavailable = no section could be answered (address not found, or every source failed); out_of_scope = no evaluated section applies at this address. Section status uses the same words plus not_covered (this area is not evaluated). str.status follows the two permit determinations: new_non_owner_occupied_permit.value (allowed, not_allowed, needs_review, out_of_scope, not_covered, unavailable) and owner_occupied_permit.value (possible, not_allowed, needs_review, out_of_scope, not_covered, unavailable). Both firm = ok, one firm and one not = needs_review, none usable = unavailable. Exception: an owner_occupied_permit of possible that rests only on an active city STR license (owner_occupied_permit.basis.kind active_city_license, Denver and Scottsdale) is not a firm yes, so str.status stays needs_review there. str.supporting_data_status appears when side lookups such as permit counts or building lists were incomplete. ## MCP - Endpoint: `POST https://ziplot.daderader.workers.dev/mcp` (Streamable HTTP, stateless, JSON responses, no key required). - Tools (read-only): `ziplot_deal_check` (args: `address` required, `bedrooms`, `value`, `include`) and `ziplot_deal_picture` (args: `address` and `price` required, plus the same optional deal inputs as /v1/deal-picture). `nashville_deal_check` is a legacy alias of ziplot_deal_check (same tool, kept for compatibility; deprecated: use ziplot_deal_check). - [Server card](https://ziplot.daderader.workers.dev/.well-known/mcp/server-card.json) - Client config: `{"mcpServers":{"ziplot":{"url":"https://ziplot.daderader.workers.dev/mcp"}}}` ## Docs - [API and MCP overview](https://ziplot.daderader.workers.dev/docs) - [Landing page and data sources](https://ziplot.daderader.workers.dev/) ## Data sources US Census Geocoder and ACS 5-year county tables; FEMA National Flood Hazard Layer; HUD FY2026 Small Area FMRs and FMRs (This product uses the HUD User Data API but is not endorsed or certified by HUD User.); city and county open data and STR codes for the covered markets. Verify with the city's short-term-rental office and the county assessor and treasurer.