Documentation

PermitFlow API

A REST API for US construction permits and contractor licenses. JSON in, JSON out. Versioned. Webhook-friendly.

Authentication

All requests are authenticated with a bearer token. Get yours from the pricing page.

Authorization header
Authorization: Bearer pf_live_a1b2c3d4e5f6g7h8

List permits

GET/v1/permits

Returns a paginated list of permits, ordered by most recently issued.

ParamTypeDescription
citystringCity slug, e.g. phoenix
statestringTwo-letter state code, e.g. AZ
zipstringFilter by zip prefix
typestringsolar, hvac, roofing, pool, addition, electrical, commercial
sincedateISO date — only permits issued on/after
limitintMax 100 (default 50)
Request
curl https://permitflow.dev/api/public/v1/permits \
  -H "Authorization: Bearer pf_live_..." \
  -G \
  -d city=phoenix \
  -d type=solar \
  -d issued_since=2025-04-01 \
  -d limit=25
Response
{
  "data": [
    {
      "permit_number": "BLD2025-04123",
      "city": "Phoenix",
      "state": "AZ",
      "zip": "85016",
      "address": "2847 E Camelback Rd",
      "type": "Solar",
      "status": "Issued",
      "valuation": 24500,
      "description": "7.2kW rooftop solar PV system, 18 panels",
      "contractor": {
        "name": "SunPro Solar of Arizona",
        "license": "ROC-289341"
      },
      "issued_date": "2025-04-22",
      "applied_date": "2025-04-08"
    }
  ],
  "has_more": true,
  "next_cursor": "cur_a1b2c3"
}

Get permit

GET/v1/permits/{permit_number}
Request
curl https://permitflow.dev/api/public/v1/permits/BLD2025-04123 \
  -H "Authorization: Bearer pf_live_..."

Contractor lookup

GET/v1/contractors/{license_number}

Verify a contractor license against the source state board. Returns license status, classifications, expiration, and the last 90 days of permit activity.

Response
{
  "license_number": "ROC-289341",
  "name": "SunPro Solar of Arizona",
  "state": "AZ",
  "status": "Active",
  "classifications": ["C-11 Solar"],
  "expires": "2026-08-31",
  "permits_last_90d": 142
}

Webhooks

Subscribe to permit.issued and get a POST within minutes of new filings hitting source portals.

POST your endpoint
{
  "event": "permit.issued",
  "filter": { "city": "phoenix", "type": "solar" },
  "data": { /* permit object */ }
}

Errors

Standard HTTP codes. Errors return JSON:

Error response
{
  "error": {
    "code": "invalid_request",
    "message": "Unknown city slug: 'phenix'"
  }
}

Rate limits

Monthly call quota by plan, returned on every response in X-RateLimit-Limit and X-RateLimit-Remaining headers:

  • Free — 100 calls/mo
  • Starter — 10,000 calls/mo
  • Growth — 100,000 calls/mo
  • Scale — 1,000,000 calls/mo

Quota resets on the 1st of each month. Exceeding returns 429 quota_exceeded.