API Reference

All endpoints return JSON and are CORS-enabled. Base URL: https://lotlyze.com. API access is included with a Pro subscription. Upgrade at lotlyze.com/sign-up to receive your API key. For Chicago addresses and Cook County PINs, use /api/chicago-units; the other property endpoints cover NYC. Response examples are shortened, and their values are illustrative; field names match the live API.

Authentication

Pass your API key in the Authorization header on every request. Free accounts have no API access. Requests without a valid Pro key return 401.

curl
curl "https://lotlyze.com/api/lookup?query=3016070023" \
  -H "Authorization: Bearer YOUR_API_KEY"
JavaScript / fetch
const API_KEY = "YOUR_API_KEY"; // from lotlyze.com/account

const res = await fetch(
  "https://lotlyze.com/api/lookup?query=3016070023",
  { headers: { Authorization: `Bearer ${API_KEY}` } }
);
const data = await res.json();
Python
import httpx

API_KEY = "YOUR_API_KEY"  # from lotlyze.com/account
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

data = httpx.get(
    "https://lotlyze.com/api/lookup",
    params={"query": "3016070023"},
    headers=HEADERS,
).json()

Where to find your key

  1. Sign in at lotlyze.com/sign-in
  2. Go to My Account
  3. Copy the key from the API Key section
  4. Use it in the Authorization: Bearer <key> header

Error responses

StatusMeaningAction
400Missing or invalid parameterCheck the parameter format for the endpoint
401Missing or invalid API keyUpgrade at lotlyze.com/sign-up for Pro API access
404No property matches the query (lookup, property)Check the address, BBL, or BIN
429Request volume temporarily limitedRetry after a short delay
500 / 502A public data source failed or timed outRetry after a short delay
503Auth service temporarily unavailableRetry after a short delay
GET/api/lookup

Resolve any NYC address, BBL, or BIN to canonical identifiers.

Parameters

NameTypeRequiredDescription
querystringYesAddress, 10-digit BBL, hyphenated BBL, or 7-digit BIN

Example

curl
curl "https://lotlyze.com/api/lookup?query=250+Broadway+Manhattan" \
  -H "Authorization: Bearer YOUR_API_KEY"
JavaScript
const res = await fetch(
  "https://lotlyze.com/api/lookup?query=250+Broadway+Manhattan",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } }
);
const { bbl, bin, label } = await res.json();

Response

{
  "type": "address",
  "bbl": "1001247502",
  "bin": "1001408",
  "label": "250 B'WAY, New York, NY, USA",
  "source": "geosearch"
}

For a BBL or BIN query, type is bbl or bin, source is pad, and there is no label. The bin field can be null when no building is on file for the lot. An unknown BIN or address returns 404.

GET/api/chicago-units

Look up the best public evidence of a Chicago 2–6 unit residential building's dwelling-unit count, plus building facts, the owner of record, the Assessor's value, the last permit for each building system, permits, violations, and sales history. Zoning, nearby district classes, parcel coordinates, and 2021 parcel outlines are available for all Chicago property classes, including those with an unsupported unit count. Optionally compare user-entered listing figures. Requires a Pro API key.

Parameters

