How to Query Building Permit Data by ZIP Code via API
Updated Tue, Sep 22, 2026 - 8 min read
By Raf Howery | Kukun
Building permit data is one of the most underused signals in real estate, and one of the most valuable. A permit tells you what happened to a property: a roof replaced, an HVAC system swapped out, a kitchen gut-renovated. For lenders, insurers, and proptech platforms, that signals change how you underwrite, price, and market.
The challenge has always been access. Most permit data is trapped in PDFs across thousands of county and city portals. What the Kukun API does is standardize it, 800M+ permits, 5,600+ sources, delivered in a single API call.
This post walks through querying permit data by ZIP code: what the call looks like, what comes back, and how to filter it for your use case.
Why ZIP-level queries matter
A single-address lookup tells you what happened at one property. A ZIP-level query tells you what’s happening across a market. That’s a different product.
Use cases that require ZIP-level permit queries:
- Insurance portfolio review: Which ZIP codes in your book have the highest concentration of aging HVAC systems with no recent replacement permit? That’s your next loss cluster.
- HELOC prospecting: Surface homeowners in a target ZIP who pulled a renovation permit in the last 18 months; they have equity, they’re spending, and they’re warm to a refi conversation.
- Appraisal and collateral review: Verify that a property’s condition matches its stated value by checking whether any major system work was permitted.
- Proptech and investment tools: Map renovation activity across neighborhoods to identify where capital is flowing before prices move.
The API call
The Kukun Permits API supports geographic queries by ZIP code, city, or county. A single call to one geographic scope returns up to 1,000 results. Each result is one permit record.
Here’s a basic ZIP-level query in cURL:
curl -X GET “https://api.mykukun.com/v1/permits/search” \
-H “Authorization: Bearer YOUR_API_KEY” \
-H “Content-Type: application/json” \
-G \
–data-urlencode “zip-code=33133” \
–data-urlencode “status=issued” \
–data-urlencode “label=roof,hvac,kitchen-remodel” \
–data-urlencode “date-from=2024-01-01” \
–data-urlencode “date-to=2026-09-16” \
–data-urlencode “details=1” \
–data-urlencode “limit=2”
Key parameters:
| Parameter | What it does |
|---|---|
| zip-code | Target ZIP: one geographic scope per call |
| status | Filter by permit lifecycle: issued, applied, closed, expired |
| label | Filter by permit type, comma-separated, OR logic by default |
| date-from / date-to | Date window for permit status date |
| details=1 | Return full permit records (vs. count-only) |
| limit | Results per page, up to 1,000 |
What comes back
Here are two real permit records returned for ZIP code 33133 (Coconut Grove, Miami):
{
“permits”: [
{
“permit”: {
“id”: “FLMM001204948”,
“number”: “#BD25029787001MA001”,
“description”: “AC central heating system | sheet metal work | exhaust ventilation | fiberglass ductwork”,
“status”: “issued”,
“labels”: “residential, building, new construction”,
“tags”: [“hvac”],
“type”: “residential”,
“city_assigned_cost”: 35000,
“timeline”: [
{ “status”: “applied”, “date”: “2025-12-19” },
{ “status”: “issued”, “date”: “2026-01-09” }
],
“durations”: { “total_days”: 245 }
},
“property”: {
“type”: “residential”,
“subtype”: “single_family”,
“year_built”: 1952,
“lot_size_sqft”: 20000,
“building_area_sqft”: 6156,
“stories”: 4,
“valuation”: { “market_value”: 622317 }
},
“location”: {
“address”: {
“street_address”: “3220 Frow Ave”,
“city”: “Miami”,
“county”: “Miami-Dade”,
“state”: “Florida”,
“zip_code”: “33133”
},
“coordinates”: { “lat”: 25.7291427, “lng”: -80.2460271 },
“jurisdiction”: [“Miami”]
}
},
{
“permit”: {
“id”: “FLMM001205228”,
“number”: “#BD26019113001BR001”,
“description”: “Shingle roof”,
“status”: “issued”,
“labels”: “residential, building, building roofing”,
“tags”: [“roof”],
“type”: “residential”,
“city_assigned_cost”: 13637,
“timeline”: [
{ “status”: “applied”, “date”: “2026-08-13” },
{ “status”: “issued”, “date”: “2026-08-20” }
],
“durations”: { “total_days”: 8 }
},
“property”: {
“type”: “residential”,
“subtype”: “duplex”,
“year_built”: 1963,
“lot_size_sqft”: 4000,
“building_area_sqft”: 1344,
“valuation”: { “market_value”: 220787 }
},
“location”: {
“address”: {
“street_address”: “2644 SW 28th Ct”,
“city”: “Miami”,
“county”: “Miami-Dade”,
“state”: “Florida”,
“zip_code”: “33133”
},
“coordinates”: { “lat”: 25.7425362, “lng”: -80.2399146 },
“jurisdiction”: [“Miami”]
}
}
],
“total”: 1606,
“limit”: 2,
“total_pages”: 803,
“next_page_id”: “W1sxNzg3MjcwNDAwMDAwLDAsIkZMTU0w…”
}
What to notice in this response:
- total: 1606: there are over 1,600 matching permits in this ZIP for the date range and label filters specified. The query returned the first 2; use next_page_id to paginate.
- tags: normalized labels (hvac, roof) applied by Kukun’s processing layer, consistent across all jurisdictions regardless of how the local authority described the work.
- timeline: full permit lifecycle: applied → issued → closed. The roof permit above went from application to issuance in 7 days. The HVAC permit has been active for 245 days, meaning work is ongoing.
- property: property context joined to the permit: year built, square footage, market value. You get the property record alongside the permit without a second API call.
- durations.total_days: useful for identifying properties with long-running open permits, which can signal unpermitted work, contractor disputes, or stalled construction.
Filtering for your use case
The label parameter is where most of the workflow-specific filtering happens. Supported labels include:
roof · hvac · kitchen-remodel · bathroom-remodel · electrical · plumbing · solar · new-construct · new-construct-adu · whole-house-remodel · foundation · pool · deck · fence · and more
Label logic: comma-separated values use OR by default. Prefix with + for AND (required), – to exclude.
Examples:
- label=roof,hvac — permits tagged roof OR hvac
- label=+roof,+hvac — permits tagged both roof AND hvac (full system replacement signal)
- label=kitchen-remodel,-bathroom-remodel — kitchen remodels that are not also bathroom remodels
Result caps and pagination
Self-serve plans cap geographic query results at 1,000 per call. The next_page_id cursor lets you paginate through results within that cap. If your use case requires more than 1,000 results per query (a full county pull, a nationwide portfolio run) that’s an Enterprise use case.
Each result returned counts as 1 query unit against your monthly plan. A query returning 500 permits uses 500 query units.
Getting started
API keys are issued through the developer portal. Free tier includes 20 queries, enough to test geographic queries against any ZIP before committing to a plan.
→ Get your API key at mykukun.com/developers
Full parameter reference and label vocabulary are in the API documentation.