Zoning Firehose API

Build on the same data your alerts run on: every validated rezoning, specific use permit, plat, and PD amendment we track across DFW P&Z agendas, as clean JSON. Same pipeline, same freshness — hours after the packet drops.

API access is included with the Metro and Corporate plans. Sign in and mint a key on your account page — it takes a moment and the key is shown once. Email us if anything goes wrong.

Try it live

The whole API is published as OpenAPI 3, so you can explore it here or generate a client instead of hand-writing one. The spec declares the X-API-Key scheme, so Swagger's Authorize button and any generated client send it for you — and it is scoped to Dallas–Fort Worth, the metro you are viewing, so the examples call the host your plan covers.

Authentication

Send your key in the X-API-Key header on every request. Requests without a valid key get 401.

Rate limit: 60 requests/minute per account (300 on Corporate, shared across its users). The quota belongs to your account, not to each key — minting a second key gives you another credential, not more requests. Over the limit returns 429; retry after the Retry-After seconds. Every response carries X-RateLimit-Remaining so you can back off first.

curl -H "X-API-Key: zf_your_key_here" \
  "https://zoningfirehose.com/api/v1/cases?county=Collin&case_type=rezoning&limit=5"

Endpoints

GET /api/v1/cases

List validated cases, newest first. Returns total (matches across all pages), count, cases, and ready-to-follow next/prev page URLs (null at the ends). Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset so you can back off before a 429. The API is metro-scoped by host — this host serves DFW data; hit another metro's subdomain for its data (each case carries a metro field).

Query parameters (all optional):

ParamMeaning
municipalityCity name, e.g. Addison
countyCollin, Dallas, Denton, Ellis
petitionerExact applicant name — the same grouping as the petitioner pages, e.g. McAdams
case_typeOne of: rezoning, specific_use_permit, plat, pd_amendment, comprehensive_plan_amendment, variance, site_plan, text_amendment, annexation, other
statusOne of: new, updated, continued, approved, denied, withdrawn. Only new, updated, continued are ever produced — see below
hearing_after / hearing_beforeISO dates (YYYY-MM-DD) bounding the hearing date
qKeyword search across case number, structured fields, and full agenda text
limit / offsetPaging — limit defaults to 50, max 200. Above 200 returns 422 rather than silently truncating, so a short page is always a page you asked for.

Each case object carries the full extracted record:

{
  "case_number": "Z-2026-014",
  "case_type": "rezoning",
  "address_or_location": "NE corner of Main St & FM 2478",
  "acreage": 12.4,
  "current_zoning": "AG",
  "requested_zoning": "PD-MF",
  "proposed_use": "Multi-family residential",
  "petitioner": "Example Development LLC",
  "staff_recommendation": "approval",
  "confidence": "high",
  "impact_summary": "Rezoning 12.4 acres from agricultural to a planned development for multi-family.",
  "municipality": "Addison",
  "county": "Collin",
  "metro": "dfw",
  "hearing_date": "2026-08-11",
  "status": "new",
  "processed_at": "2026-07-28T14:02:11Z",
  "detail_url": "https://zoningfirehose.com/cases/addison/Z-2026-014",
  "source_url": "https://addison.legistar.com/..."
}

GET /api/v1/cases/{municipality}/{case_number}

One case by city and case number. 404 if we don't track it.

curl -H "X-API-Key: zf_your_key_here" \
  "https://zoningfirehose.com/api/v1/cases/addison/Z-2026-014"

GET /api/v1/municipalities

Coverage list: every municipality, its county, agenda platform, P&Z meeting cadence, live status, and tracked case count.

curl -H "X-API-Key: zf_your_key_here" "https://zoningfirehose.com/api/v1/municipalities"

MCP server — use the data from Claude

Ship your key to Claude Desktop, Claude Code, or any MCP client with our single-file server — no extra packages beyond Python 3.11+ and httpx. Download mcp_server.py, then add this to your MCP config:

{
  "mcpServers": {
    "zoning-firehose": {
      "command": "python",
      "args": [
        "/path/to/mcp_server.py"
      ],
      "env": {
        "ZONING_API_KEY": "zf_your_key_here"
      }
    }
  }
}

That gives Claude four tools — search_cases, get_petitioner_history, get_case, and list_municipalities — so you can ask things like “any multi-family rezonings in Collin County with hearings next month?” or “what has McAdams filed this year?” and get grounded answers from live data.

No-code: RSS into Slack, Teams or Zapier

Every plan — not just metro — includes a private RSS feed of your matches at /feed.xml?token=…, running the same filters as your email. The link is on your filters page. No API key required.

Treat the feed URL like a password — anyone holding it sees the cases your filters match. It is read-only and separate from your sign-in link, so it cannot change your alerts or show your address. If it leaks, reset it yourself from your account page — one click, and the old URL stops working immediately.

Lifecycle, signals and proximity in the data

Cases are tracked as they move, so the same case number legitimately appears more than once over its life. status reflects the latest transition we observed — a case advancing from Planning & Zoning to Council is a distinct event from a continuance, and the two are never conflated.

We do not report outcomes, and will not imply one. We read agendas, which cities publish before the meeting; minutes are not ingested. So status describes where a case is in our pipeline, not how a vote went. The values approved, denied and withdrawn exist in the schema and are still accepted by the filter, but nothing ever sets them: a query for them returns an empty list, and that empty list means we do not know — never that no case was approved. If you are building on this, treat the absence of an outcome as missing data rather than a negative result.

staff_recommendation is the field to watch if you are modelling outcomes: a value of deny is the earliest reliable signal a case is in trouble, and it arrives with the packet rather than at the hearing. It is present on roughly a third of cases — only where the packet states one, never inferred.

Proximity alerts (filings near land you own) are an email and RSS feature configured on your filters page; they are not part of the REST payload.

Fair use

Data is licensed for your internal tools and analysis under your subscription. No resale or public rehosting of the feed. Questions, higher limits, webhooks? questions@zoningfirehose.com.

Start 14-day free trial