NameTypeRequiredDescription
querystringYesChicago street address, 14-digit Cook County PIN (dashes accepted), or a Chicago Redfin/Zillow property URL. Only the address in the URL is read; no listing is fetched. Resolved query maximum: 200 characters.
pricenumberNoAsking price ($). 1–1,000,000,000, increments of 0.01. Blank means unknown.
unitsnumberNoListing units. 1–1,000, increments of 1. Blank means unknown.
bedroomsnumberNoListing bedrooms. 0–1,000, increments of 1. Blank means unknown.
bathsnumberNoListing baths (half = 0.5). 0–1,000, increments of 0.5. Blank means unknown.
buildingSqftnumberNoListing building sq ft. 1–10,000,000, increments of 0.01. Blank means unknown.
landSqftnumberNoListing lot sq ft. 1–100,000,000, increments of 0.01. Blank means unknown.
rent1–rent6numberNoLegacy listing-comparison assumptions: 0–100,000 dollars/month, increments of 0.01. Blank is unknown, not zero. Use unitRent1–unitRent6 for return calculations.
investmentPricenumberNoPurchase-price assumption in dollars, greater than zero and at most 1 billion. Defaults to Assessor market value if available.
unitRent1–unitRent6numberNoMonthly gross-rent assumptions, 0–100,000 dollars. Explicit zero is preserved. Blank uses HUD for selected bedrooms, then ACS tract median gross rent if available.
rentBedrooms1–rentBedrooms6integerNo0–4 bedrooms per unit; 0 means studio. Used only when that unit's entered rent is absent, with the latest baked HUD ZIP SAFMR. No unit mix is inferred from total building bedrooms.
vacancyPctnumberNo0–99.99 percent; defaults to the township low-rise apartment model when available.
expensePctnumberNo0–100 percent of collected rent for non-tax operating expenses. When absent, model total expenses are split into tax and non-tax portions to avoid double-counting tax.
annualTaxnumberNo0–10,000,000 dollars; replaces the rough public tax estimate. All underwriting inputs accept at most two decimal places; duplicates, signs, commas, and exponents are rejected.

Real example: 2121 N Laporte Ave, Chicago

curl — address
curl "https://lotlyze.com/api/chicago-units?query=2121+N+Laporte+Ave,+Chicago" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl — Cook County PIN (same property)
curl "https://lotlyze.com/api/chicago-units?query=13332200130000" \
  -H "Authorization: Bearer YOUR_API_KEY"

Listing comparison example

/api/chicago-units?query=13233210110000&price=799000&units=2&bedrooms=6&baths=3&landSqft=6250&rent1=1800&rent2=1800

These are user assumptions, not verified listing data. Listing inputs do not alter the shared report snapshot. Numeric inputs use plain decimal numbers without currency signs, commas, or exponents; duplicate inputs are rejected. Website listing comparison is currently paused; this API contract remains available. Query strings may appear in access logs; do not include private tenant information.

Unlevered return example

/api/chicago-units?query=13233210110000&investmentPrice=600000&unitRent1=2000&unitRent2=2000&vacancyPct=5&expensePct=30&annualTax=10000

These assumptions yield $48,000 gross rent/year, $45,600 collected rent, $13,680 non-tax expenses, $10,000 tax, $21,920 NOI, 3.6533% cap rate, and 12.5 GRM. Underwriting is separate from listing comparison and never saved in the shared public snapshot. Missing inputs or benchmarks producestatus: incomplete with explicit missing reasons; unknown is not zero. Blank price uses Assessor market value. Blank unit rents use HUD when bedrooms are specified, otherwise the ACS tract median gross rent if available; no unit bedroom mix is inferred. Blank tax, vacancy, and expenses use the report's public estimates/model. Results identify applied price and rent sources; entered values (including zero where allowed) take precedence. No debt, capital repairs, closing costs, or income taxes are included.

Response excerpt

Public source records checked October 19, 2026. Permit 101073592, issued April 7, 2026, states a total of 3 dwelling units; the Assessor lists 2. The permit takes precedence and mismatch: true flags the disagreement. Owner fields are placeholders here; geography is an illustrative shape and its polygon features are omitted for brevity. Live results may change as source records are updated. An issued permit does not prove the work was completed or establish legal occupancy.

