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
429with aRetry-Afterheader in seconds. - Strict parameters
- An unknown parameter, a repeated one or a bad value gets a
400whoseerrornames 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-DDand ranges include both ends. Times are ISO 8601 with a zone, such as2026-10-09T00:00:00Z; send a+offset as%2B. - Paging
- Permit and property lists are newest first and use a keyset cursor. Pass
next_cursorback ascursorwith the same filters until it comes backnull. 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.
| Route | Returns |
|---|---|
/health | Answers {"ok": true}. No key needed. |
/v1/permits | Permits 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/properties | Find 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}/properties | Find 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/events | Changes to permits' status and dates, oldest first. See change events. |
/v1/contractors | Search 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/dictionary | The full data dictionary, with each field's sources, as JSON. |
/v1/meta/coverage | Fill 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.
| Parameter | Matches |
|---|---|
region | One or more region ids. Without it, every region. |
tag | Work tags such as solar, roofing, hvac, pool_spa or new_construction. |
permit_type | Permit type codes, as each region writes them. With region, only that region's codes are accepted. |
status | final, closed, active, in_review or inactive. |
permit_class | Residential or Commercial. |
zip | One or more 5-digit ZIP codes. |
contractor_id | Permits that name this licence. |
zoning_base | A base zoning district as the region writes it, such as SF or R-1. |
council_district, county_commission_district | The ward or commission district the permit falls in. |
issued_after, issued_before | Issue date range, both ends included. applied_from/applied_to and completed_from/completed_to work the same way. |
updated_since | Permits whose served record changed at or after this time, new permits included. |
min_value, max_value | Job valuation range in dollars. |
geo | lat,lng,radius_m: permits within the radius (1 to 50,000 m) of the point. |
bbox | min_lng,min_lat,max_lng,max_lat: permits inside the box. |
parcel_id, owner_name | A parcel number, or the start of an owner name (case-insensitive). |
has_fees, has_inspections | true or false. |
fields | Only these columns, plus region, permit_number and issue_date. The nested contractors come back only when you name contractors. |
limit | 1 to 500, default 50. |
cursor | The next_cursor of the previous page. |
format | json (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.csvContractors
/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.
| Id | Place |
|---|---|
austin | Austin |
las_vegas | Las Vegas |
henderson | Henderson |
clark_county | unincorporated Clark County |
mesquite | Mesquite |
reno | Reno |
sparks | Sparks |
washoe_county | unincorporated Washoe County |
carson_city | Carson City |
north_las_vegas | North Las Vegas |
douglas_county | Douglas County |
boulder_city | Boulder City |
elko | Elko |
fernley | Fernley |
lyon_county | Lyon County |
Errors
An error answers {"error": "..."} with one of these status codes.
| Status | Meaning |
|---|---|
| 400 | A parameter is unknown, repeated or invalid. The error names it. |
| 401 | The key is missing, unknown or revoked. |
| 404 | No such permit, property or contractor. |
| 429 | Over the rate limit. Wait the seconds in Retry-After. |
| 500 | Our fault. Retry later, or write to us if it persists. |