{"openapi":"3.1.0","info":{"title":"Zoning Firehose API","description":"Structured municipal rezoning data for commercial real estate developers.\n\nEvery case here was extracted from a real Planning & Zoning agenda packet and\nvalidated before storage — anything the extractor could not stand behind is held\nfor review rather than served.\n\n## Authentication\n\nSend your key in the `X-API-Key` header on every request:\n\n```\ncurl -H \"X-API-Key: zf_your_key_here\" \\\n  \"https://zoningfirehose.com/api/v1/cases?case_type=rezoning&limit=5\"\n```\n\nMint a key at `/profile` once you have a subscription. Keys are shown once.\n\n## Rate limits\n\nPer **account**, not per key, so minting more keys does not raise your ceiling.\nA corporate seat draws on the paying account's allowance. Exceeding it returns\n`429` with a `Retry-After` header.\n\n## Conventions\n\n- All dates are ISO-8601 (`YYYY-MM-DD`).\n- `limit` is capped at 200; page with `offset`.\n- Unknown query parameters are ignored; invalid enum values return `422`.\n- This is a stable, additive contract — fields get added, not removed or renamed.\n","version":"1.0.0"},"paths":{"/health":{"get":{"tags":["Service"],"summary":"Liveness probe","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}},"/api/v1/cases":{"get":{"tags":["Cases"],"summary":"Search cases","description":"List validated cases, newest first. Same archive the dashboard renders.","operationId":"api_v1_cases_api_v1_cases_get","parameters":[{"name":"municipality","in":"query","required":false,"schema":{"type":"string","default":"","title":"Municipality"}},{"name":"county","in":"query","required":false,"schema":{"type":"string","default":"","title":"County"}},{"name":"case_type","in":"query","required":false,"schema":{"type":"string","default":"","title":"Case Type"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}},{"name":"petitioner","in":"query","required":false,"schema":{"type":"string","default":"","title":"Petitioner"}},{"name":"hearing_after","in":"query","required":false,"schema":{"type":"string","default":"","title":"Hearing After"}},{"name":"hearing_before","in":"query","required":false,"schema":{"type":"string","default":"","title":"Hearing Before"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Matching cases, newest first, with a total for paging.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Missing, invalid or revoked X-API-Key"},"429":{"description":"Account rate limit exceeded; see Retry-After"}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/cases/{municipality}/{case_number}":{"get":{"tags":["Cases"],"summary":"Fetch one case","description":"Single case by city + case number (case numbers may contain slashes).","operationId":"api_v1_case_detail_api_v1_cases__municipality___case_number__get","parameters":[{"name":"municipality","in":"path","required":true,"schema":{"type":"string","title":"Municipality"}},{"name":"case_number","in":"path","required":true,"schema":{"type":"string","title":"Case Number"}}],"responses":{"200":{"description":"The full validated case, including its source document URL.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"401":{"description":"Missing, invalid or revoked X-API-Key"},"429":{"description":"Account rate limit exceeded; see Retry-After"}},"security":[{"ApiKeyAuth":[]}]}},"/api/v1/municipalities":{"get":{"tags":["Coverage"],"summary":"List monitored municipalities","description":"Coverage list: every municipality we track, with case counts.","operationId":"api_v1_municipalities_api_v1_municipalities_get","responses":{"200":{"description":"Every municipality being monitored, with metro and county.","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing, invalid or revoked X-API-Key"},"429":{"description":"Account rate limit exceeded; see Retry-After"}},"security":[{"ApiKeyAuth":[]}]}}},"components":{"schemas":{"Body_admin_login_admin_login_post":{"properties":{"password":{"type":"string","title":"Password","default":""}},"type":"object","title":"Body_admin_login_admin_login_post"},"Body_contact_submit_contact_post":{"properties":{"name":{"type":"string","title":"Name","default":""},"email":{"type":"string","title":"Email","default":""},"message":{"type":"string","title":"Message","default":""},"website":{"type":"string","title":"Website","default":""}},"type":"object","title":"Body_contact_submit_contact_post"},"Body_filters_save_filters_post":{"properties":{"keywords":{"type":"string","title":"Keywords","default":""},"metro":{"type":"string","title":"Metro","default":""},"city":{"type":"string","title":"City","default":""},"county":{"type":"string","title":"County","default":""},"delivery_mode":{"type":"string","title":"Delivery Mode","default":"instant"},"distress_only":{"type":"string","title":"Distress Only","default":""}},"type":"object","title":"Body_filters_save_filters_post"},"Body_login_submit_login_post":{"properties":{"email":{"type":"string","title":"Email","default":""},"website":{"type":"string","title":"Website","default":""}},"type":"object","title":"Body_login_submit_login_post"},"Body_optout_optout_post":{"properties":{"token":{"type":"string","title":"Token","default":""}},"type":"object","title":"Body_optout_optout_post"},"Body_profile_mint_api_key_profile_api_keys_post":{"properties":{"token":{"type":"string","title":"Token"},"label":{"type":"string","title":"Label","default":""}},"type":"object","required":["token"],"title":"Body_profile_mint_api_key_profile_api_keys_post"},"Body_profile_revoke_api_key_profile_api_keys_revoke_post":{"properties":{"token":{"type":"string","title":"Token"},"key_prefix":{"type":"string","title":"Key Prefix"}},"type":"object","required":["token","key_prefix"],"title":"Body_profile_revoke_api_key_profile_api_keys_revoke_post"},"Body_team_add_team_add_post":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"Body_team_add_team_add_post"},"Body_team_remove_team_remove_post":{"properties":{"seat_id":{"type":"integer","title":"Seat Id"}},"type":"object","required":["seat_id"],"title":"Body_team_remove_team_remove_post"},"Body_unsubscribe_unsubscribe_post":{"properties":{"token":{"type":"string","title":"Token","default":""}},"type":"object","title":"Body_unsubscribe_unsubscribe_post"},"Body_watchlist_add_watchlist_post":{"properties":{"label":{"type":"string","title":"Label"},"address":{"type":"string","title":"Address"},"radius_feet":{"type":"integer","title":"Radius Feet","default":1000}},"type":"object","required":["label","address"],"title":"Body_watchlist_add_watchlist_post"},"Body_watchlist_delete_watchlist_delete_post":{"properties":{"parcel_id":{"type":"integer","title":"Parcel Id"}},"type":"object","required":["parcel_id"],"title":"Body_watchlist_delete_watchlist_delete_post"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"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"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Mint one at /profile. Rate limits apply per account, not per key."}}},"tags":[{"name":"Cases","description":"Validated rezoning, plat, SUP and variance cases."},{"name":"Coverage","description":"Which municipalities are being monitored, and in which metro."},{"name":"Service","description":"Liveness."}],"servers":[{"url":"https://raleigh.zoningfirehose.com","description":"Production"}]}