{
  "status": "ok",
  "pin": "13332200130000",
  "pins": [
    "13332200130000"
  ],
  "address": "2121 N LAPORTE AVE 1",
  "assessorClass": "211",
  "units": 3,
  "source": "permit",
  "assessorUnits": 2,
  "mismatch": true,
  "permit": {
    "units": 3,
    "permitNumber": "101073592",
    "issueDate": "2026-04-07",
    "text": "SRP 2019 CBRC: INTERIOR & EXTERIOR ALTERATIONS IN EXISTING 2-STORY BRICK MULTI-UNIT RESIDENCE (2DU) IN ORDER TO CONVERT EXISTING UNFINISHED FIRST FLOOR LEVEL INTO NEW DWELLING UNIT FOR TOTAL OF 3 DWELLING UNITS. MECHANICAL, ELECTRICAL & PLUMBING, CONVERT EXISTING REAR OPEN WOOD PORCH TO REAR ENCLOSED WOOD PORCH PER PLANS.OCCUPANCY CLASSIFICATION: R-5 CONSTRUCTION TYPE: III-B"
  },
  "facts": {
    "yearBuilt": 1914,
    "buildingSqft": 2405,
    "landSqft": 3780,
    "bedrooms": 4,
    "fullBaths": 2,
    "halfBaths": 0,
    "heat": "Warm Air Furnace",
    "airConditioning": "No Central A/C",
    "roof": "Shingle + Asphalt",
    "basement": "Full, unfinished",
    "attic": "None",
    "porch": "None",
    "garage": "2 cars, detached, frame",
    "exteriorWall": "Masonry",
    "condition": "Average"
  },
  "owner": {
    "name": "OWNER NAME",
    "mailingAddress": "MAILING ADDRESS, BOLINGBROOK, IL 60490",
    "likelyOwnerOccupied": false
  },
  "assessment": {
    "year": 2026,
    "stage": "mailed",
    "assessedValue": 38000,
    "marketValue": 380000
  },
  "lastPermitBySystem": {
    "roof": null,
    "porch": {
      "permitNumber": "101073592",
      "issueDate": "2026-04-07"
    },
    "masonry": null,
    "electrical": {
      "permitNumber": "101073592",
      "issueDate": "2026-04-07"
    },
    "plumbing": {
      "permitNumber": "101073592",
      "issueDate": "2026-04-07"
    },
    "heating": {
      "permitNumber": "101073592",
      "issueDate": "2026-04-07"
    },
    "windows": null
  },
  "checkedAt": "2026-10-19T13:07:15.000Z",
  "listing": null,
  "comparison": [],
  "location": {
    "latitude": 41.9198,
    "longitude": -87.7406,
    "sourceYear": 2026
  },
  "geography": {
    "status": "available",
    "zoning": {
      "districts": [
        {
          "code": "RT-4",
          "description": "Residential two-flat / townhome"
        }
      ],
      "nearbyDistricts": [
        "RS-3",
        "RT-4"
      ],
      "nearbyRadiusMeters": 402.336,
      "density": {
        "lotSqftPerUnit": 1000,
        "approximateUnits": 3
      },
      "sourceUrl": "https://data.cityofchicago.org/d/dj47-wfun",
      "rulesUrl": "https://www.chicago.gov/city/en/depts/dcd/supp_info/zoning_ordinance.html"
    },
    "parcelOutlines": {
      "year": 2021,
      "sourceUrl": "https://datacatalog.cookcountyil.gov/d/77tz-riq7",
      "missingPin10s": [],
      "geojson": {
        "type": "FeatureCollection",
        "features": []
      }
    },
    "errors": []
  },
  "disclaimer": "Best public evidence, not a certified legal unit count.",
  "verifyUrl": "https://www.chicago.gov/city/en/depts/dcd/supp_info/legal-unit-count.html"
}

Response fields

