{"openapi":"3.0.0","info":{"title":"GeoClear API","version":"1.0.0","description":"US address intelligence API — 120M+ addresses enriched with flood zones, risk scores, census data, and more. Start free at geoclear.io/portal.html.","contact":{"name":"GeoClear Support","url":"https://geoclear.io","email":"support@geoclear.io"},"license":{"name":"Commercial","url":"https://geoclear.io/terms"}},"servers":[{"url":"https://geoclear.io","description":"Production"},{"url":"http://localhost:4001","description":"Local dev"}],"tags":[{"name":"Health","description":"Service health checks"},{"name":"Address","description":"Address lookup, autocomplete, bulk, and proximity"},{"name":"Enrich","description":"Location enrichment — flood zone, risk scores, census"},{"name":"Account","description":"API key signup and usage"}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"Your GeoClear API key. Get one free at https://geoclear.io/portal.html"}},"schemas":{"HealthResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"string","example":"healthy"},"addresses":{"type":"number","example":120000000},"uptime":{"type":"number","example":3600}},"required":["ok","status","addresses","uptime"]},"AddressListResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"count":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AddressResult"}}},"required":["ok","count","data"]},"AddressResult":{"type":"object","properties":{"nad_uuid":{"type":"string","example":"a1b2c3d4-0000-0000-0000-000000000000"},"full_address":{"type":"string","example":"1600 PENNSYLVANIA AVE NW, WASHINGTON, DC 20500"},"add_number":{"type":"string","example":"1600","description":"Street number"},"st_name":{"type":"string","example":"PENNSYLVANIA AVE NW","description":"Street name (NAD uppercase format)"},"st_pos_typ":{"type":"string","nullable":true,"example":"NW"},"inc_muni":{"type":"string","nullable":true,"example":"WASHINGTON","description":"Incorporated municipality (city)"},"post_city":{"type":"string","nullable":true,"example":"WASHINGTON","description":"USPS post city"},"display_city":{"type":"string","nullable":true,"example":"Washington","description":"Best display name for city"},"county":{"type":"string","nullable":true,"example":"District of Columbia"},"state":{"type":"string","example":"DC"},"zip_code":{"type":"string","nullable":true,"example":"20500"},"latitude":{"type":"number","nullable":true,"example":38.8977},"longitude":{"type":"number","nullable":true,"example":-77.0365},"confidence":{"type":"number","example":95,"description":"0–100 reliability score"},"match_type":{"type":"string","enum":["exact","number+street","street+location","street","location"],"example":"exact"},"fips":{"type":"string","nullable":true,"example":"11001","description":"5-digit county FIPS"},"timezone":{"type":"string","nullable":true,"example":"America/New_York"},"residential":{"type":"string","nullable":true,"example":"residential"}},"required":["nad_uuid","full_address","add_number","st_name","state","confidence","match_type"]},"Error":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["ok","error"]},"SuggestResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"count":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SuggestItem"}}},"required":["ok","count","data"]},"SuggestItem":{"type":"object","properties":{"full_address":{"type":"string"},"inc_muni":{"type":"string","nullable":true},"post_city":{"type":"string","nullable":true},"state":{"type":"string"},"zip_code":{"type":"string","nullable":true}},"required":["full_address","state"]},"BulkResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"count":{"type":"number"},"data":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/AddressResult"},{"type":"object","properties":{"verified":{"type":"boolean","enum":[false]}},"required":["verified"]}]}}},"required":["ok","count","data"]},"BulkItem":{"type":"object","properties":{"street":{"type":"string","example":"1600 Pennsylvania Ave NW"},"number":{"type":"string","example":"1600"},"city":{"type":"string","example":"Washington"},"state":{"type":"string","example":"DC"},"zip":{"type":"string","example":"20500"}},"required":["street"]},"CoverageResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"count":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/CoverageState"}}},"required":["ok","count","data"]},"CoverageState":{"type":"object","properties":{"state":{"type":"string","example":"CA"},"count":{"type":"number","example":14000000}},"required":["state","count"]},"EnrichResult":{"type":"object","properties":{"fips":{"type":"string","nullable":true,"example":"11001"},"timezone":{"type":"string","nullable":true,"example":"America/New_York"},"flood_zone":{"type":"string","nullable":true,"example":"X","description":"FEMA flood zone code"},"flood_zone_desc":{"type":"string","nullable":true,"example":"Minimal flood risk"},"flood_sfha":{"type":"boolean","nullable":true,"example":false,"description":"In Special Flood Hazard Area"},"elevation_ft":{"type":"number","nullable":true,"example":42},"wildfire_risk":{"type":"string","nullable":true,"example":"Low"},"wildfire_score":{"type":"number","nullable":true,"example":12},"earthquake_risk":{"type":"string","nullable":true,"example":"Low"},"drought_risk":{"type":"string","nullable":true,"example":"None"},"nri_risk":{"type":"string","nullable":true,"example":"Relatively Low"}}},"RiskResult":{"type":"object","properties":{"ok":{"type":"boolean"},"nad_uuid":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"flood":{"$ref":"#/components/schemas/FloodData"},"wildfire":{"$ref":"#/components/schemas/WildfireData"},"earthquake":{"$ref":"#/components/schemas/EarthquakeData"},"drought":{"type":"object","nullable":true,"properties":{"risk_class":{"type":"string","nullable":true}}},"nri":{"$ref":"#/components/schemas/NriData"}},"required":["ok"]},"FloodData":{"type":"object","nullable":true,"properties":{"zone":{"type":"string","nullable":true,"example":"AE"},"description":{"type":"string","nullable":true,"example":"High risk flood zone"},"in_sfha":{"type":"boolean","nullable":true,"example":true},"panel_number":{"type":"string","nullable":true},"effective_date":{"type":"string","nullable":true}}},"WildfireData":{"type":"object","nullable":true,"properties":{"risk_class":{"type":"string","nullable":true,"example":"Very High"},"score":{"type":"number","nullable":true,"example":87},"percentile":{"type":"number","nullable":true}}},"EarthquakeData":{"type":"object","nullable":true,"properties":{"risk_class":{"type":"string","nullable":true,"example":"Moderate"},"pga":{"type":"number","nullable":true,"example":0.42,"description":"Peak Ground Acceleration (g)"}}},"NriData":{"type":"object","nullable":true,"properties":{"risk_rating":{"type":"string","nullable":true,"example":"Relatively High"},"composite_score":{"type":"number","nullable":true}}},"SignupResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object","properties":{"api_key":{"type":"string","example":"gc_live_..."},"tier":{"type":"string","example":"free"},"email":{"type":"string","example":"dev@example.com"},"limits":{"$ref":"#/components/schemas/Limits"}},"required":["api_key","tier","email","limits"]}},"required":["ok","data"]},"Limits":{"type":"object","properties":{"req_per_day":{"type":"number","example":50000},"req_per_min":{"type":"number","example":60},"enrichment":{"type":"boolean","example":true}},"required":["req_per_day","req_per_min","enrichment"]},"MeResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object","properties":{"tier":{"type":"string","example":"starter"},"email":{"type":"string","example":"user@example.com"},"limits":{"$ref":"#/components/schemas/Limits"},"requests_today":{"type":"number","example":42},"requests_total":{"type":"number","example":1234},"created_at":{"type":"string","nullable":true},"usage_history":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"count":{"type":"number"}},"required":["date","count"]}}},"required":["tier","email","limits","requests_today","requests_total","usage_history"]}},"required":["ok","data"]}},"parameters":{}},"paths":{"/api/health":{"get":{"security":[],"tags":["Health"],"summary":"Health check","description":"Returns service health. No authentication required.","operationId":"getHealth","responses":{"200":{"description":"Service healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/api/ping":{"get":{"security":[],"tags":["Health"],"summary":"Ping","description":"Lightweight liveness check.","operationId":"ping","responses":{"200":{"description":"Pong","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/api/address":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Lookup an address","description":"Returns a verified, normalized address record with computed fields (confidence, match_type, fips, timezone). Requires API key. Flood/risk fields are not included — use /api/enrich or /v1/address/risk for those.","operationId":"lookupAddress","parameters":[{"schema":{"type":"string","example":"1600 Pennsylvania Ave NW"},"required":false,"name":"street","in":"query"},{"schema":{"type":"string","example":"1600"},"required":false,"name":"number","in":"query"},{"schema":{"type":"string","example":"Washington"},"required":false,"name":"city","in":"query"},{"schema":{"type":"string","example":"DC","description":"2-letter state code"},"required":false,"description":"2-letter state code","name":"state","in":"query"},{"schema":{"type":"string","example":"20500"},"required":false,"name":"zip","in":"query"},{"schema":{"type":"string","example":"10","description":"Max results (1–50)"},"required":false,"description":"Max results (1–50)","name":"limit","in":"query"},{"schema":{"type":"string","example":"false"},"required":false,"name":"fuzzy","in":"query"}],"responses":{"200":{"description":"Address results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressListResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/suggest":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Autocomplete suggestions","description":"Returns up to 10 address suggestions for a partial input. Ideal for search-as-you-type.","operationId":"suggestAddress","parameters":[{"schema":{"type":"string","example":"1600 Penn","description":"Partial address (min 2 chars)"},"required":true,"description":"Partial address (min 2 chars)","name":"q","in":"query"},{"schema":{"type":"string","example":"DC"},"required":false,"name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"zip","in":"query"},{"schema":{"type":"string","example":"5"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Suggestions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/address/bulk":{"post":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Bulk address lookup (JSON)","description":"Look up up to 1,000 addresses in a single request. Returns results in input order.","operationId":"bulkLookup","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BulkItem"},"maxItems":1000}}}},"responses":{"200":{"description":"Bulk results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/address/csv":{"post":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Bulk address lookup (CSV)","description":"Upload a CSV file with address columns. Header row required. Max 5,000 rows. Returns CSV with enrichment columns appended.","operationId":"bulkLookupCsv","requestBody":{"required":true,"content":{"text/csv":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Enriched CSV","content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/near":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Nearby addresses","description":"Returns addresses within a radius of a lat/lon point, sorted by distance.","operationId":"nearbyAddresses","parameters":[{"schema":{"type":"string","example":"38.8977"},"required":true,"name":"lat","in":"query"},{"schema":{"type":"string","example":"-77.0365"},"required":true,"name":"lon","in":"query"},{"schema":{"type":"string","example":"0.25","description":"Radius in miles (max 5)"},"required":false,"description":"Radius in miles (max 5)","name":"radius","in":"query"},{"schema":{"type":"string","example":"10"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Nearby results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressListResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/zip/{zip}":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"ZIP code lookup","description":"Returns city, state, county, and coordinates for a 5-digit ZIP code.","operationId":"zipLookup","responses":{"200":{"description":"ZIP data","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object","properties":{},"additionalProperties":{"nullable":true}}},"required":["ok","data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/coverage":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Coverage statistics","description":"Returns address counts per state. Cached 6 hours.","operationId":"getCoverage","responses":{"200":{"description":"Coverage data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/stats":{"get":{"security":[{"ApiKey":[]}],"tags":["Address"],"summary":"Database statistics","description":"Returns total address count and DB metadata.","operationId":"getStats","responses":{"200":{"description":"Stats","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"type":"object","properties":{},"additionalProperties":{"nullable":true}}},"required":["ok","data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/enrich":{"get":{"security":[{"ApiKey":[]}],"tags":["Enrich"],"summary":"Enrich a lat/lon point","description":"Returns flood zone, risk scores (wildfire, earthquake, drought, NRI), census data, FAA airspace, and timezone for any US coordinate. This endpoint returns the flood/risk data that is NOT in /api/address.","operationId":"enrichPoint","parameters":[{"schema":{"type":"string","example":"38.8977"},"required":true,"name":"lat","in":"query"},{"schema":{"type":"string","example":"-77.0365"},"required":true,"name":"lon","in":"query"}],"responses":{"200":{"description":"Enrichment data","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"data":{"$ref":"#/components/schemas/EnrichResult"}},"required":["ok","data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/address/risk":{"get":{"security":[{"ApiKey":[]}],"tags":["Enrich"],"summary":"Full risk assessment for an address","description":"Geocodes the address and returns comprehensive risk data — FEMA flood zone (with panel number and SFHA flag), wildfire score (USGS), earthquake PGA, drought classification, and FEMA NRI 18-hazard composite.","operationId":"addressRisk","parameters":[{"schema":{"type":"string","example":"123 Main St"},"required":false,"name":"street","in":"query"},{"schema":{"type":"string"},"required":false,"name":"city","in":"query"},{"schema":{"type":"string","example":"CA"},"required":false,"name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"zip","in":"query"},{"schema":{"type":"string"},"required":false,"name":"nad_uuid","in":"query"}],"responses":{"200":{"description":"Risk assessment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskResult"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/signup":{"post":{"security":[],"tags":["Account"],"summary":"Get a free API key","description":"Creates a free-tier key (10K lookups/month). No credit card required. One key per email address.","operationId":"signup","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"dev@example.com"}},"required":["email"]}}}},"responses":{"201":{"description":"Key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me":{"get":{"security":[{"ApiKey":[]}],"tags":["Account"],"summary":"Key info and usage","description":"Returns tier, rate limits, usage counters, and optional daily usage history for the authenticated key.","operationId":"getMe","parameters":[{"schema":{"type":"string","example":"30","description":"Days of usage history (max 90)"},"required":false,"description":"Days of usage history (max 90)","name":"history_days","in":"query"}],"responses":{"200":{"description":"Key info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}