Skip to main content
One permit as the issuing city or county filed it. GET /v1/properties/{property_id}/permits returns it. A parcel search row summarises the same permits in its permits block. The recent-permit, major-work-permit and open-permit quicklists read them.

Status

The parcel’s n_open_permits_12m counts a permit that is active or in_review and older than a year. Such a permit is a signal of work started and abandoned, not of work in progress. status is null where the jurisdiction reports none.

Tags and major work

type, subtype and description are the jurisdiction’s own words and differ between cities. tags[] is the normalised reading of them, for example Solar or Pool and Hot Tub, and it is empty when nothing matched. major_work is true for the five tags that change a house: Addition, ADU, New Construction, Pool and Hot Tub, Solar. A tag adds a fact and never removes one. A permit with an empty tags[] still describes real work: its words did not match a normalised label. Filter on tags to find something, not to exclude something.

The fields a reader misreads

  • job_value is what the applicant declared, and only about half of the Maricopa permits report one. Null is “not reported”, so a sum is a lower bound. It is never a valuation of the house.
  • The three durations are calendar days: approval_duration_days from filing to issue, construction_duration_days from issue to final, total_duration_days from filing to final. Each is null while the permit lacks a date it needs, which is normal on an open permit.
  • inspection_pass_rate is a share from 0 to 1, and is null where the jurisdiction reports no inspections.
  • id is stable across snapshots, so you can follow a permit from one load to the next.

What is never served

Applicant names, phones and email addresses. The permit files carry them on some rows. The pipeline loads them and drops them before the served tier, for every key and every scope. So this object has no contact field, and no scope unlocks one.

One building permit on the parcel. The API never serves applicant names, phones and addresses.

id
string
required

Permit id, stable across snapshots (32 hex).

jurisdiction
string | null
required

The issuing city or county, upper case; null when the delivery does not record it.

permit_number
string | null
required

The jurisdiction's own number; null when the delivery does not record it.

type
string | null
required

The jurisdiction's own type label; null when the delivery does not record it.

subtype
string | null
required

The jurisdiction's own subtype; null when the delivery does not record it.

status
enum<string> | null
required

Null when the jurisdiction reports none. Permit status as the jurisdiction reports it. The values: final (closed out), active (issued, work under way), inactive (lapsed or closed, no final), in_review (applied for, not issued).

Available options:
final,
active,
inactive,
in_review
description
string | null
required

The permit description as filed; null when the delivery does not record it.

tags
string[]
required

The normalised work tags that apply, for example ["Solar"], ["Pool and Hot Tub"], ["New Construction"]. Empty when none.

major_work
boolean
required

True when the tags include Addition, ADU, New Construction, Pool and Hot Tub or Solar.

file_date
string | null
required

Application date.

issue_date
string | null
required

Issue date.

final_date
string | null
required

Final inspection or close-out date.

job_value
integer | null
required

Declared job value; null when the jurisdiction reports none. Most jurisdictions report none.

Required range: -9007199254740991 <= x <= 9007199254740991
fees
number | null
required

Fees paid; null when the delivery does not record it.

inspection_pass_rate
number | null
required

Share of inspections passed, 0 to 1; null when the jurisdiction reports no inspections.

approval_duration_days
integer | null
required

Days from filing to issue; null when either date is null.

Required range: -9007199254740991 <= x <= 9007199254740991
construction_duration_days
integer | null
required

Days from issue to final; null when either date is null.

Required range: -9007199254740991 <= x <= 9007199254740991
total_duration_days
integer | null
required

Days from filing to final; null when either date is null.

Required range: -9007199254740991 <= x <= 9007199254740991