FieldDescription
statusok, unsupported (outside Chicago, or not a 2–6 unit residential building), or not_found.
pin14-digit Cook County key PIN of the property. A tied side lot returns its key PIN's report.
pinsEvery PIN in the property, key PIN first. Tied PINs (such as a side lot) share one building.
addressStreet address from the Cook County Assessor.
cityMunicipality from the Assessor, e.g. CHICAGO.
assessorClassCurrent Assessor class; 211 is a 2–6 unit apartment building.
classDescriptionPlain-English building type for the class, or null.
unitsBest public evidence of the dwelling-unit count, or null.
sourceWhere units came from: permit or assessor; null when unknown.
assessorUnitsApartment count recorded by the Assessor, or null.
permitNewest permit stating a unit total ({units, permitNumber, issueDate, text}), or null.
mismatchtrue when the permit and Assessor counts disagree.
factsAssessor building facts for the key PIN's first building ({yearBuilt, buildingSqft, landSqft, bedrooms, fullBaths, halfBaths, heat, airConditioning, roof, basement, attic, porch, garage, exteriorWall, condition}), or null. landSqft is summed across pins.
ownerAssessor owner of record and tax-bill mailing address ({name, mailingAddress, likelyOwnerOccupied}), or null. likelyOwnerOccupied is true when bills are mailed to the property.
assessmentLatest Assessor value summed across pins ({year, stage, assessedValue, marketValue}), or null. stage is board, certified, or mailed; marketValue is assessedValue ÷ 10% for residential classes, else null.
permitsUp to 200 most recent City building permits at the street address.
lastPermitBySystemNewest permit whose wording mentions each building system ({roof, porch, masonry, electrical, plumbing, heating, windows}: {permitNumber, issueDate} or null). A keyword match; no permit on record doesn't mean no work was done.
violationsUp to 200 most recent City building violations at the street address.
salesUp to 20 most recent Assessor-recorded sales for the key PIN.
locationParcel-point coordinates from the Cook County parcel universe ({latitude, longitude, sourceYear}), or null.
contextAll-class Chicago location context: sourced transit distances/approximate walking times, bus stops, noise/flood indicators, CMAP walkability, community/ward/TIF, distress/development, and building 311 requests. Includes crime: {status,communityArea,years:[{year,areaCount,cityCount}],comparison,errors}. Crime is reported property-crime record counts for five completed calendar years (FBI codes 05/06/07/09), with a same-year population-normalized comparison when all 77 ACS area estimates are valid. comparison includes year, populationPeriod, areaPopulation, cityPopulation, areaRate, cityRate (per 1,000 residents), percentDifference. City population is the sum of the 77 estimates. No safety score or temporal-trend claim; CPD warns against comparisons over time. Context null outside Chicago.
marketClass-211 neighborhood comps (18 months) and 12-calendar-year sale trend, 2024-rate tax estimate, and township 7+-unit low-rise income-model assumptions. Includes status/errors, source links, period, sample counts/truncation, pricePerUnit/pricePerSqft {count,median,q1,q3}, weightedPricePerUnit (recency-weighted average), ten similar comps with coordinates, trend {year,medianPrice,sales,partialYear}, tax {annual,assessmentYear,assessedValue,year,equalizer,rate,equalizerUrl,rateUrl}, and assumptions {year,township,samples,vacancy,expenseRatio,capRate,sourceUrl}. Not an appraisal, tax bill, or small-building operating forecast.
rentBenchmarksClass-211 baked HUD ZIP SAFMR and Census ACS 5-year tract rents: {zip,tract,status,safmr,acs}. Each source has status, source and latest/history records, or an explicit missing reason. SAFMR records are {year,byBedrooms} (studio–4BR); ACS records are {year,medianGrossRent,byBedrooms} (studio–5+BR). Monthly gross-rent benchmarks, not live asking/lease comps. Null for unsupported reports; missing while provider data has not been baked.
underwritingRequest-only {inputs,results} unlevered return estimate. Results include status/missing, grossAnnualRent, effectiveGrossIncome, nonTaxExpenses, taxes, noi, capRate (fraction), grm, pricePerUnit, pricePerUnitVsMedian (dollars), monthlyRents, rentSources, vacancyPct, nonTaxExpensePct, modelExpenseRatio. Unknown stays null. Inputs and results are never saved in the public snapshot.
geographyZoning and map context for all Chicago property classes: {status, zoning, parcelOutlines, errors}. status is available, partial, unavailable, or outside_chicago. zoning contains districts ({code, description}), nearbyDistricts within about 1/4 mile, nearbyRadiusMeters, density ({lotSqftPerUnit, approximateUnits} or null), sourceUrl, rulesUrl. Density is a base lot-area screening ratio, not permitted/legal units. parcelOutlines contains year (2021), sourceUrl, missingPin10s, and a GeoJSON FeatureCollection keyed by PIN10. Boundaries may be outdated.
listingUser inputs ({price, units, bedrooms, baths, buildingSqft, landSqft, monthlyRents}), or null when omitted. Each figure can be null; monthlyRents has six nullable entries. Not part of the shared snapshot.
comparisonOne entry per supplied comparable figure: {field, label, listed, recorded, delta, status, source, explanation}. delta is listing minus record; status is matches, differs, or unavailable. Price compares to Assessor market value, not an appraisal. Empty when no listing figures are supplied or status is not ok.
checkedAtWhen Lotlyze last checked the public sources (ISO 8601). Reports refresh after 24 hours.
disclaimerReminder that this is public evidence, not a certified legal unit count.
verifyUrlCity page for requesting a certified unit count.

