Permit Data API

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.

Free 100 requests/day — no key required, keyed by IP.  ·  Paid Unlimited — API key required, available at /app/settings → API Keys. Contractor name & license number returned only for paid key holders.

Authentication

Anonymous (free tier)

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

API Key (unlimited, paid subscribers only)

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.

Base URL

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.

Endpoints

GET /permits

List permits with filters. Returns up to 200 per page. Sorted by newest first.

ParameterTypeDescription
citystringMetro slug (e.g. austin, nyc, chicago). See /metros for full list.
tradestringTrade tag (e.g. hvac, roofing). See /trades.
zipstring5-digit ZIP code.
min_valuenumberMinimum declared job value in USD.
min_hot_scorenumberMinimum hot score (0–100). 80+ = hot, 50–79 = warm.
sinceISO dateOnly permits filed on or after this date. Format: 2025-01-01.
limitnumberResults per page. Default 50, max 200.
cursornumberPagination 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"
GET /permits/:id

Fetch a single permit by its numeric ID.

curl https://permitpulseos.com/api/public/v1/permits/123456
GET /metros

List supported metros with total permit counts.

curl https://permitpulseos.com/api/public/v1/metros
GET /trades

List supported trade tags with permit counts across all metros.

curl https://permitpulseos.com/api/public/v1/trades

Response Schema

Permit object

FieldTypeDescription
idnumberUnique permit ID.
citystringMetro slug (e.g. austin).
zipstringZIP code.
tradestring | nullPrimary trade tag.
tradesstring[]All matched trade tags.
declared_valuenumber | nullDeclared job value in USD.
permit_dateISO date | nullFiled date (YYYY-MM-DD).
last_synced_atISO datetime | nullLast time this record was updated from source.
hot_scorenumber | nullPermitPulse intent score, 0–100.
hot_score_bucketstringhot (≥80), warm (50–79), cold, or unknown.
permit_typestring | nullRaw permit type string from source.
descriptionstring | nullWork description (when available).
address_redactedstringStreet name + city (street number stripped for privacy).
contractor_namestring | nullContractor of record. Paid key only
contractor_licensestring | nullContractor license number. Paid key only

Meta block

FieldTypeDescription
countnumberNumber of results in this response.
next_cursornumber | nullPass as cursor to get the next page. Null when no more pages.
rate_limit_remainingnumber | nullRequests remaining today (free tier only, null for API key).
rate_limit_resetISO datetime | nullWhen the daily rate limit resets (free tier only).

Example response

{
  "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"
  }
}

Supported Metro Slugs

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

Error Codes

StatusMeaning
400Bad request — invalid parameter (e.g. malformed date, non-numeric ID).
401Invalid or revoked API key.
404Permit not found.
429Free-tier rate limit exceeded. Check Retry-After header.
500Internal server error — transient, retry with exponential backoff.

Pull permits into your stack

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