{"openapi":"3.1.0","info":{"title":"PermitStack","description":"\n## PermitStack Building Permit API\n\nAccess 58M+ building permits across 552 active U.S. jurisdictions (plus 51 historical archives), updated daily from official open data portals.\n\n### Getting started\n1. Sign up at [permit-stack.com](https://permit-stack.com/#pricing) for a free API key (100 req/day)\n2. Pass your key as `X-API-Key` header on every request\n3. See the `/v1/permits/search` endpoint to get started\n\n### Rate limits\nTier       | Requests/min | Requests/day\n-----------|--------------|-------------\nFree       | 30           | 100\nIndie      | 30           | 1,000\nHobbyist   | 30           | 2,500\nDeveloper  | 60           | 10,000\nStartup    | 200          | 100,000\nGrowth     | 500          | 500,000\n\n### Support\nsupport@permit-stack.com\n","termsOfService":"https://permit-stack.com/terms.html","contact":{"name":"PermitStack Support","url":"https://permit-stack.com/","email":"support@permit-stack.com"},"license":{"name":"Commercial -- see Terms","url":"https://permit-stack.com/terms.html"},"version":"1.0.0"},"servers":[{"url":"https://api.permit-stack.com","description":"Production"}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health Check","operationId":"health_check","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/stats":{"get":{"tags":["Health"],"summary":"Public Stats","description":"Public stats endpoint — no auth required.\nReturns aggregate coverage numbers for marketing/transparency.\nCached server-side for 30 minutes.","operationId":"public_stats","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/permits/search":{"get":{"tags":["Permits"],"summary":"Search Permits","operationId":"search_permits","security":[{"ApiKey":[]}],"parameters":[{"name":"zip_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"5-digit ZIP code","title":"Zip Code"},"description":"5-digit ZIP code"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City name","title":"City"},"description":"City name"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"2-letter state code","title":"State"},"description":"2-letter state code"},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction name (e.g. 'Wake County', 'Tacoma') or partial match","title":"Jurisdiction"},"description":"Jurisdiction name (e.g. 'Wake County', 'Tacoma') or partial match"},{"name":"address","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Street address, partial + case-insensitive (e.g. '1600 Pennsylvania') — indexed, fast","title":"Address"},"description":"Street address, partial + case-insensitive (e.g. '1600 Pennsylvania') — indexed, fast"},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Latitude for radius search","title":"Lat"},"description":"Latitude for radius search"},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Longitude for radius search","title":"Lng"},"description":"Longitude for radius search"},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":50,"description":"Radius in miles (used with lat/lng)","default":5.0,"title":"Radius Miles"},"description":"Radius in miles (used with lat/lng)"},{"name":"bbox","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Map-viewport bounding box 'minLng,minLat,maxLng,maxLat'. Returns permits whose location falls inside the box (geocoded permits only).","title":"Bbox"},"description":"Map-viewport bounding box 'minLng,minLat,maxLng,maxLat'. Returns permits whose location falls inside the box (geocoded permits only)."},{"name":"polygon","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"A drawn area as a GeoJSON Polygon geometry (URL-encoded), e.g. {\"type\":\"Polygon\",\"coordinates\":[[[lng,lat],...]]}. Returns permits inside the polygon (geocoded permits only).","title":"Polygon"},"description":"A drawn area as a GeoJSON Polygon geometry (URL-encoded), e.g. {\"type\":\"Polygon\",\"coordinates\":[[[lng,lat],...]]}. Returns permits inside the polygon (geocoded permits only)."},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Permit category (e.g. solar, SOLAR, roofing, hvac — case insensitive)","title":"Category"},"description":"Permit category (e.g. solar, SOLAR, roofing, hvac — case insensitive)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/PermitStatus"},{"type":"null"}],"description":"Permit status (e.g. issued, filed, final)","title":"Status"},"description":"Permit status (e.g. issued, filed, final)"},{"name":"property_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/PropertyType"},{"type":"null"}],"description":"Property type (e.g. residential, commercial)","title":"Property Type"},"description":"Property type (e.g. residential, commercial)"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag","title":"Tag"},"description":"Filter by tag"},{"name":"record_kind","in":"query","required":false,"schema":{"type":"string","description":"Record kind: 'permit' (default, building permits only), 'contractor', 'tag', 'non_building', 'admin', or 'all'","default":"permit","title":"Record Kind"},"description":"Record kind: 'permit' (default, building permits only), 'contractor', 'tag', 'non_building', 'admin', or 'all'"},{"name":"filed_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Filed on or after this date","title":"Filed After"},"description":"Filed on or after this date"},{"name":"filed_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Filed on or before this date","title":"Filed Before"},"description":"Filed on or before this date"},{"name":"issued_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Issued on or after this date","title":"Issued After"},"description":"Issued on or after this date"},{"name":"issued_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Issued on or before this date","title":"Issued Before"},"description":"Issued on or before this date"},{"name":"date_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"On or after this date, matched against whichever date a record has (issued, else filed). Use this when a source populates only one of issued/filed — e.g. issued-only feeds vs filed-only feeds.","title":"Date After"},"description":"On or after this date, matched against whichever date a record has (issued, else filed). Use this when a source populates only one of issued/filed — e.g. issued-only feeds vs filed-only feeds."},{"name":"date_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"On or before this date, matched against whichever date a record has (issued, else filed).","title":"Date Before"},"description":"On or before this date, matched against whichever date a record has (issued, else filed)."},{"name":"parcel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Parcel number / APN / folio (formatting ignored). Returns permits on that parcel where the source publishes one.","title":"Parcel"},"description":"Parcel number / APN / folio (formatting ignored). Returns permits on that parcel where the source publishes one."},{"name":"min_value","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum estimated value","title":"Min Value"},"description":"Minimum estimated value"},{"name":"max_value","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Maximum estimated value","title":"Max Value"},"description":"Maximum estimated value"},{"name":"min_solar_kw","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum extracted solar system size (kW DC)","title":"Min Solar Kw"},"description":"Minimum extracted solar system size (kW DC)"},{"name":"max_solar_kw","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Maximum extracted solar system size (kW DC)","title":"Max Solar Kw"},"description":"Maximum extracted solar system size (kW DC)"},{"name":"min_sqft","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum square footage mentioned (from enrichment)","title":"Min Sqft"},"description":"Minimum square footage mentioned (from enrichment)"},{"name":"has_enrichment","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Only permits that have (true) or lack (false) LLM enrichment","title":"Has Enrichment"},"description":"Only permits that have (true) or lack (false) LLM enrichment"},{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on the enriched work scope","title":"Scope"},"description":"Substring match on the enriched work scope"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Case-insensitive substring match across description, address, and permit number","title":"Q"},"description":"Case-insensitive substring match across description, address, and permit number"},{"name":"contractor_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Contractor name (partial match)","title":"Contractor Name"},"description":"Contractor name (partial match)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/permits/export":{"get":{"tags":["Permits"],"summary":"Export Permits","description":"Export permits matching filters as CSV. Tier-gated row limits.","operationId":"export_permits","security":[{"ApiKey":[]}],"parameters":[{"name":"zip_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code"}},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/PermitStatus"},{"type":"null"}],"title":"Status"}},{"name":"property_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/PropertyType"},{"type":"null"}],"title":"Property Type"}},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"}},{"name":"record_kind","in":"query","required":false,"schema":{"type":"string","default":"permit","title":"Record Kind"}},{"name":"filed_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Filed After"}},{"name":"filed_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Filed Before"}},{"name":"issued_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Issued After"}},{"name":"issued_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Issued Before"}},{"name":"date_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"On or after this date, matched against whichever date a record has (issued, else filed).","title":"Date After"},"description":"On or after this date, matched against whichever date a record has (issued, else filed)."},{"name":"date_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"On or before this date, matched against whichever date a record has (issued, else filed).","title":"Date Before"},"description":"On or before this date, matched against whichever date a record has (issued, else filed)."},{"name":"parcel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Parcel number / APN / folio (formatting ignored).","title":"Parcel"},"description":"Parcel number / APN / folio (formatting ignored)."},{"name":"min_value","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Value"}},{"name":"max_value","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Value"}},{"name":"min_solar_kw","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Solar Kw"}},{"name":"max_solar_kw","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Solar Kw"}},{"name":"min_sqft","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Sqft"}},{"name":"has_enrichment","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Enrichment"}},{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"contractor_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contractor Name"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000000,"minimum":1,"default":1000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/permits/events":{"get":{"tags":["Permits"],"summary":"List Permit Events","description":"Queryable feed of permit status/date transitions (new_permit, status_change,\nissued, completed, expired), built from a daily-ingest diff. A real-time,\nhistorical, filter-scoped change feed no competitor offers below enterprise —\npair it with a webhook to be alerted the moment a matching permit changes status.","operationId":"list_permit_events","security":[{"ApiKey":[]}],"parameters":[{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by event type: new_permit, status_change, issued, completed, expired","title":"Event Type"},"description":"Filter by event type: new_permit, status_change, issued, completed, expired"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Permit category (e.g. solar, battery)","title":"Category"},"description":"Permit category (e.g. solar, battery)"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City name","title":"City"},"description":"City name"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"2-letter state code","title":"State"},"description":"2-letter state code"},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction name (partial)","title":"Jurisdiction"},"description":"Jurisdiction name (partial)"},{"name":"permit_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Events for a single permit id","title":"Permit Id"},"description":"Events for a single permit id"},{"name":"detected_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events detected on/after this UTC timestamp (ISO 8601)","title":"Detected After"},"description":"Only events detected on/after this UTC timestamp (ISO 8601)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitEventsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/permits/{permit_id}":{"get":{"tags":["Permits"],"summary":"Get Permit","description":"Get full details for a single permit.","operationId":"get_permit","security":[{"ApiKey":[]}],"parameters":[{"name":"permit_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Permit Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/permits/address/{address}":{"get":{"tags":["Permits"],"summary":"Get Permits By Address","description":"Get all permits for a specific address (partial match).","operationId":"get_permits_by_address","security":[{"ApiKey":[]}],"parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/permits/stats/coverage":{"get":{"tags":["Permits"],"summary":"Get Coverage Stats","description":"Get coverage statistics — total permits, jurisdictions, and breakdown by city.","operationId":"get_coverage_stats","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/plays":{"get":{"tags":["Permits"],"summary":"List Plays","description":"List available trade plays and their parameters.","operationId":"list_plays","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/plays/battery-retrofit-candidates":{"get":{"tags":["Permits"],"summary":"Battery Retrofit Candidates","description":"Solar permits aged between min/max years whose address has NO battery permit\non file — the storage-retrofit lead list. Requires a location filter.","operationId":"battery_retrofit_candidates","security":[{"ApiKey":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"2-letter state code","title":"State"},"description":"2-letter state code"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City name","title":"City"},"description":"City name"},{"name":"zip_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"5-digit ZIP","title":"Zip Code"},"description":"5-digit ZIP"},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction name (partial)","title":"Jurisdiction"},"description":"Jurisdiction name (partial)"},{"name":"min_age_years","in":"query","required":false,"schema":{"type":"number","maximum":30,"minimum":0,"description":"Minimum age of the PV permit, in years","default":2,"title":"Min Age Years"},"description":"Minimum age of the PV permit, in years"},{"name":"max_age_years","in":"query","required":false,"schema":{"type":"number","maximum":40,"minimum":0,"description":"Maximum age of the PV permit, in years","default":7,"title":"Max Age Years"},"description":"Maximum age of the PV permit, in years"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/plays/orphan-recovery":{"get":{"tags":["Permits"],"summary":"Orphan Recovery","description":"PV permits whose installer (contractor, applicant, or owner) matches `installer`\nin a territory — a named competitor's customer base. Requires a location filter.","operationId":"orphan_recovery","security":[{"ApiKey":[]}],"parameters":[{"name":"installer","in":"query","required":true,"schema":{"type":"string","minLength":2,"description":"Installer name to match (contractor/applicant/owner)","title":"Installer"},"description":"Installer name to match (contractor/applicant/owner)"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"2-letter state code","title":"State"},"description":"2-letter state code"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City name","title":"City"},"description":"City name"},{"name":"zip_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"5-digit ZIP","title":"Zip Code"},"description":"5-digit ZIP"},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Jurisdiction name (partial)","title":"Jurisdiction"},"description":"Jurisdiction name (partial)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contractors/search":{"get":{"tags":["Contractors"],"summary":"Search Contractors","description":"Search contractors by name, location, or specialty, ranked by activity score.","operationId":"search_contractors","security":[{"ApiKey":[]}],"parameters":[{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Contractor name (partial match)","title":"Name"},"description":"Contractor name (partial match)"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"2-letter state code","title":"State"},"description":"2-letter state code"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City name","title":"City"},"description":"City name"},{"name":"specialty","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Specialty tag (e.g. solar, roofing, hvac)","title":"Specialty"},"description":"Specialty tag (e.g. solar, roofing, hvac)"},{"name":"min_permits","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Minimum total permits","title":"Min Permits"},"description":"Minimum total permits"},{"name":"min_score","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":0},{"type":"null"}],"description":"Minimum contractor activity score (0-100)","title":"Min Score"},"description":"Minimum contractor activity score (0-100)"},{"name":"sort","in":"query","required":false,"schema":{"type":"string","description":"Sort order: 'score' (default), 'permits', or 'recent'","default":"score","title":"Sort"},"description":"Sort order: 'score' (default), 'permits', or 'recent'"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractorSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contractors/{contractor_id}":{"get":{"tags":["Contractors"],"summary":"Get Contractor","description":"Get a contractor's full profile with permit stats.","operationId":"get_contractor","security":[{"ApiKey":[]}],"parameters":[{"name":"contractor_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contractor Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractorProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contractors/{contractor_id}/permits":{"get":{"tags":["Contractors"],"summary":"Get Contractor Permits","description":"Get all permits associated with a contractor.","operationId":"get_contractor_permits","security":[{"ApiKey":[]}],"parameters":[{"name":"contractor_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contractor Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property/history":{"get":{"tags":["Property History"],"summary":"Get Property History","description":"Complete construction history + property profile for an address.\n\nMatches every permit whose street address contains the supplied address;\npass `city`/`state`/`zip` to disambiguate the same street number across\nmetros. Returns a derived profile (permit timeline, category breakdown,\ncontractors, and underwriting signals such as solar/roof/pool age) plus\nthe paginated permit records.\n\nAn address with **no** permits returns `found: false` with an empty\nprofile (HTTP 200) — a clean property is a valid, useful answer, not an\nerror.","operationId":"get_property_history","security":[{"ApiKey":[]}],"parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string","minLength":3,"description":"Street address to look up (e.g. '123 Main St')","title":"Address"},"description":"Street address to look up (e.g. '123 Main St')"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional city to disambiguate identical street addresses","title":"City"},"description":"Optional city to disambiguate identical street addresses"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":2,"maxLength":2},{"type":"null"}],"description":"Optional 2-letter state code","title":"State"},"description":"Optional 2-letter state code"},{"name":"zip","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":3,"maxLength":10},{"type":"null"}],"description":"Optional ZIP (prefix-matched)","title":"Zip"},"description":"Optional ZIP (prefix-matched)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property/by-parcel":{"get":{"tags":["Property History"],"summary":"Get Property By Parcel","description":"Complete construction history + property profile for a parcel / APN.\n\nLooks up every permit whose source parcel number matches `parcel`, with\nformatting ignored, so an APN from a county appraiser matches regardless of how\nthe permit feed punctuates it. Pass `state` to disambiguate the same parcel\nnumber used by different counties. Returns the same profile shape as /history\n(timeline, category breakdown, contractors, and roof/solar/HVAC age signals).\n\nParcel coverage spans the county / appraiser / GIS sources that publish a parcel\nid; a handful of Accela-sourced jurisdictions omit parcel in their public export\nand won't match here (use /property/history by address for those).\n\nA parcel with **no** permits returns `found: false` (HTTP 200), not an error.","operationId":"get_property_by_parcel","security":[{"ApiKey":[]}],"parameters":[{"name":"parcel","in":"query","required":true,"schema":{"type":"string","minLength":3,"description":"Parcel number / APN / folio. Formatting is ignored — dashes, dots and spaces are stripped before matching.","title":"Parcel"},"description":"Parcel number / APN / folio. Formatting is ignored — dashes, dots and spaces are stripped before matching."},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":2,"maxLength":2},{"type":"null"}],"description":"Optional 2-letter state to disambiguate the same parcel number across counties","title":"State"},"description":"Optional 2-letter state to disambiguate the same parcel number across counties"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/":{"get":{"tags":["Webhooks"],"summary":"List Webhooks","description":"List all your registered webhooks.","operationId":"list_webhooks","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]},"post":{"tags":["Webhooks"],"summary":"Create Webhook","description":"Register a webhook to be notified when new permits match your filters.\n\nAvailable on Developer ($49/mo) and above. Maximum 10 webhooks per API key.\nWhen a new permit matches your filters, we'll POST the permit data as JSON to your URL.","operationId":"create_webhook","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"ApiKey":[]}]}},"/v1/webhooks/{webhook_id}":{"delete":{"tags":["Webhooks"],"summary":"Delete Webhook","description":"Delete a webhook.","operationId":"delete_webhook","security":[{"ApiKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{webhook_id}/test":{"post":{"tags":["Webhooks"],"summary":"Test Webhook","description":"Send a test event to a webhook URL.\n\nUseful for verifying your webhook endpoint is reachable and signature \nvalidation works. Sends a fake permit payload with event=permit.test.","operationId":"test_webhook","security":[{"ApiKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{webhook_id}/secret":{"get":{"tags":["Webhooks"],"summary":"Get Webhook Secret","description":"Retrieve your webhook signing secret. Use this to validate signatures.\n\nThe X-PermitStack-Signature header on incoming webhook requests is the\nHMAC-SHA256 of the request body using this secret. Verify before \nprocessing to ensure the request came from PermitStack.","operationId":"get_webhook_secret","security":[{"ApiKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","description":"Your PermitStack API key. Get one at permit-stack.com/#pricing","in":"header","name":"X-API-Key"}},"schemas":{"ContractorProfile":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"license_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Number"},"license_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License State"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"total_permits":{"type":"integer","title":"Total Permits"},"first_permit_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"First Permit Date"},"last_permit_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Permit Date"},"specialties":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specialties"},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score"},"is_business":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Business"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code"},"recent_categories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Recent Categories"},"avg_project_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Project Value"}},"type":"object","required":["id","name","license_number","license_state","city","state","total_permits","first_permit_date","last_permit_date","specialties","phone","email","address","zip_code"],"title":"ContractorProfile"},"ContractorSearchResponse":{"properties":{"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"},"results":{"items":{"$ref":"#/components/schemas/ContractorSummary"},"type":"array","title":"Results"}},"type":"object","required":["total","page","per_page","results"],"title":"ContractorSearchResponse"},"ContractorSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"license_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Number"},"license_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License State"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"total_permits":{"type":"integer","title":"Total Permits"},"first_permit_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"First Permit Date"},"last_permit_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Permit Date"},"specialties":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specialties"},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score"},"is_business":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Business"}},"type":"object","required":["id","name","license_number","license_state","city","state","total_permits","first_permit_date","last_permit_date","specialties"],"title":"ContractorSummary"},"CoverageConfidence":{"properties":{"confidence":{"type":"string","title":"Confidence"},"covered":{"type":"boolean","title":"Covered"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"data_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Status"},"jurisdiction_permit_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Jurisdiction Permit Count"},"note":{"type":"string","title":"Note"}},"type":"object","required":["confidence","covered","note"],"title":"CoverageConfidence","description":"Honest read on whether a `found: false` is meaningful or just missing data.\n\nThe wedge competitors won't ship: a 'no permit on record' is only useful if we\nactually cover that jurisdiction. We say so explicitly so an automated (e.g.\nunderwriting) workflow can tell UNKNOWN apart from genuinely-no-work."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PermitDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"permit_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permit Number"},"status":{"type":"string","title":"Status"},"category":{"type":"string","title":"Category"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"property_type":{"type":"string","title":"Property Type"},"address_street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Street"},"address_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address City"},"address_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address State"},"address_zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Zip"},"description_raw":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Raw"},"estimated_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Value"},"date_filed":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Filed"},"date_issued":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Issued"},"date_completed":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Completed"},"contractor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contractor Name"},"jurisdiction_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Name"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"enrichment":{"anyOf":[{"$ref":"#/components/schemas/PermitEnrichment"},{"type":"null"}]},"record_kind":{"type":"string","title":"Record Kind","default":"permit"},"date_expired":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Expired"},"fee_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fee Amount","description":"Permit/inspection fee. Frequently null — most open-data feeds do not publish fee data."},"stories":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stories"},"units":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Units"},"square_footage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Square Footage"},"applicant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applicant Name"},"owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Name"},"contractor_license":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contractor License"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","permit_number","status","category","tags","property_type","address_street","address_city","address_state","address_zip","description_raw","estimated_value","date_filed","date_issued","date_completed","date_expired","stories","units","square_footage","applicant_name","owner_name"],"title":"PermitDetail"},"PermitEnrichment":{"properties":{"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"},"work_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Summary"},"solar_kw":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Solar Kw"},"sqft":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sqft"},"units":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Units"},"is_residential":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Residential"},"is_commercial":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Commercial"},"materials":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Materials"}},"type":"object","title":"PermitEnrichment","description":"Curated subset of the offline LLM enrichment (permits.enriched_data).\n\nPresent only on the ~1-2% of permits that have been enriched so far\n(prioritized toward SOLAR/ROOFING/NEW_CONSTRUCTION). null otherwise."},"PermitEventOut":{"properties":{"id":{"type":"integer","title":"Id"},"permit_id":{"type":"string","format":"uuid","title":"Permit Id"},"event_type":{"type":"string","title":"Event Type"},"old_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Old Value"},"new_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Value"},"occurred_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Occurred On"},"detected_at":{"type":"string","format":"date-time","title":"Detected At"},"permit_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permit Number"},"address_street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Street"},"address_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address City"},"address_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address State"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"jurisdiction_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Name"}},"type":"object","required":["id","permit_id","event_type","detected_at"],"title":"PermitEventOut"},"PermitEventsResponse":{"properties":{"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"},"results":{"items":{"$ref":"#/components/schemas/PermitEventOut"},"type":"array","title":"Results"}},"type":"object","required":["total","page","per_page","results"],"title":"PermitEventsResponse"},"PermitSearchResponse":{"properties":{"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"},"results":{"items":{"$ref":"#/components/schemas/PermitSummary"},"type":"array","title":"Results"},"total_capped":{"type":"boolean","title":"Total Capped","default":false}},"type":"object","required":["total","page","per_page","results"],"title":"PermitSearchResponse"},"PermitStatus":{"type":"string","enum":["filed","issued","in_progress","final","expired","cancelled","revoked","unknown"],"title":"PermitStatus"},"PermitSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"permit_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permit Number"},"status":{"type":"string","title":"Status"},"category":{"type":"string","title":"Category"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"property_type":{"type":"string","title":"Property Type"},"address_street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Street"},"address_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address City"},"address_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address State"},"address_zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Zip"},"description_raw":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Raw"},"estimated_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Value"},"date_filed":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Filed"},"date_issued":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Issued"},"date_completed":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Completed"},"contractor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contractor Name"},"jurisdiction_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction Name"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"enrichment":{"anyOf":[{"$ref":"#/components/schemas/PermitEnrichment"},{"type":"null"}]}},"type":"object","required":["id","permit_number","status","category","tags","property_type","address_street","address_city","address_state","address_zip","description_raw","estimated_value","date_filed","date_issued","date_completed"],"title":"PermitSummary"},"PropertyHistoryResponse":{"properties":{"query":{"$ref":"#/components/schemas/PropertyQuery"},"found":{"type":"boolean","title":"Found"},"total_matches":{"type":"integer","title":"Total Matches"},"truncated":{"type":"boolean","title":"Truncated"},"summary":{"$ref":"#/components/schemas/PropertySummary"},"coverage":{"anyOf":[{"$ref":"#/components/schemas/CoverageConfidence"},{"type":"null"}]},"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"},"has_more":{"type":"boolean","title":"Has More"},"permits":{"items":{"$ref":"#/components/schemas/PermitSummary"},"type":"array","title":"Permits"}},"type":"object","required":["query","found","total_matches","truncated","summary","page","per_page","has_more","permits"],"title":"PropertyHistoryResponse"},"PropertyQuery":{"properties":{"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"parcel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parcel"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"}},"type":"object","title":"PropertyQuery"},"PropertySignals":{"properties":{"has_solar":{"type":"boolean","title":"Has Solar","default":false},"solar_kw":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Solar Kw"},"last_solar_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Solar Date"},"has_battery":{"type":"boolean","title":"Has Battery","default":false},"last_battery_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Battery Date"},"has_roofing":{"type":"boolean","title":"Has Roofing","default":false},"last_roofing_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Roofing Date"},"has_pool":{"type":"boolean","title":"Has Pool","default":false},"last_pool_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Pool Date"},"has_addition":{"type":"boolean","title":"Has Addition","default":false},"has_new_construction":{"type":"boolean","title":"Has New Construction","default":false},"has_electrical":{"type":"boolean","title":"Has Electrical","default":false},"has_hvac":{"type":"boolean","title":"Has Hvac","default":false},"last_hvac_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Hvac Date"},"has_plumbing":{"type":"boolean","title":"Has Plumbing","default":false},"has_demolition":{"type":"boolean","title":"Has Demolition","default":false},"last_activity_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Activity Date"}},"type":"object","title":"PropertySignals","description":"Boolean/scalar rollups useful for underwriting, valuation and diligence.\n\nDerived from permit category + tags + offline enrichment across every\npermit matched at the address. Dates are the most-recent permit of that\nkind (ISO yyyy-mm-dd) so you can reason about roof/solar/pool age."},"PropertySummary":{"properties":{"total_permits":{"type":"integer","title":"Total Permits"},"first_permit_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Permit Date"},"last_permit_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Permit Date"},"years_of_history":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Years Of History"},"total_estimated_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Estimated Value"},"categories":{"additionalProperties":{"type":"integer"},"type":"object","title":"Categories"},"jurisdictions":{"items":{"type":"string"},"type":"array","title":"Jurisdictions"},"contractors":{"items":{"type":"string"},"type":"array","title":"Contractors"},"signals":{"$ref":"#/components/schemas/PropertySignals"}},"type":"object","required":["total_permits","categories","jurisdictions","contractors","signals"],"title":"PropertySummary"},"PropertyType":{"type":"string","enum":["residential","commercial","industrial","mixed_use","institutional","unknown"],"title":"PropertyType"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookCreate":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Url"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["url"],"title":"WebhookCreate"}}},"tags":[{"name":"Permits","description":"Search and retrieve building permits"},{"name":"Contractors","description":"Search contractors and see their permit history"},{"name":"Property History","description":"Get permit history for a specific address"},{"name":"Webhooks","description":"Subscribe to real-time permit events (paid tiers)"},{"name":"Health","description":"Service health checks"}]}