City permits and violations match the street address and may miss other addresses on the parcel. A property can span several Cook County PINs: a tied side-lot PIN returns its key PIN's report, and pins lists them all. Reports refresh after 24 hours; checkedAt shows when the sources were last checked. This is not a certified legal unit count: request City verification before relying on it for a purchase or zoning decision.

Geography is evaluated at the Assessor's parcel point, not every boundary of a split-zoned lot. The density screen uses base lot area per dwelling unit for RS-1, RS-2, RS-3, RT-3.5, RT-4, RM-4.5, and RM-5 only; other or multiple districts return density: null. It is not an allowed/legal-unit count or ADU determination. Tied tax PINs need not be one zoning lot.geography.errors identifies missing sources, coordinates, or outdated/missing outlines. Failed geography sources produce an explicit partial/unavailable result rather than removing the core report.

context is available for every Chicago class. Transit distances are straight-line; walking estimates assume 3 mph, not a walking route. CMAP bands split the 10–130 range into thirds, not Walk Score. Traffic, rail, and airport data are noise proxies, not measured building sound. FEMA/First Street indicators are not insurance advice. Building-related 311 requests are address-matched allegations, not confirmed violations; the latest 50 are returned with a truncation flag. Each metric retains its source vintage; some are older than the report check.

market is for class 211. Comps use the same Assessor neighborhood and the preceding 18 months, exclude multi-parcel and Assessor-flagged sales, remove tied buildings, and keep one latest sale per PIN. Quartiles use linear interpolation; weightedPricePerUnit weights each sale linearly from 0.5 (oldest) to 1 (newest). Ten properties are ranked by unit-count match, then building area. Statistics cover all joined eligible properties (at most 1,000 input sales, with truncated flagged). Current Assessor facts may differ from sale-date facts. The 12-calendar-year median sale trend is not a repeat-sales index; the current year is partial. Tax estimates multiply the property's latest AV by the 2024 equalizer 3.0355 and Chicago average composite rate 6.619%, before exemptions. They mix assessment/rate years and are not actual bills or forecasts; check the Treasurer for each PIN. Income defaults are township medians for 7+-unit low-rise apartments, not observed 2–6-flat operations.

rentBenchmarks comes from an offline annual bake, not per-request provider calls. HUD SAFMR is a ZIP gross-rent benchmark, not asking rent; ACS is a lagged tract median from overlapping five-year samples on 2020 tract boundaries. Nominal histories retain each fiscal/vintage year. HUD fallback requires an explicit per-unit bedroom count and includes tenant-paid utilities. Provider data not yet baked returns explicit missing statuses rather than estimated rents. The Assessor model expense ratio is treated as all-in: non-tax expense defaults to max(0, model ratio × collected rent − taxes). A supplied expensePct instead means non-tax expenses, with taxes deducted separately.

