ZipMarketData is distributed exclusively through RapidAPI — the world's largest API marketplace. This guide walks you through everything: creating your account, subscribing to a plan, authenticating requests, and making your first live API call in any language.

No credit card required to start The free tier includes 100 requests/day and gives you full access to all five endpoints. No credit card is required until you exceed the free tier limits.

Step 1 — Create a RapidAPI Account

  1. Go to RapidAPI and sign up

    Visit rapidapi.com and click Sign Up Free. You can register with GitHub, Google, or an email address.

  2. Search for ZipMarketData

    In the RapidAPI search bar, type ZipMarketData or real estate market data. Click the ZipMarketData listing.

  3. Choose a plan and subscribe

    Select the Basic (Free) plan to get started. Your subscription activates immediately and your API key is ready to use in seconds.

  4. Copy your API key

    On the ZipMarketData API page, click the Endpoints tab. Your unique X-RapidAPI-Key appears pre-filled in the code snippets on the right panel. Copy it now.

Step 2 — Understand Authentication

All protected endpoints require two headers when calling through RapidAPI. RapidAPI handles rate limiting, billing, and forwards your request to our servers with an internal validation secret — you never manage that secret yourself.

Header Value Required Notes
X-RapidAPI-Key Your unique key from RapidAPI dashboard Yes Never share or commit this to source control
X-RapidAPI-Host real-estate-market-data.p.rapidapi.com Yes Identifies which API you're calling
Keep your key secret Store your RapidAPI key in an environment variable, never hardcode it in source files. A leaked key can exhaust your quota or run up charges. If you suspect exposure, regenerate it immediately in the RapidAPI dashboard under My Apps → App Name → Security.

Step 3 — Make Your First Request

Let's fetch market statistics for ZIP code 78701 (downtown Austin, TX). All five examples below are equivalent — pick the language you're working in.

