Pull building permit filings across 21 metros into your CRM, dashboard, or app. JSON REST API with cursor pagination, hot-score filtering, and trade tagging.
No key required. Rate-limited to 100 requests per UTC day per IP address. Contractor name and license are anonymized.
# No auth header needed
curl https://permitpulseos.com/api/public/v1/permits?city=austin&limit=5
Pass your key in the X-API-Key header or as ?api_key= query param.
Get your key at /app/settings → API Keys.
# Header (recommended)
curl -H "X-API-Key: ppk_your_key_here" \
https://permitpulseos.com/api/public/v1/permits?city=chicago&min_hot_score=70
# Query param (for quick testing)
curl "https://permitpulseos.com/api/public/v1/permits?city=chicago&api_key=ppk_your_key_here"
When rate limited, you'll receive a 429 response with a Retry-After header
(seconds until midnight UTC) and a meta.rate_limit_reset timestamp.
https://permitpulseos.com/api/public/v1
All endpoints return Content-Type: application/json with CORS headers
(Access-Control-Allow-Origin: *) — safe to call from browser or server.
List permits with filters. Returns up to 200 per page. Sorted by newest first.
| Parameter | Type | Description |
|---|---|---|
| city | string | Metro slug (e.g. austin, nyc, chicago). See /metros for full list. |
| trade | string | Trade tag (e.g. hvac, roofing). See /trades. |
| zip | string | 5-digit ZIP code. |
| min_value | number | Minimum declared job value in USD. |
| min_hot_score | number | Minimum hot score (0–100). 80+ = hot, 50–79 = warm. |
| since | ISO date | Only permits filed on or after this date. Format: 2025-01-01. |
| limit | number | Results per page. Default 50, max 200. |
| cursor | number | Pagination cursor from previous response's meta.next_cursor. |
# Hot HVAC permits in Austin, sorted by newest
curl "https://permitpulseos.com/api/public/v1/permits?city=austin&trade=hvac&min_hot_score=70"
# Paginate with cursor
curl "https://permitpulseos.com/api/public/v1/permits?city=chicago&limit=100&cursor=PREVIOUS_CURSOR"
Fetch a single permit by its numeric ID.
curl https://permitpulseos.com/api/public/v1/permits/123456
List supported metros with total permit counts.
curl https://permitpulseos.com/api/public/v1/metros
List supported trade tags with permit counts across all metros.
curl https://permitpulseos.com/api/public/v1/trades
| Field | Type | Description |
|---|---|---|
| id | number | Unique permit ID. |
| city | string | Metro slug (e.g. austin). |
| zip | string | ZIP code. |
| trade | string | null | Primary trade tag. |
| trades | string[] | All matched trade tags. |
| declared_value | number | null | Declared job value in USD. |
| permit_date | ISO date | null | Filed date (YYYY-MM-DD). |
| last_synced_at | ISO datetime | null | Last time this record was updated from source. |
| hot_score | number | null | PermitPulse intent score, 0–100. |
| hot_score_bucket | string | hot (≥80), warm (50–79), cold, or unknown. |
| permit_type | string | null | Raw permit type string from source. |
| description | string | null | Work description (when available). |
| address_redacted | string | Street name + city (street number stripped for privacy). |
| contractor_name | string | null | Contractor of record. Paid key only |
| contractor_license | string | null | Contractor license number. Paid key only |
| Field | Type | Description |
|---|---|---|
| count | number | Number of results in this response. |
| next_cursor | number | null | Pass as cursor to get the next page. Null when no more pages. |
| rate_limit_remaining | number | null | Requests remaining today (free tier only, null for API key). |
| rate_limit_reset | ISO datetime | null | When the daily rate limit resets (free tier only). |
{
"data": [
{
"id": 482901,
"city": "austin",
"zip": "78704",
"trade": "hvac",
"trades": ["hvac"],
"declared_value": 12500,
"permit_date": "2026-06-15",
"hot_score": 87,
"hot_score_bucket": "hot",
"permit_type": "Mechanical",
"description": "Install new HVAC system",
"address_redacted": "South Congress Ave, Austin",
"contractor_name": null, // null for free tier
"contractor_license": null
}
],
"meta": {
"count": 1,
"next_cursor": 482900,
"rate_limit_remaining": 94,
"rate_limit_reset": "2026-06-19T00:00:00.000Z"
}
}
Use these in the ?city= filter.
nyc
New York City
chicago
Chicago
sf
San Francisco
la
Los Angeles
austin
Austin
seattle
Seattle
boston
Boston
dc
Washington DC
minneapolis
Minneapolis
new_orleans
New Orleans
philadelphia
Philadelphia
denver
Denver
phoenix
Phoenix
houston
Houston
dallas
Dallas
miami
Miami
atlanta
Atlanta
san_diego
San Diego
nj
New Jersey
seacoast_nh
Seacoast NH
| Status | Meaning |
|---|---|
| 400 | Bad request — invalid parameter (e.g. malformed date, non-numeric ID). |
| 401 | Invalid or revoked API key. |
| 404 | Permit not found. |
| 429 | Free-tier rate limit exceeded. Check Retry-After header. |
| 500 | Internal server error — transient, retry with exponential backoff. |
Get an API key at /app/settings after signing up. Free trial — card required, not charged for 7 days.
Start free trial → get API key