status is ok, unsupported (outside the supported residential class or outside Chicago), or not_found. These outcomes return HTTP 200; a unit count can be null when evidence is unavailable. Missing or overlong queries, unsupported listing URLs, and invalid listing inputs return 400; upstream data failures return 502. Without a valid Pro key, requests return 401.

GET/api/property

NYC all-in-one: resolves an address, BBL, or BIN, then returns its identifiers, ACRIS records, and DOB records in one request.

Parameters

NameTypeRequiredDescription
querystringYesAddress, 10-digit BBL, hyphenated BBL, or 7-digit BIN

Example

curl
curl "https://lotlyze.com/api/property?query=534+Kosciuszko+St+Brooklyn" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "lookup": {
    "address": "534 KOSCIUSZKO STREET, Brooklyn, NY, USA",
    "bbl": "3016070023",
    "bbl_formatted": "3-01607-0023",
    "bin": "3043452",
    "borough": "Brooklyn",
    "block": "01607",
    "lot": "0023",
    "latitude": 40.6926,
    "longitude": -73.932574
  },
  "acris": {
    "records": [
      {
        "id": "2019061400456001",
        "date": "2019-06-14",
        "type": "DEED",
        "description": "DEED",
        "party1": "SELLER NAME",
        "party2": "BUYER NAME",
        "amount": 1250000,
        "formatted_amount": "$1,250,000"
      }
    ],
    "count": 1
  },
  "dob": {
    "permits": [],
    "jobFilings": [],
    "dobNow": [],
    "violations": [],
    "complaints": []
  }
}

address, latitude, and longitude are only filled for address queries. ACRIS records here have no category and use formatted_amount. Each DOB list holds up to 20 raw NYC Open Data rows since January 1, 2020, newest first. An unknown address or BIN returns 404.

GET/api/acris

Fetch ACRIS deed and document records for a property.

Parameters

NameTypeRequiredDescription
bblstringYes10-digit Borough-Block-Lot

Example

curl
curl "https://lotlyze.com/api/acris?bbl=1000477501" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "bbl": "1000477501",
  "records": [
    {
      "id": "2023012700123456",
      "date": "2023-01-27",
      "type": "DEED",
      "description": "DEED",
      "category": "deed",
      "party1": "SELLER NAME",
      "party2": "BUYER NAME",
      "amount": 4500000,
      "formattedAmount": "$4,500,000"
    }
  ],
  "count": 1
}

Records are newest first. category is deed, mortgage, lien, ucc, satisfaction, or other. A BBL with no ACRIS records returns {"bbl": "…", "records": []} without a count.

GET/api/dob

Fetch DOB permits, job filings, violations, and complaints for a building.

Parameters

NameTypeRequiredDescription
binstringYes7-digit Building ID Number

Example

curl
curl "https://lotlyze.com/api/dob?bin=1001074" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "bin": "1001074",
  "permits": [
    {
      "job__": "102657000",
      "permit_type": "SG",
      "issuance_date": "2000-10-20",
      "source_system": "DOB_Socrata"
    }
  ],
  "jobFilings": [
    {
      "job__": "140641321",
      "job_type": "A3",
      "latest_action_date": "12/06/2018",
      "source_system": "DOB_Socrata"
    }
  ],
  "dobNow": [
    {
      "job_filing_number": "M00001019-I1",
      "work_permit": "M00001019-I1-FN",
      "approved_date": "2017-10-30T12:13:00.000",
      "source_system": "DOB_NOW"
    }
  ],
  "violations": [],
  "complaints": [
    {
      "complaint_number": "1411462",
      "status": "CLOSED",
      "date_entered": "12/03/2015",
      "source_system": "DOB_Socrata"
    }
  ]
}