cURL
curl -s \ -H "X-RapidAPI-Key: YOUR_RAPIDAPI_KEY" \ -H "X-RapidAPI-Host: real-estate-market-data.p.rapidapi.com" \ "https://real-estate-market-data.p.rapidapi.com/market-stats?zip_code=78701"
Python (requests)
import requests import os API_KEY = os.environ["RAPIDAPI_KEY"] # never hardcode url = "https://real-estate-market-data.p.rapidapi.com/market-stats" headers = { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } response = requests.get(url, params={"zip_code": "78701"}, headers=headers, timeout=10) response.raise_for_status() data = response.json() print(f"Median sale price: ${data['median_sale_price']:,}") print(f"Days on market: {data['median_days_on_market']}") print(f"Market temp: {data['market_temperature']}") print(f"YoY change: {data['yoy_price_change']*100:.1f}%")
JavaScript (fetch)
const apiKey = process.env.RAPIDAPI_KEY; // load from environment const url = new URL("https://real-estate-market-data.p.rapidapi.com/market-stats"); url.searchParams.set("zip_code", "78701"); const response = await fetch(url, { headers: { "X-RapidAPI-Key": apiKey, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } }); if (!response.ok) throw new Error(`API error: ${response.status}`); const data = await response.json(); console.log(`Median price: $${data.median_sale_price.toLocaleString()}`); console.log(`Market temp: ${data.market_temperature}`);
Node.js (axios)
const axios = require("axios"); const API_KEY = process.env.RAPIDAPI_KEY; async function getMarketStats(zipCode) { const { data } = await axios.get( "https://real-estate-market-data.p.rapidapi.com/market-stats", { params: { zip_code: zipCode }, headers: { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" }, timeout: 10000 } ); return data; } getMarketStats("78701").then(console.log);
R (httr2)
library(httr2) api_key <- Sys.getenv("RAPIDAPI_KEY") resp <- request("https://real-estate-market-data.p.rapidapi.com/market-stats") |> req_url_query(zip_code = "78701") |> req_headers( "X-RapidAPI-Key" = api_key, "X-RapidAPI-Host" = "real-estate-market-data.p.rapidapi.com" ) |> req_perform() data <- resp_body_json(resp) cat(sprintf("Median price: $%s\n", format(data$median_sale_price, big.mark=",")))

Step 4 — Understand the Response

Every successful response is JSON. Here is an example /market-stats response for ZIP 78701. Fields are consistent across plans — there is no data truncation on the free tier.

{ "zip_code": "78701", "data_date": "2026-03", "median_sale_price": 685000, "median_list_price": 699000, "median_days_on_market": 22, "active_listings": 143, "new_listings_30d": 58, "price_reduced_pct": 0.19, "list_to_sale_ratio": 0.982, "mom_price_change": 0.0041, "yoy_price_change": 0.0612, "market_temperature": "Warm", "inventory_months": 1.8, "data_source": "redfin_mls" }

The data_source field tells you the origin of the data:

data_sourceMeaningCoverage
redfin_mls Real MLS data from Redfin's public dataset 28,000+ US ZIP codes
hud_fmr HUD Small Area Fair Market Rents (government) All ZIP codes with HUD data
census_acs US Census Bureau ACS income data 900+ metro areas
estimated Regional average with deterministic perturbation Any ZIP not yet in the dataset
About estimated responses When a ZIP code isn't in the live dataset yet, the API returns a clearly-labelled estimate anchored to real data from neighbouring ZIPs. The same ZIP always returns the same estimate (deterministic). Check data_source === "estimated" if you need to distinguish live vs. estimated values.

Available Endpoints

All five data endpoints are available to every subscriber. The /demo and /health endpoints require no authentication.

Endpoint Method Key Parameter What You Get
/market-stats GET zip_code Median price, DOM, inventory, YoY/MoM change
/price-history GET city + state 12 months of price & sales data by city
/rental-yield GET zip_code HUD rents, gross yield %, yield rating
/affordability GET metro Affordability index, price-to-income, DTI
/property-estimate GET zip_code Value estimate, cap rate, cash flow, CoC return
/demo GET zip_code Public demo — no auth required
/health GET API status and data freshness

Rate Limits and Plans

Limits are enforced by RapidAPI at the plan level. The API itself also enforces a hard cap of 120 requests/minute regardless of plan, with a burst allowance of 40 requests.

PlanRequests / DayPriceBest For
Basic (Free) 100 $0 Prototyping, evaluation, personal projects
Pro 1,000 See RapidAPI listing Small apps, dashboards, regular automation
Ultra 10,000 See RapidAPI listing Production apps, bulk screening tools
Mega 50,000+ See RapidAPI listing Enterprise, high-volume data pipelines
Tip: make 100 requests go a long way Cache responses locally for up to 24 hours — data updates once daily. Screening 100 ZIP codes per day is enough for most investment workflows. See the caching guide for implementation patterns in Python and Node.

Handling Errors

All errors return a JSON body with a detail field describing the problem. Here are the errors you'll encounter and how to handle them.

HTTP StatusCauseFix
400 Bad Request Invalid parameter (e.g. non-numeric ZIP, state code too long) Check parameter format — ZIP must be exactly 5 digits
403 Forbidden Missing or invalid API key Check your X-RapidAPI-Key header; regenerate key if needed
422 Unprocessable Entity Parameter validation failed (e.g. bedrooms outside 1–5) Read the detail field to identify the failing parameter
429 Too Many Requests Rate limit exceeded Implement exponential backoff; cache responses for 24h
500 Internal Server Error Transient server error Retry after 5–10 seconds; contact support if persistent

Robust error handling in Python

import requests, time, os API_KEY = os.environ["RAPIDAPI_KEY"] HEADERS = { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } BASE = "https://real-estate-market-data.p.rapidapi.com" def get_with_retry(endpoint, params, max_retries=3): """GET with exponential backoff for 429 and 5xx errors.""" for attempt in range(max_retries): try: resp = requests.get( f"{BASE}/{endpoint}", params=params, headers=HEADERS, timeout=10 ) if resp.status_code == 429: wait = 2 ** attempt # 1s, 2s, 4s print(f"Rate limited — waiting {wait}s...") time.sleep(wait) continue if resp.status_code >= 500: time.sleep(2 ** attempt) continue resp.raise_for_status() return resp.json() except requests.Timeout: if attempt == max_retries - 1: raise time.sleep(1) raise RuntimeError(f"Failed after {max_retries} retries") # Usage data = get_with_retry("market-stats", {"zip_code": "78701"}) print(data)

Using the RapidAPI Playground

Before writing any code, try the API directly in the RapidAPI web playground:

  1. Navigate to an endpoint

    On the ZipMarketData listing, click the Endpoints tab and select GET /market-stats from the left sidebar.

  2. Fill in the parameters

    In the Required Parameters panel, enter a 5-digit ZIP code (try 90210, 10001, or 60601).

  3. Click Test Endpoint

    Your API key is pre-filled. The live JSON response appears immediately in the right panel. The playground also generates ready-to-copy code in 10+ languages.

Environment Variable Setup

Never hardcode your API key. Here is how to store it safely across common environments:

Linux / macOS (.bashrc or .zshrc)
export RAPIDAPI_KEY="your_key_here" # then: source ~/.bashrc
Windows PowerShell
$env:RAPIDAPI_KEY = "your_key_here" # for persistence: [System.Environment]::SetEnvironmentVariable("RAPIDAPI_KEY","your_key","User")
.env file (Python — use python-dotenv)
# .env RAPIDAPI_KEY=your_key_here # in your script: from dotenv import load_dotenv load_dotenv() import os API_KEY = os.environ["RAPIDAPI_KEY"]
.env file (Node.js — use dotenv)
# .env RAPIDAPI_KEY=your_key_here // in your script: require("dotenv").config(); const API_KEY = process.env.RAPIDAPI_KEY;
GitHub Actions secret
# In your workflow YAML: env: RAPIDAPI_KEY: ${{ secrets.RAPIDAPI_KEY }} # Add RAPIDAPI_KEY to Settings → Secrets → Actions in your repo

What to Build Next

Now that authentication is working, explore what you can build: