DataJackpot API

One REST API for US property data: 36M+ building permits and certificates of occupancy, 51M+ assessor parcels, and 2.9M+ licensed contractors. Refreshed continuously, and sourced in part directly from town clerks, so it includes records that are not posted online anywhere else.

Quick start

  1. Email henry@datajackpot.net for an API key. Your key looks like dj_live_… and may be scoped to permits, parcels, contractors, or all three.
  2. Send the key on every request as a bearer token.
  3. Make your first call:
curl "https://datajackpot.net/api/v1/permits?state=NY&permit_type=roofing&limit=5" \
  -H "Authorization: Bearer dj_live_your_key_here"

Python

import requests

BASE = "https://datajackpot.net/api/v1"
HEADERS = {"Authorization": "Bearer dj_live_your_key_here"}

r = requests.get(f"{BASE}/permits",
                 params={"state": "NY", "permit_type": "roofing", "limit": 5},
                 headers=HEADERS)
print(r.json()["data"])

JavaScript

const res = await fetch(
  "https://datajackpot.net/api/v1/permits?state=NY&permit_type=roofing&limit=5",
  { headers: { Authorization: "Bearer dj_live_your_key_here" } }
);
const { data } = await res.json();
console.log(data);

Authentication

Send your key as a bearer token (or the X-API-Key header) on every request. Keys are secret. Keep them server-side. If a key is ever exposed, email us and we will rotate it.

Authorization: Bearer dj_live_your_key_here

Each key carries scopes that control which datasets it can read (permits, parcels, contractors). Calling an endpoint your key is not scoped for returns 403.

Permits

GET https://datajackpot.net/api/v1/permits — building permits, plus certificates of occupancy and new-construction parcels via record_class.

Parameters (all optional)

Response shape

{
  "data": [
    {
      "id": "…",
      "town": "NYC - Brooklyn",
      "state": "NY",
      "permit_number": "B-2026-01234",
      "permit_type": "roofing",
      "permit_status": "issued",
      "date_filed": "2026-03-31",
      "date_issued": "2026-04-05",
      "property_address": "75 Poplar St",
      "owner_name": "…",
      "contractor_name": "…",
      "contractor_phone": "…",
      "project_value": 18500,
      "work_description": "Re-roof, asphalt shingle",
      "record_class": "permit"
    }
  ],
  "returned": 100,
  "next_cursor": "…"   // null when there are no more pages
}

Single record: GET https://datajackpot.net/api/v1/permits/{id}.

Parcels

GET https://datajackpot.net/api/v1/parcels — 51M+ assessor records: owner, year built, building size, land use, assessed value, and last sale. Requires the parcels scope.

curl "https://datajackpot.net/api/v1/parcels?state=OH&county_name=Franklin&year_built_from=2020&limit=100" \
  -H "Authorization: Bearer dj_live_your_key_here"

Contractors

GET https://datajackpot.net/api/v1/contractors — 2.9M+ licensed contractors: business name, license, classification, contact, bond and insurance. Requires the contractors scope.

curl "https://datajackpot.net/api/v1/contractors?state=FL&classification=gc&license_status=Active&limit=100" \
  -H "Authorization: Bearer dj_live_your_key_here"

Browse coverage

Town names are source-specific (e.g. NYC - Bronx). Look them up rather than guessing, so a typo does not return an empty result.

GET https://datajackpot.net/api/v1/states            -> states we cover, with town + record counts
GET https://datajackpot.net/api/v1/towns?state=NY    -> exact town names in a state, with counts
GET https://datajackpot.net/api/v1/permit-types      -> permit_type categories + record types

A permit search that matches no town returns a hint field pointing you to /towns.

Paging through results

Results come in pages of up to 1000. Each response returns a next_cursor. Pass it back to get the next page, and stop when it is null. Pagination is stable and complete, even across tens of millions of rows.

import requests
BASE = "https://datajackpot.net/api/v1"
H = {"Authorization": "Bearer dj_live_your_key_here"}

cursor, all_rows = None, []
while True:
    r = requests.get(f"{BASE}/permits",
                     params={"state": "NJ", "limit": 1000, "cursor": cursor},
                     headers=H).json()
    all_rows += r["data"]
    cursor = r["next_cursor"]
    if not cursor:
        break
print(len(all_rows), "permits")

Common recipes

New roofing permits in NY this month

GET https://datajackpot.net/api/v1/permits?state=NY&permit_type=roofing&date_filed_from=2026-06-01

Certificates of occupancy in a state

GET https://datajackpot.net/api/v1/permits?state=NY&record_class=certificate_of_occupancy

Homes built since 2020 in a county

GET https://datajackpot.net/api/v1/parcels?state=OH&county_name=Franklin&year_built_from=2020

Active general contractors in Florida

GET https://datajackpot.net/api/v1/contractors?state=FL&classification=gc&license_status=Active

Recent high-value sales

GET https://datajackpot.net/api/v1/parcels?state=NC&sale_date_from=2026-01-01&assessed_min=500000

Limits & billing

Errors

Questions? henry@datajackpot.net · datajackpot.net