Each list holds up to 20 raw NYC Open Data rows, newest first, using the source dataset's field names, plus a source_system tag. Rows are shortened above.

GET/api/hpd

HPD housing-code violations and complaints for a property.

Parameters

NameTypeRequiredDescription
bblstringYes10-digit or hyphenated Borough-Block-Lot

Example

curl
curl "https://lotlyze.com/api/hpd?bbl=3016070023" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "bbl": "3016070023",
  "violations": [
    {
      "orderId": "12345678",
      "class": "B",
      "description": "§ 27-2026 ADM CODE REPAIR THE LEAKY FAUCET IN THE BATHROOM",
      "inspectionDate": "2024-05-02",
      "issuedDate": "2024-05-03",
      "status": "NOV SENT OUT",
      "apartment": "2",
      "source": "HPD"
    }
  ],
  "complaints": [
    {
      "complaintId": "3447477",
      "type": "EMERGENCY",
      "status": "CLOSE",
      "openedDate": "2006-09-13",
      "closedDate": "2006-09-17",
      "source": "HPD"
    }
  ]
}

Up to 50 violations, newest inspection first. Complaint problem rows are grouped by complaint, so one complaint can list several types; closedDate is empty until the complaint closes.

GET/api/ecb

ECB/OATH violations for a building, with the total unpaid balance.

Parameters

NameTypeRequiredDescription
binstringYes7-digit Building ID Number

Example

curl
curl "https://lotlyze.com/api/ecb?bin=3043452" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "bin": "3043452",
  "violations": [
    {
      "violationId": "34847088Z",
      "respondent": "OWNER NAME",
      "description": "FAILURE TO MAINTAIN BLDG IN CODE COMPLIANT MANNER.",
      "violationType": "Construction",
      "agency": "DOB",
      "issueDate": "20100423",
      "hearingDate": "20100614",
      "penaltyTotal": 5000,
      "balanceDue": 0,
      "status": "RESOLVE",
      "source": "ECB"
    }
  ],
  "totalBalanceDue": 0
}

Up to 50 violations, newest first. Dates are YYYYMMDD strings, as published, and totalBalanceDue is the sum of balanceDue across the returned violations.

GET/api/tax

NYC Department of Finance assessment for a property.

Parameters

NameTypeRequiredDescription
bblstringYes10-digit or hyphenated Borough-Block-Lot

Example

curl
curl "https://lotlyze.com/api/tax?bbl=3016070023" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "bbl": "3016070023",
  "assessment": {
    "bbl": "3016070023",
    "taxClass": "1",
    "marketValue": 1355000,
    "assessedValue": 81300,
    "exemptValue": 0,
    "taxableAssessedValue": 21919,
    "annualTax": 4349.39,
    "annualTaxIsEstimate": true,
    "assessmentYear": "2027",
    "taxRateYear": "25/26",
    "taxRatePercent": 19.843,
    "has421a": null,
    "stabilizationIndicator": null,
    "source": "DOF"
  }
}

assessment is null when Finance has no record for the BBL. The annual tax is an estimate: the latest published rate for the tax class is applied to the DOF taxable assessed value, and does not account for property-specific credits. The current assessment dataset does not identify 421-a exemptions, so has421a and stabilizationIndicator are null.

GET/api/summary

NYC full summary: ACRIS, DOB, HPD, ECB, and Finance tax data in a single request. Resolves BBL to BIN automatically.

Parameters

NameTypeRequiredDescription
bblstringYes10-digit or hyphenated Borough-Block-Lot

Example

curl
curl "https://lotlyze.com/api/summary?bbl=3016070023" \
  -H "Authorization: Bearer YOUR_API_KEY"
Python
import httpx

API_KEY = "YOUR_API_KEY"

data = httpx.get(
    "https://lotlyze.com/api/summary",
    params={"bbl": "3016070023"},
    headers={"Authorization": f"Bearer {API_KEY}"},
).json()

print(data["acris"][0]["date"])   # most recent deed date
print(len(data["dob"]["violations"]))

