Florida Building Permits & Code Violation Leads
Pricing
from $4.00 / 1,000 permit / code records
Florida Building Permits & Code Violation Leads
Fresh Florida building permits and open code-violation cases from official Miami, Miami-Dade and Orlando open-data feeds. Filter by trade, value or keyword; optional 0-100 lead scores for roofers, solar/HVAC installers, suppliers and property investors. No phones or emails scraped.
Pricing
from $4.00 / 1,000 permit / code records
Rating
0.0
(0)
Developer
Nathan Madrishin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
Florida Building Permits & Code Violations API (Miami, Miami-Dade, Orlando)
Fresh building permits and open code-violation cases from official Florida open-data feeds - as clean JSON, CSV or Excel, with optional 0-100 lead scores. No API keys, no logins, no proxies, no browser scraping: it reads the cities' and county's own public data APIs, so it is fast, stable and cheap.
Use it to find out who just pulled a big permit and which properties are in trouble - this week, not last year.
At a glance (for people, scripts and AI agents): input
dataType(permits,codeViolationsorboth),daysBack, optional filters (sources,keywords,commercialOnly,minEstimatedValue,codeStatus) andenrichfor 0-100 lead scores; output is one flat JSON record per permit or code case. Defaults return 100 fresh records in seconds. Covers Orlando, Miami-Dade County and the City of Miami. From $4 per 1,000 records. Ready-made snippets for MCP, curl, Python and JavaScript are under "Use it from AI agents, code and no-code tools".
Who it is for
| You are a... | Try this |
|---|---|
| Roofer, solar, HVAC, electrical, plumbing or pool contractor | Permits, commercialOnly, keywords like roof, solar, hvac |
| Building-materials supplier or equipment dealer | Permits with minEstimatedValue (e.g. $100,000+) and enrich on |
| Real-estate investor or wholesaler | Code violations, codeStatus: open, enrich on - lien and civil cases, unsafe structures, expired permits |
| Property manager or insurance / restoration company | Code violations at addresses you serve |
| Broker, developer or market analyst | Permits over time by jurisdiction, value and trade |
| Sales team / lead-gen agency | Scheduled daily runs into Google Sheets or your CRM |
What you get
| Source | Data | Updated | Date filter |
|---|---|---|---|
| City of Orlando | Permit applications (building, mechanical, electrical, plumbing, roofing, fire, engineering...) | daily | application processed date |
| Miami-Dade County | Issued building permits | daily | permit issued date |
| City of Miami | Building permits since 2014 (thousands of new ones every month) | daily | permit issued date |
| City of Orlando | Code-enforcement cases | daily | case opened date |
| Miami-Dade County | Code-compliance cases, including lien, civil-penalty and collections referrals | daily | case opened date |
| Miami-Dade County | Building violations: unsafe structures, expired permits, boilers, other | daily | case opened date |
Every permit has: permit number, type, work type, status, estimated project value, square footage, dates, address, parcel / folio number, the contractor company, and the owner - only when the owner is a business or government entity.
Every code case has: case number, type, status, open / closed flag, opened date, address, parcel / folio number, a plain issue description, severity flags (unsafe, unpermitted-work, expired-permit, vacant, overgrown...), and whether a lien was referred.
Lead scoring (enrich: true)
Turn a raw feed into a ranked call list. Every record gets a 0-100 score and human-readable scoreReasons, and the best leads come first.
- Permits: project value, commercial flag, how new it is, trade tags (roofing, solar, hvac, electrical, plumbing, pool, demolition, remodel, fire-protection, sign...) and whether the owner is a business entity.
- Code cases: open status, age, escalation (lien, civil penalty, collections referral), severity flags, vacant land use and the number of cases at the same address - a transparent "distressed property" indicator.
Quick start - copy one of these inputs
Big commercial projects in Miami this fortnight
{"dataType": "permits","sources": ["miami-city", "miami-dade"],"commercialOnly": true,"minEstimatedValue": 100000,"daysBack": 14,"enrich": true,"maxResults": 200}
Distressed-property leads: open code cases, worst first
{"dataType": "codeViolations","codeStatus": "open","daysBack": 90,"enrich": true,"maxResults": 500}
Every new solar or roofing permit in the last month
{"dataType": "permits","keywords": ["solar", "roof"],"daysBack": 30,"maxResults": 1000}
Run with the defaults to get 100 fresh permits, shared evenly across every source (Orlando's impact-fee billing entries are left out - only real construction permits). dataType: "both" returns a balanced mix of permits and code cases.
Input
| Field | Default | Notes |
|---|---|---|
dataType | permits | permits, codeViolations, or both (results are shared between the two types) |
sources | all | orlando, miami-dade, miami-city. Code violations: Orlando and Miami-Dade |
daysBack | 30 | 1-365 |
commercialOnly | false | permits only |
minEstimatedValue | 0 | permits only, USD |
keywords | - | keep records matching any keyword (type, work type, description, address, contractor, issue flags) |
codeStatus | open | open (not closed, includes lien / civil / referred cases) or all |
includeTickets | false | Orlando "ticket" cases (mostly street-level transient enforcement) are skipped by default |
enrich | false | adds scores, reasons, trade tags, cases-at-address; billed at the scored-lead rate |
maxResults | 100 | hard cap on returned and billed records (max 5,000); your run's maximum-charge setting is honoured too |
socrataAppToken | - | optional; raises the Orlando API rate limit |
Output example (abridged)
A permit:
{"recordType": "permit", "source": "miami-city", "jurisdiction": "City of Miami, FL","permitNumber": "BD25000255019B001", "permitType": "NEW CONSTRUCTION", "isCommercial": true,"status": "Active", "estimatedValue": 980000, "issuedDate": "2026-09-18","address": "1785 NW 35 ST", "parcelId": "0131270090140","contractorCompany": "OCEAN DOORS AND WINDOWS. INC.","tags": ["new-construction"], "score": 79,"scoreReasons": ["project value >= $100k", "commercial permit", "new activity in last 7 days", "trades: new-construction"]}
A code case:
{"recordType": "codeViolation", "source": "miami-dade", "jurisdiction": "Miami-Dade County, FL","caseNumber": "20260250634", "caseType": "Unsafe Structure", "status": "Open", "isOpen": true,"openedDate": "2026-09-17", "address": "19422 SW 119 CT", "parcelId": "3069010270170","ownerName": "P&B GLOBAL PROPERTIES LLC", "ownerType": "entity","issueFlags": ["unsafe", "structural"], "score": 50,"scoreReasons": ["case still open", "severity flags: unsafe, structural"]}
Also written, to the run's key-value store: a SUMMARY record with the date window, counts per source, warnings, and whether the run stopped at your spending limit. Every field is explained under Output fields below.
Pricing
Pay per event - you only pay for records you actually receive:
- $4.00 per 1,000 records (
enrichoff) - $20.00 per 1,000 scored lead records (
enrichon) - $0.005 per run start
Set a maximum charge on the run and it stops there. Compare that with subscription lead lists: a $4 run gets you 1,000 fresh records.
Privacy by design
This Actor is deliberately not a contact scraper.
- No phone numbers or e-mail addresses are collected.
- Private individuals' names (homeowners, violators, complainants) are not returned. Owners appear only when the name is clearly a business or government entity; otherwise
ownerTypeisindividualandownerNameisnull. Use the parcel / folio number to look the property up in the county property appraiser's public records. - Individual contractor / licensee names, contractor street addresses and architect names are dropped; the contractor company name is kept.
- Free-text code-case comments are never output (citizen complaints often contain the complainant's name, phone and address). Only generic severity flags derived from them are.
- Confidential and protected cases published by the county are skipped.
Use it from AI agents, code and no-code tools
The Actor is built to be called by machines: a run with the defaults finishes in seconds, every input has a safe default, every field is documented below, and the output is flat, typed JSON with a stable schema. There is no login, proxy or browser to configure.
AI agents (MCP). Add the Apify MCP server and expose just this Actor as a tool:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=open-records-data/florida-building-permits-code-violations"}}}
Works with Claude, Cursor, VS Code and any MCP client. Sign in with OAuth, or send an Authorization: Bearer <APIFY_TOKEN> header. Then just ask, for example: "Find open unsafe-structure code cases in Miami-Dade from the last 30 days" or "List new commercial permits over $250,000 in Miami this week."
HTTP API (one call, JSON back):
curl -X POST "https://api.apify.com/v2/acts/open-records-data~florida-building-permits-code-violations/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"dataType":"permits","commercialOnly":true,"minEstimatedValue":100000,"daysBack":14,"enrich":true,"maxResults":50}'
Python:
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("open-records-data/florida-building-permits-code-violations").call(run_input={"dataType": "codeViolations", "codeStatus": "open", "daysBack": 30, "enrich": True, "maxResults": 100})for lead in client.dataset(run["defaultDatasetId"]).iterate_items():if lead.get("recordType") == "codeViolation":print(lead["score"], lead["address"], lead["caseType"], lead["scoreReasons"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('open-records-data/florida-building-permits-code-violations').call({ dataType: 'permits', keywords: ['roof', 'solar'], daysBack: 30, maxResults: 200 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Schedules and integrations. Put it on a schedule (daily is typical), then send results anywhere: Google Sheets, Airtable, Slack or e-mail via Apify integrations, Zapier, Make or n8n, or a webhook into your CRM.
Tips for agents.
- Start with the defaults and a small
maxResults(10-20) to see the shape of the data, then widen. - Skip
enrichwhen you only need raw records: it costs more per record but ranks the results and explains the ranking. - Filter records with
recordType(permitorcodeViolation) andsource(orlando,miami-dade,miami-city). - Run totals, per-source counts, the date window and any per-source warnings are in the
SUMMARYrecord of the run's key-value store. Check it if a source returns fewer records than expected. - Records are public-record data with owner and contractor personal data removed. Do not use them for tenant screening, credit, insurance or employment decisions.
Output fields
| Field | Type | Meaning |
|---|---|---|
recordType | permit | codeViolation | What kind of record this is |
source, jurisdiction | string | orlando, miami-dade or miami-city, and the readable name |
permitNumber / caseNumber | string | The jurisdiction's own identifier |
permitType, workType, description | string | What the permit is for (permits only) |
caseType, caseName, description | string | What the case is about (code cases only) |
status, isOpen | string, boolean | Jurisdiction status; isOpen is true while a code case is not closed |
isCommercial | boolean or null | Commercial vs. residential where the jurisdiction says |
estimatedValue | number (USD) or null | Declared project value |
squareFootage | number or null | Permit square footage when published |
appliedDate, issuedDate, activityDate | YYYY-MM-DD | Application, issue and most recent of the two |
openedDate, closedDate | YYYY-MM-DD | Code case dates |
address, parcelId | string | Street address and parcel / folio number |
ownerName, ownerType | string or null, entity | individual | unknown | Name only when the owner is a business or government entity |
contractorCompany | string or null | Contractor company (never an individual) |
issueFlags | string[] | Code cases: unsafe, structural, unpermitted-work, expired-permit, vacant, overgrown... |
lienReferral | boolean | Miami-Dade code cases: a lien or collections referral is on file |
tags | string[] | Permits, with enrich: trade tags such as roofing, solar, hvac |
score, scoreReasons | 0-100, string[] | With enrich: lead score and the plain-language reasons |
casesAtAddress | number | With enrich: code cases at the same address in this run |
sourceUrl | string | The official open-data page the record came from |
FAQ
Is this legal? It reads public records that the cities and county publish for reuse through their official open-data APIs. It is not affiliated with or endorsed by any of them.
Can I use it for tenant screening, credit, insurance or hiring decisions? No. It is public-record data, not a consumer report, and must not be used for purposes regulated by the FCRA.
How fresh is the data? As fresh as each jurisdiction publishes it - all sources update daily. Orlando permits are filtered by application processed date, so newly filed applications appear before they are issued (issuedDate may be empty). Miami-Dade and City of Miami permits are issued permits.
Why is the owner missing on most permits? Owners of homes are individuals, so their names are withheld by design. Business owners are shown. City of Miami permits carry no owner field.
Is the score a prediction? No. It is a transparent heuristic for triage: the scoreReasons tell you exactly why a record ranks where it does.
What if a city changes its data? The Actor reports per-source failures in the SUMMARY record and in the log rather than silently returning nothing, and keeps returning data from the other sources.
Does it cover all of Florida? Not yet. Today: the City of Orlando, Miami-Dade County (as published in the county's open-data feeds) and the City of Miami. Each jurisdiction runs its own permit system, so cities are added one at a time as they publish usable open data.
How do I get roofing, solar or HVAC leads? Run permits with keywords such as ["roof"], ["solar"] or ["hvac"], set commercialOnly or minEstimatedValue to focus on bigger jobs, turn enrich on to rank them, and schedule a daily run.
Will you add more cities? Yes - requests for more Florida jurisdictions are welcome. Open an issue on the Issues tab and say which city and which data (permits or code cases).
More Florida public-record Actors
- Florida New Business Leads (Miami-Dade, Broward, Miami) - businesses the week they are licensed, or before they open, from official business tax receipt feeds, with optional 0-100 lead scores. Pair it with this Actor to reach new businesses that are also pulling permits.
- Miami-Dade Property Records API - look up any Miami-Dade address or folio, or search by ZIP and sale date, for property facts, FEMA flood zone, permits, violations and a 0-100 prospecting score. Use it to enrich the addresses this Actor returns.
Limitations
- Owner classification is a name heuristic. Some entities without a legal suffix (for example a bare association name) are treated as individuals and withheld. It errs on the side of privacy.
- Coverage today is Orlando, Miami-Dade County and the City of Miami; more Florida jurisdictions are on the roadmap.
- Data is only as accurate as the jurisdiction publishes it. Miami-Dade's electrical, mechanical and other sub-permits often repeat the whole project's estimated value, so several permits for one project can show the same (large) number.
- Code cases with no street address are skipped.