Water Quality API

Programmatic access to water quality data for every U.S. ZIP code. Built on EPA SDWIS data, updated regularly.

What Data Is Available

The ZipCheckup API provides structured water quality and home safety data for 85,358+ U.S. ZIP codes. All data is sourced from EPA SDWIS, state environmental agencies, and public records.

Water Quality Scores Safety score (0-100), letter grade, and risk level for any ZIP code
Contaminant Data Detected contaminants, measured levels vs. EPA MCLs, health risk context
Violations EPA violations by water system, type, severity, and dates
State Summaries Average scores, top contaminants, and worst ZIPs per state
Rankings National rankings — best and worst ZIP codes by water quality score
Contaminant Reference Health effects, EPA limits, and sources for 100+ contaminants

Simple, Transparent Pricing

Start free. Upgrade when you need more.

Free

$0
No credit card required
  • 100 requests per day
  • All endpoints included
  • JSON responses
  • Rate limited (100/min)
  • Attribution required
  • Community support
Get Free API Key

Enterprise

Custom
For teams and organizations
  • Custom request limits
  • Dedicated support engineer
  • SLA with uptime guarantee
  • Custom data exports
  • Webhook notifications
  • Priority feature requests
Contact Us

Quick Start

cURL
Python
Node.js
R
# Get water quality data for ZIP 90210
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.zipcheckup.com/v1/zip/90210"

# Get safety score only
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.zipcheckup.com/v1/zip/90210/score"

# State summary
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.zipcheckup.com/v1/state/CA"
import requests

API_KEY = "YOUR_API_KEY"
BASE    = "https://api.zipcheckup.com/v1"

headers = {"X-API-Key": API_KEY}

# Full water quality data
r = requests.get(f"{BASE}/zip/90210", headers=headers)
data = r.json()

print(f"Score: {data['score']} ({data['grade']})")
print(f"Contaminants: {len(data['contaminants'])}")

# Top 50 worst ZIPs
r = requests.get(f"{BASE}/rankings?limit=50&order=asc", headers=headers)
for z in r.json()["rankings"]:
    print(f"{z['zip']}: {z['score']}")
const API_KEY = "YOUR_API_KEY";
const BASE    = "https://api.zipcheckup.com/v1";

const headers = { "X-API-Key": API_KEY };

// Full water quality data
const res = await fetch(`${BASE}/zip/90210`, { headers });
const data = await res.json();

console.log(`Score: ${data.score} (${data.grade})`);
console.log(`Contaminants: ${data.contaminants.length}`);

// State summary
const state = await (await fetch(`${BASE}/state/CA`, { headers })).json();
console.log(`CA avg score: ${state.avgScore}`);
library(httr2)
library(jsonlite)

api_key <- "YOUR_API_KEY"
base    <- "https://api.zipcheckup.com/v1"

# Full water quality data
resp <- request(paste0(base, "/zip/90210")) |>
  req_headers("X-API-Key" = api_key) |>
  req_perform()

data <- resp |> resp_body_json()
cat(sprintf("Score: %s (%s)\n", data$score, data$grade))

# Rankings as data frame
rankings <- request(paste0(base, "/rankings?limit=50&order=asc")) |>
  req_headers("X-API-Key" = api_key) |>
  req_perform() |>
  resp_body_json()

df <- do.call(rbind, lapply(rankings$rankings, as.data.frame))
head(df)

Get Your Free API Key

Enter your email and we'll send your API key instantly. No credit card required.

Need More Than 100 Requests/Day?

Tell us your use case and we'll work with you on a plan that fits.

Ready to integrate? Read the full documentation.

View API Documentation

Frequently Asked Questions

What data does the API include?

The API provides water quality scores, detected contaminants with measured levels vs. EPA limits, violation history, state-level summaries, national rankings, and contaminant reference data. All sourced from EPA SDWIS and state environmental agencies.

What are the rate limits?

Free tier: 100 requests per day, max 100 per minute. Pro tier: 10,000 requests per day, max 1,000 per minute. Enterprise: custom limits based on your needs.

What does "attribution required" mean on the Free tier?

If you display ZipCheckup data publicly (on a website, in an app, in a report), include a link back to zipcheckup.com. Example: "Data from ZipCheckup." Pro and Enterprise tiers do not require attribution.

How often is the data updated?

We refresh data from EPA SDWIS regularly. The current dataset date is included in every API response as the dataDate field.

Can I cancel my Pro subscription anytime?

Yes. Pro is billed monthly with no contract. Cancel anytime and your access continues until the end of the billing period. Your API key reverts to Free tier limits after that.

What formats are supported?

All responses are JSON by default. Pro tier also supports CSV export via the format=csv query parameter.

Do you offer bulk endpoints?

Yes, Pro and Enterprise tiers can query up to 100 ZIP codes in a single request via POST /v1/bulk/zip. See the API documentation for details.

I need custom data or higher limits. Who do I contact?

Email [email protected] and we'll set up an Enterprise plan tailored to your needs.