Load permits once, then take only what changed each night. Add permit history to property pages, build market series, and show your users how current every source is, because the API tells you.
No credit card required. 100 free requests/day.
# Initial load of one state's permits, then only what changed
curl "https://api.permit-stack.com/v1/permits/sync?state=TX\
&limit=50000" \
-H "X-API-Key: pk_your_key_here"
# Save next_cursor. After tomorrow's ingest:
curl "https://api.permit-stack.com/v1/permits/sync\
?cursor=$NEXT_CURSOR&limit=50000" \
-H "X-API-Key: pk_your_key_here"PermitStack normalizes 117M+ building permits from 887 active data sources in 8,000+ cities across 48 states and DC into one schema: 20 categories, normalized statuses and dates, address components, coordinates where available, and contractors of record. Platforms use /v1/permits/sync to keep a local copy current, /v1/property/history for property pages, and /v1/metrics for market series.
Every source reports a data-through date and freshness label through /v1/jurisdictions, so you can show your users the same honesty. Start free, and check your market before you pay.
From 887 active data sources in 8,000+ cities across 48 states and DC, plus 75 historical-archive jurisdictions.
Sources are polled daily at 03:00 UTC; the sync cursor hands you only what is new or changed since your last page.
100 free requests per day, no card. Free keys see the last 30 days of permits; paid plans remove the date limit.
Each example is a real request and a trimmed copy of the response it returned. Residential street addresses are redacted.
/v1/permits/sync pages the dataset in (updated_at, id) order. Omit the cursor for the initial load, persist next_cursor, and after each nightly ingest you receive only new and changed permits. Pages hold up to 50,000 permits and can be scoped by state or category; fields=full adds the extended columns.
It is upsert-only: deletions at the source are not emitted, so treat the feed as additions and corrections.
# Texas new-construction permits changed since Sept 28 (a small page)
curl "https://api.permit-stack.com/v1/permits/sync?state=TX\
&category=new_construction\
&since=2026-09-28T00:00:00Z\
&limit=2" \
-H "X-API-Key: pk_your_key_here"{
"results": [
...,
{"permit_number": "RES-NEW-26-001660", "status": "UNKNOWN",
"category": "NEW_CONSTRUCTION", "property_type": "RESIDENTIAL",
"address_street": "[redacted]", "address_city": "Dallas",
"address_state": "TX", "address_zip": "75235",
"description_raw": "NSFAA a new single family dwelling is being built",
"date_filed": "2026-09-11", "latitude": 32.81..., "longitude": -96.82...,
"jurisdiction_name": "Dallas",
"updated_at": "2026-09-28T01:52:01Z", ...}
],
"count": 2,
"has_more": true,
"next_cursor": "2026-09-28T01:52:01.633660+00:00|d7192593-..."
}/v1/property/history (address) and /v1/property/by-parcel (APN) return a property's permit timeline with a derived summary: years of history, category mix, contractors of record, and the latest roof, HVAC, solar and pool dates. That is the renovation and system-age context a listing, valuation or diligence page needs.
data_currency lists every source behind the answer. In this example one of the four sources is lagging, and the response says so instead of hiding it.
# A downtown Seattle building
curl "https://api.permit-stack.com/v1/property/history?address=1507%20Western%20Ave\
&city=Seattle\
&state=WA" \
-H "X-API-Key: pk_your_key_here"{
"found": true,
"total_matches": 42,
"distinct_addresses": 2,
"summary": {
"first_permit_date": "2005-04-28",
"last_permit_date": "2026-09-10",
"years_of_history": 21,
"total_estimated_value": 2481054.0,
"categories": {"ELECTRICAL": 14, "HVAC": 8, "INTERIOR_REMODEL": 8,
"RENOVATION": 4, "ROOFING": 3, ...},
"contractors": ["Premier Mechanical & Electric", "Axiom Division 7 Inc", ...],
"signals": {"last_roofing_date": "2026-09-10",
"last_hvac_date": "2025-12-22", "has_addition": true, ...}
},
"data_currency": [
{"jurisdiction": "King County", "data_through": "2026-08-09", "status": "lagging", ...},
{"jurisdiction": "Seattle", "data_through": "2026-09-25", "status": "current", ...},
...
],
...
}/v1/metrics/monthly returns permits and total valuation per month for a city, state and category; /v1/metrics/current gives the category mix over a trailing window; /v1/metrics/cities ranks the busiest cities in a state. They are served from a nightly rollup, so they answer in milliseconds, and each response states its own as_of time and how it attributes permits to cities.
# Busiest Texas cities for new construction, last 3 months
curl "https://api.permit-stack.com/v1/metrics/cities?state=TX\
&category=NEW_CONSTRUCTION\
&months=3\
&limit=5" \
-H "X-API-Key: pk_your_key_here"{
"filters": {"state": "TX", "category": "NEW_CONSTRUCTION", "months": 3},
"cities": [
{"city": "FORT WORTH", "permits": 2219},
{"city": "DALLAS", "permits": 1377},
{"city": "AUSTIN", "permits": 1048},
{"city": "SAN ANTONIO", "permits": 849},
{"city": "MCKINNEY", "permits": 462}
],
"as_of": "2026-09-29T10:10:00Z",
"note": "... City attribution differs by design: metrics uses the permit's
own address_city, while search also matches the jurisdiction name ..."
}Query by bbox (a map viewport), polygon (a drawn GeoJSON area) or lat/lng/radius_miles, combined with category, property type, value and date filters. Spatial filters return geocoded permits only; a permit without coordinates is still reachable by city, ZIP or address.
# New construction in a Boulder map viewport since 2025
curl "https://api.permit-stack.com/v1/permits/search?bbox=-105.2900,40.0100,-105.2700,40.0250\
&category=new_construction\
&date_after=2025-01-01" \
-H "X-API-Key: pk_your_key_here"{
"total": 11,
"results": [
{"permit_number": "BLD-SFD2026-00429", "status": "FILED",
"category": "NEW_CONSTRUCTION", "property_type": "RESIDENTIAL",
"address_street": "[redacted]", "address_city": "Boulder",
"estimated_value": 134101.1, "date_filed": "2026-07-16",
"contractor_name": "FLATIRONS HABITAT FOR HUMANITY", ...},
...
],
"coverage": [{"jurisdiction": "Boulder", "data_through": "2026-09-27",
"status": "current", ...}]
}/v1/jurisdictions lists every source with its data-through date and plain-language labels for freshness, completeness, owner-address coverage and the trades it does not carry. They are the same sentences the export picker and delivered export manifests use. Surface them next to the data so your users see what we see.
# Every jurisdiction with freshness and completeness labels
curl "https://api.permit-stack.com/v1/jurisdictions" \
-H "X-API-Key: pk_your_key_here"{
"name": "Bessemer Building and Inspections", "state": "AL",
"data_status": "active",
"data_through": "2026-08-07",
"freshness_label": "Lagging -- data through 2026-08-07 (upstream access
blocked since 2026-08-18 (43d) -- the host refuses our requests
(HTTP 403); we cannot confirm whether the source itself has stopped)",
"completeness_label": "Complete -- we hold all ~259 records this
source publishes",
"owner_coverage_label": "No owner mailing data",
"trades_absent": ["electrical", "hvac", "new_construction", ...],
"total_records": 269, ...
}If you show permit data to your users, its gaps become your gaps. So the API states freshness, completeness and owner coverage per source, and never fills a missing value with a guess.
data_through is the newest permit we hold for a source, never the time we last polled it. Labels read current (under 45 days), lagging (under a year) or stale, and a blocked source says why.completeness_label compares our count with it. Where it does not, the label says completeness is not measured rather than implying complete.UNKNOWN, never invented.owner_coverage_label states it per jurisdiction. It is not included in CSV exports.total_capped. A count that cannot finish returns total_unknown instead of a number.The coverage check is free and needs no account. It answers with the permits we hold for a city over the last 12 months, the date each source's data runs through, and whether that source is current or lagging. The same box sits in the pricing section of the homepage.
curl "https://api.permit-stack.com/v1/coverage/check?city=Austin&state=TX"Business is the entry point for platforms because it includes the sync feed. Scale adds headroom for national pulls and faster support. Developer covers property lookups, metrics and webhooks for a prototype.
/v1/metrics monthly series and city rankingsfields=full on search/v1/permits/sync change feed (cursor-based)Every plan is self-serve through Stripe and you can start on the free tier (100 requests/day, last 30 days of permits). For licensing or redistribution, email support@permit-stack.com.
Yes. Our terms let you store and cache results indefinitely, combine them with other data, derive scores and analytics, and display permit records in a paid product. What they do not allow is reselling or redistributing the data as a dataset, or as a competing permit-data API or feed. For licensing or redistribution, email support@permit-stack.com.
Use /v1/permits/sync on Business ($149/mo) or Scale ($499/mo). Omit the cursor for the initial load, save next_cursor, and pass it back after each nightly ingest to receive only new and changed permits. The feed is upsert-only; source deletions are not emitted.
Sources are polled daily, with the main ingest at 03:00 UTC, and webhooks are dispatched within about 60 seconds of a permit reaching us. Some cities publish weeks after the fact, so every jurisdiction reports its own data_through date and a current, lagging or stale label.
117M+ permits from 887 active data sources in 8,000+ cities across 48 states and DC, plus 75 historical-archive jurisdictions for back-history. Coverage is uneven, so check the specific markets you serve with the free coverage check or /v1/jurisdictions.
Shovels covers more jurisdictions and publishes a free plan, with paid plans beginning at $599 per month. PermitStack's paid plans run $29 to $499 per month, self-serve, with a data-through date and freshness label on every source. Our comparison page lists the differences in detail.
Check before you pay. GET https://api.permit-stack.com/v1/coverage/check?city=Austin&state=TX needs no key and returns the permits we hold for that city over the last 12 months and how current each source is. The same check is in the pricing section of the homepage.
117M+ permits · 887 active data sources · 8,000+ cities · nightly change feed