Puller API

A read-only REST API for building permits, the properties they sit on and the contractors who pull them, across15 places in Nevada and Texas. Every response is JSON, and permit lists also come as CSV.

On this site: Change events and the data dictionary.

Make a first request

The base URL is https://api.pullerdata.com. Every /v1 request needs your key in the x-api-key header. Keys are issued by hand: request access and we will send one.

curl "https://api.pullerdata.com/v1/permits?region=las_vegas&tag=solar&issued_after=2026-09-01&limit=2" \
  -H "x-api-key: YOUR_KEY"

A list answers with a page of rows and a cursor for the next page:

{
  "data": [ { "region": "las_vegas", "permit_number": "...", "issue_date": "2026-10-14", "contractors": [ ... ], ... } ],
  "next_cursor": "eyJ..."
}

Rules every route follows

Rate limit
60 requests a minute per key, and 120 requests a minute per client address. Over either, you get a 429 with a Retry-After header in seconds.
Strict parameters
An unknown parameter, a repeated one or a bad value gets a 400 whose error names it, for example {"error":"limit: must be an integer from 1 to 500"}. A list parameter takes one value or several separated by commas.
Dates and times
Dates are YYYY-MM-DD and ranges include both ends. Times are ISO 8601 with a zone, such as 2026-10-09T00:00:00Z; send a + offset as %2B.
Paging
Permit and property lists are newest first and use a keyset cursor. Pass next_cursor back as cursor with the same filters until it comes back null. Change events come oldest first (see change events), and a contractor search returns one page with no cursor.
Removed records
A permit the agency no longer publishes is not served by any route.

Routes

Every route is a GET.

The routes of the Puller API.
RouteReturns
/healthAnswers {"ok": true}. No key needed.
/v1/permitsPermits of every region, or of the regions you name, newest issue date first. Filters below.
/v1/regions/{region}/permits/{permit_number}One permit with its contractors, fee lines, inspections, plan review steps and the parcel's planning cases. URL-encode the number.
/v1/permits/{permit_number}One Austin permit, by number alone.
/v1/propertiesFind properties by street address or parcel number, in every region or the ones you name.
/v1/properties/{parcel_id}One property, in whichever region holds the parcel.
/v1/regions/{region}/propertiesFind one region's properties by street address.
/v1/regions/{region}/properties/{parcel_id}One property: a summary, one row per trade, the parcel's facts, its sales and planning cases, and a page of its permits.
/v1/eventsChanges to permits' status and dates, oldest first. See change events.
/v1/contractorsSearch contractor licences by licence number or by business name.
/v1/contractors/{id}One licence with its permit totals, the people the board lists for it and the board's disciplinary actions.
/v1/meta/dictionaryThe full data dictionary, with each field's sources, as JSON.
/v1/meta/coverageFill rates of each field per region, with permit counts and the first and last issue dates.

A permit's fees, inspections, review_steps and planning_cases are empty arrays where its region publishes none; the coverage table shows which places publish what.

Filtering permits

/v1/permits takes these parameters. Filters combine with AND; the values inside one list parameter combine with OR.

Parameters of /v1/permits.
ParameterMatches
regionOne or more region ids. Without it, every region.
tagWork tags such as solar, roofing, hvac, pool_spa or new_construction.
permit_typePermit type codes, as each region writes them. With region, only that region's codes are accepted.
statusfinal, closed, active, in_review or inactive.
permit_classResidential or Commercial.
zipOne or more 5-digit ZIP codes.
contractor_idPermits that name this licence.
zoning_baseA base zoning district as the region writes it, such as SF or R-1.
council_district, county_commission_districtThe ward or commission district the permit falls in.
issued_after, issued_beforeIssue date range, both ends included. applied_from/applied_to and completed_from/completed_to work the same way.
updated_sincePermits whose served record changed at or after this time, new permits included.
min_value, max_valueJob valuation range in dollars.
geolat,lng,radius_m: permits within the radius (1 to 50,000 m) of the point.
bboxmin_lng,min_lat,max_lng,max_lat: permits inside the box.
parcel_id, owner_nameA parcel number, or the start of an owner name (case-insensitive).
has_fees, has_inspectionstrue or false.
fieldsOnly these columns, plus region, permit_number and issue_date. The nested contractors come back only when you name contractors.
limit1 to 500, default 50.
cursorThe next_cursor of the previous page.
formatjson (the default) or csv.

CSV

Add format=csv to get one row per permit, without the nested contractors. The next cursor comes in the x-next-cursor response header.

curl "https://api.pullerdata.com/v1/permits?region=henderson&format=csv&limit=500" \
  -H "x-api-key: YOUR_KEY" -D headers.txt -o page1.csv

Contractors

/v1/contractors takes exactly one of license_number (exact; a short Nevada number is also tried padded to seven digits) and name (the start of the business name, ignoring case, punctuation and company suffixes). Add board=nscb for Nevada State Contractors Board licences or board=tdlr for Texas ones. limit runs from 1 to 100, default 20.

/v1/contractors/{id} adds the licence's totals over its matched permits, the principals and qualified individuals the board lists, and the board's disciplinary actions, newest first. To list a contractor's permits, call /v1/permits?contractor_id= with its id.

Region ids

Use these ids in region and in the region routes.

Region ids and the places they cover.
IdPlace
austinAustin
las_vegasLas Vegas
hendersonHenderson
clark_countyunincorporated Clark County
mesquiteMesquite
renoReno
sparksSparks
washoe_countyunincorporated Washoe County
carson_cityCarson City
north_las_vegasNorth Las Vegas
douglas_countyDouglas County
boulder_cityBoulder City
elkoElko
fernleyFernley
lyon_countyLyon County

Errors

An error answers {"error": "..."} with one of these status codes.

Error status codes.
StatusMeaning
400A parameter is unknown, repeated or invalid. The error names it.
401The key is missing, unknown or revoked.
404No such permit, property or contractor.
429Over the rate limit. Wait the seconds in Retry-After.
500Our fault. Retry later, or write to us if it persists.