Developers
PlumbIntel API
REST + JSON access to Arizona building permits, the AZ ROC contractor roster, multi-permit project clusters, property characteristics, and contractor-relationship signals — the same intelligence the app runs on. Pipe it into your CRM, tools, or model. 1M+ permits across 25 Arizona jurisdictions, most refreshed daily.
- • All 12 read endpoints, every dataset
- • Up to 10,000 requests/day
- • Up to 5 API keys + the Plumb dashboard
- • Daily-fresh permits, contractors, parcels
✨ Start free — a 14-day trial with real data, no card required.
Quickstart
- Create a key under Settings → API access (org admins on an API-enabled plan). It’s shown once — store it securely. Pick Live or Test — test keys (
pk_test_…) read the same data but are capped at 1,000 req/day for dev & CI. - Send it as a bearer token on every request.
- Read the
dataenvelope back. That’s it.
Request
curl "https://plumbintel.com/api/v1/permits?jurisdiction=phoenix&freshness=hot&limit=2" \
-H "Authorization: Bearer pk_live_your_key_here"JavaScript
const res = await fetch(
"https://plumbintel.com/api/v1/permits?jurisdiction=phoenix&freshness=hot&limit=2",
{ headers: { Authorization: "Bearer pk_live_your_key_here" } },
);
const { data } = await res.json();
console.log(data.permits);Response (trimmed)
{
"data": {
"permits": [
{
"id": "fffcf083-c6cf-4b31-a1c9-f4bd32aff87d",
"permitNumber": "BLD-2026-03608",
"permitType": "Residential - New Single Family",
"workClass": "New",
"status": "Issued",
"lifecycleStage": "issued",
"leadFreshness": "hot",
"leadScore": 0.82,
"issueDate": "2026-06-22",
"valuationTotal": 412000,
"valuationImputed": null,
"valuationIsImputed": false,
"address": "1429 E PALM ST",
"city": "PHOENIX", "state": "AZ", "zip": "85006",
"apn": "11942003",
"jurisdiction": "phoenix",
"contractor": {
"license": "ROC123456",
"businessName": "DESERT SKY BUILDERS LLC",
"classification": "B-01",
"status": "Active",
"hasActiveDisciplinary": false
}
}
],
"hasMore": true
},
"count": 1
}The permit object
The core resource. Other endpoints reuse these fields; the contractor, parcel, and project objects are documented in the full API reference.
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Stable permit identifier — safe to store and join on. |
permitNumber | string | The jurisdiction’s own permit number. |
permitType | string | Permit type as filed by the jurisdiction. |
workClass | string | null | Work classification (e.g. New, Alteration, Reroof). |
status | string | Raw status text from the source portal. |
lifecycleStage | enum | Normalized stage: applied · issued · in_progress · finaled. |
leadFreshness | enum | Recency band for prospecting: hot · warm · cold · dead. |
leadScore | number | Lead-quality score from 0 to 1. |
issueDate | string (date) | null | ISO issue date. Null for applied-only permits (some feeds omit it). |
valuationTotal | number | null | Declared construction value as filed. 0 or null when the source didn’t report one. |
valuationImputed | number | null | Estimated value when none was filed — labeled, never blended into valuationTotal. |
valuationIsImputed | boolean | True when valuationImputed is the value to use. |
address / city / state / zip | string | null | Parsed site address components. |
apn | string | null | Normalized Maricopa County parcel number. |
jurisdiction | string | Source jurisdiction slug (e.g. phoenix, mesa). |
contractor | object | null | Contractor of record when resolved — license, businessName, classification, status, hasActiveDisciplinary. |
Conventions & rate limits
- Successful responses use the envelope
{ data, count?, notes? }. - List endpoints paginate with
limit(max 200) +offset, and returnhasMore. - Every response carries
X-RateLimit-Limit,-Remaining,-Reset(seconds to UTC midnight), and anX-Request-Idyou can quote in support. - Over your daily cap (10,000 req/day) — or a short per-minute burst — returns
429withRetry-After. - Server-to-server only — keys are secrets; don’t embed them in browser or mobile clients.
Errors
Every error returns the same shape with a stable code you can switch on (message text may change):
{
"error": {
"code": "invalid_api_key",
"message": "The provided API key is invalid or has been revoked."
},
"request_id": "8f1c2e4a-7b3d-4a1e-9c2f-5d6e7a8b9c0d"
}| Status | code | Meaning |
|---|---|---|
| 400 | invalid_request | A query, path, or body parameter is malformed (see error.details). |
| 401 | unauthorized · invalid_api_key | Missing, malformed, or revoked API key. |
| 403 | api_access_not_enabled | The organization has no active API entitlement. |
| 404 | not_found | No resource for that id, license, or APN. |
| 429 | rate_limited | Daily or per-minute cap reached — back off per the Retry-After header. |
Endpoint reference
Permits
/api/v1/permitsList permits
Filtered, paginated permit feed (~928K rows, daily-refreshed).
Query parameters
zip— Single ZIP codejurisdiction— phoenix | mesa | scottsdale | tempe | gilbert | peoriaworkClass— Case-insensitive contains match on work classlifecycle— applied | issued | in_progress | finaled | void | unknownfreshness— hot | warm | cold | deadvaluationMin— Minimum total valuationvaluationMax— Maximum total valuationissuedSince— Issued on/after (YYYY-MM-DD)issuedBefore— Issued on/before (YYYY-MM-DD)limit— Page size (max 200)offset— Result offset
/api/v1/permits/{id}Get a permit
Single permit by id, enriched with the parcel owner / property block.
Contractors
/api/v1/contractorsSearch contractors
AZ ROC roster (~64.6K) with the disciplinary / unlicensed-violator overlay.
Query parameters
q— Business-name contains (case-insensitive)classification— Exact ROC class code (e.g. 'B-01', 'CR-39')status— Exact status (e.g. 'Active')zip— Business ZIPcity— Business city (exact)hasDisciplinary— 'true' for only contractors with active disciplinarylimit— Page size (max 200)offset— Result offset
/api/v1/contractors/{license}Get a contractor
Single contractor by ROC license, with the nightly activity rollup.
/api/v1/contractors/{license}/relationshipsContractor relationship graph
Contractors who co-occur with this one at the same parcel within a time window.
Query parameters
windowMonths— Lookback months (max 60)coOccurrenceDays— ± days at same parcel (max 180)minFrequency— Min shared projects to surfacelimit— Max related contractors (max 100)
/api/v1/contractors/{license}/purchasing-profileInferred material-spend profile
Estimated annualized material spend per category from permit valuations + work-class mix.
Property & parcels
/api/v1/parcelsSearch property parcels
Maricopa County property records (~1.75M): owner, assessed value, type, year built, land use. Maricopa-only.
Query parameters
zip— Property ZIPpropertyType— Exact (e.g. 'SINGLE FAMILY', 'COMMERCIAL', 'VACANT')yearBuiltMin— Built on/afteryearBuiltMax— Built on/beforeassessedMin— Minimum assessed valueassessedMax— Maximum assessed valuelandUse— Land-use description containslimit— Page size (max 200)offset— Result offset
/api/v1/parcels/{apn}Get a property
Single parcel by APN (any format), with the most recent permits at that property.
Leads
/api/v1/leads/hotTop-ranked lead feed
Permits ranked by lead score, defaulted to fresh (hot/warm) — a ready-to-work outreach queue.
Query parameters
zip— Single ZIPjurisdiction— phoenix | mesa | scottsdale | tempe | gilbert | peoriaworkClass— Case-insensitive containsfreshness— Comma-separated subset of hot,warm,cold,dead (default 'hot,warm')minScore— Minimum lead score 0..1valuationMin— Minimum total valuationlimit— Page size (max 200)offset— Result offset
Projects
/api/v1/projectsList project clusters
Multi-permit projects (one parcel + address, 2-25 chained permits over 365d).
Query parameters
zip— Single ZIPactiveOnly— 'true' (default) = a permit in the last 90dminValuation— Minimum total project valuationlimit— Page size (max 200)offset— Result offset
Relationships
/api/v1/relationships/gapsGCs missing a recurring sub
General contractors with no recurring subcontractor in a target trade (a pitch list).
Query parameters
zip— Filter by the GC's modal ZIPworkClass— Target trade (contains)gapWorkClass— Trade to evaluate the gap in (defaults to workClass)minPermits12mo— Min GC permits in 365dmaxRegularSubs— A gap = no sub appears on more than this many permitslimit— Page size (max 200)offset— Result offset
Exports
/api/v1/exports/direct-mailDirect-mail CSV export
Owner-mailing-formatted CSV (one row per property/owner). Returns text/csv.
Query parameters
zips— Comma-separated ZIPsworkClasses— Comma-separated work classesvaluationMin— Min valuationvaluationMax— Max valuationsinceDays— Trailing window in days (max 365)freshness— Comma-separated freshness (default 'hot,warm')limit— Max rows (max 1000)
Versioning & changes
- The API is versioned in the path —
/api/v1(current version1.0.0). - We add fields and endpoints without notice — parse defensively and ignore unknown fields. We won’t remove or repurpose an existing v1 field.
- Breaking changes ship under a new version (
/api/v2); deprecations are announced here and viaDeprecation/Sunsetresponse headers with advance notice.
Changelog
- 2026-06-25 — Standard error envelope (
{ error: { code, message }, request_id }) +X-Request-Idon every response;offsetpagination on the lead, project, and relationship-gap feeds. - 2026-06-24 — Public v1 launch: permits, contractors, parcels, leads, projects, relationships, exports.
API use is subject to our Terms of Service — note in particular the redistribution restrictions (Section 7): API data is for use inside your own organization and may not be redistributed or resold.