Response

{
  "bbl": "3016070023",
  "bin": "3043452",
  "borough": "Brooklyn",
  "acris": [
    {
      "id": "2019061400456001",
      "date": "2019-06-14",
      "type": "DEED",
      "description": "DEED",
      "category": "deed",
      "party1": "SELLER NAME",
      "party2": "BUYER NAME",
      "amount": 1250000,
      "formattedAmount": "$1,250,000"
    }
  ],
  "hpd": {
    "violations": [],
    "complaints": [
      {
        "complaintId": "3447477",
        "type": "EMERGENCY",
        "status": "CLOSE",
        "openedDate": "2006-09-13",
        "closedDate": "2006-09-17",
        "source": "HPD"
      }
    ]
  },
  "ecb": {
    "violations": [],
    "totalBalanceDue": 0
  },
  "tax": {
    "bbl": "3016070023",
    "taxClass": "1",
    "marketValue": 1355000,
    "assessedValue": 81300,
    "exemptValue": 0,
    "taxableAssessedValue": 21919,
    "annualTax": 4349.39,
    "annualTaxIsEstimate": true,
    "assessmentYear": "2027",
    "taxRateYear": "25/26",
    "taxRatePercent": 19.843,
    "has421a": null,
    "stabilizationIndicator": null,
    "source": "DOF"
  },
  "dob": {
    "permits": [
      {
        "job__": "321234567",
        "issuance_date": "2021-03-02",
        "source_system": "DOB_Socrata"
      }
    ],
    "jobFilings": [],
    "dobNow": [],
    "violations": [],
    "complaints": []
  }
}

Unlike the single-source endpoints, acris is a plain array of records, HPD violations omit issuedDate, ECB violations omit status, and tax is the flat assessment plus bbl (or null). Each DOB list holds up to 20 rows, newest first, tagged with source_system.

GETPOST/api/bulkPro only

Look up to 50 NYC BBLs in a single request: identifiers, ACRIS records, and DOB records for each. Send a JSON body with POST, or a comma-separated bbls parameter with GET.

Parameters

NameTypeRequiredDescription
bblsstring[] (POST body) or comma-separated string (GET)Yes10-digit or hyphenated BBLs. Max 50.

Example

curl — POST
curl -X POST "https://lotlyze.com/api/bulk" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"bbls": ["3016070023", "1004770001", "4015670023"]}'
curl — GET
curl "https://lotlyze.com/api/bulk?bbls=3016070023,1004770001" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "count": 1,
  "results": [
    {
      "bbl": "3016070023",
      "ok": true,
      "data": {
        "bbl": "3016070023",
        "bbl_formatted": "3-01607-0023",
        "bin": "3043452",
        "borough": "Brooklyn",
        "block": "01607",
        "lot": "0023",
        "acris": {
          "records": [
            {
              "id": "2019061400456001",
              "date": "2019-06-14",
              "type": "DEED",
              "description": "DEED",
              "party1": "SELLER NAME",
              "party2": "BUYER NAME",
              "amount": 1250000,
              "formatted_amount": "$1,250,000"
            }
          ],
          "count": 1
        },
        "dob": {
          "permits": [],
          "jobFilings": [],
          "dobNow": [],
          "violations": [],
          "complaints": []
        }
      }
    }
  ]
}

Every result has ok. Successful results carry data; a BBL whose lookup failed carries error instead, without failing the whole request. ACRIS records use formatted_amount, and each DOB list holds up to 20 raw NYC Open Data rows since January 1, 2020. A missing or malformed list, more than 50 BBLs, or any invalid BBL returns 400.

Rate limits & tiers

TierPriceAPI accessBulk endpoint
Free$0 / moNo API accessNo
Pro$1 / moUnlimited API accessYes (50 BBLs/req)

Include your API key in the Authorization: Bearer <key> header. Keys are provisioned automatically on upgrade — visit your account.