Property permit intelligence
Roofing, HVAC, electrical and plumbing. One address in, four dated answers out — each one saying where the date came from and how sure it is.

A real result
| Date | Tags | Description |
|---|---|---|
| 2026-08-18filed | roofing | Remove and replace 16 sq roof. Owens corning duration storm shingles |
| 2026-03-19filed | roofing | Re-roof |
A real result, not a mock-up — address withheld. 2 permits on record. Open this report as a PDF — address absent from the file, not covered over.
Who this is for
Anyone whose decision changes when they learn the roof is twenty years old rather than two.
Underwriting, renewals and claims. Roof age decides whether a carrier writes it, and at what.
What was done, when, and whether it was permitted — before it becomes a disclosure argument.
Verify prior work on a property before you quote it: what was permitted, when, and which authority issued it.
Track what has actually been done across a portfolio rather than what the file says.
A permit history alongside the walkthrough, and a record of the work you cannot see.
Unpermitted additions and open permits, found before closing rather than after.
Permit records live in hundreds of separate county and city systems, each with its own search, its own login, and its own idea of what a date means. Checking one property is twenty minutes. Checking eight hundred is not something anyone does.
Permity answers in about a second, and will answer for a whole list from a CSV.
A twenty-year-old roof decides a renewal. An addition that raised replacement cost by forty thousand dollars against a limit that never moved is a claim waiting to happen. Work done without a permit is a disclosure problem for whoever sells the house next.
All of it is in the permit record, and none of it is in the file in front of you.
How to read it
This is the part most permit tools get wrong. “No roofing permit” and “this county does not report roofing permits” look identical if you render both as a blank. One of them prices a policy. The other sends an inspector. We never collapse them.
A permit, and a year we can stand behind.
No permit, and this jurisdiction reports well. Real signal: probably no permitted work.
A permit exists with no usable date. Work happened; when is unknown.
This jurisdiction barely reports. Absence here is not evidence of anything.
A permit record carries up to four dates and rarely all of them. We take the first that exists and always report which one it was, so you know whether a year means the work finished or only that somebody applied.
Measured on 100 Colorado roofing permits. The most truthful field is missing three times in four, so a single field will not do — and a 2012 filing is not a 2012 completion.
The honest weakness of any permit product is that unpermitted work is invisible. The street fixes it. When most of a block pulled a roofing permit the same year and one house did not, that silence is worth a question.
Where it stops
Unpermitted work leaves no record. A roof replaced without a permit is invisible here, and always will be. Absence of a permit is not absence of work.
Not every jurisdiction reports. Where coverage is thin we say so on the response rather than returning a confident blank.
We do not guess a year. Where a property has no permit for a trade but does have a build date, that inference is returned separately and labelled, never merged into the measured year.
A tool that is wrong once in the expensive direction never gets opened again. Read the API reference for exactly what each field means, or the questions page, which answers these three properly and shows a full report on a real house.
Coverage stated, not implied
| Date | Tags | Description |
|---|---|---|
| 2024-11-08completed | electrical, telecom | Remove 15 rrhs, 12 antennas, install 9 antennas, 1 bbu, 12 rrhs, relocates 1 antenna |
| 2022-04-18issued | electrical, telecom | The scope of work being proposed with this project includes the following details: rooftop work: • remove (2) existing antennas • replace with (6) c-band antennas • install (2) dc9 squids additional equipment changes will take place inside the enclosed equipment shelter with no additional shelter footprint. |
| 2019-05-22issued | electrical, telecom | Remove & replace 6 new antennas, 2 per sector *remove and replace 6 remote radioheads (rrh), 2 per sector *remove 3 rrh's, 1 per sector |
| 2016-03-16issued | telecom | Comm- cell site |
A real result, not a mock-up — address withheld. 8 permits on record. Open this report as a PDF — address absent from the file, not covered over.
See a sample report (PDF)
Real reports from sanitised inputs. The property is named by county, never by street — the address is not in the file at all.
What it does
A lookup is the start. The rest is what turns it from something you check into something that tells you what changed.
Upload a CSV and get a table back, your own columns carried through. Nobody wants one roof age — they want to know which of eight hundred renewals are sitting on twenty-year-old roofs before somebody else notices.
Download a template, drop in your addresses, get a CSV with four dated answers per row.
Unpermitted work is invisible to any permit product. The neighbours are the fix: when most of a block pulled a roofing permit the same year and one house did not, that silence is worth a question.
Every comparison states its denominator, so "3 of 22" never gets reported as "3".
A quote in flight, a claim in progress, a renewal in ninety days. A permit appearing means something changed at that property, and you find out when it lands rather than at renewal.
Webhook or dashboard. Only genuinely new permits notify — the existing ones are recorded at setup.
A signed, expiring link an underwriter, a client or a buyer can open. This work runs on forwarding documents to people who will never log in to your software.
Seven days by default, re-issuable, and the PDF renders from the stored data so it can never disagree with it.
Every dated answer names the authority standing behind it and how far that authority has published. Where two records of the same trade disagree, the report prints both counts rather than quietly choosing one.
On the report, under the trade it belongs to. No owner or contractor name is stored, so none is reported.
Point it at every address you already service and let it tell you what changed. An addition that raised replacement cost against a limit that never moved is a liability sitting in your own file.
Existing customers, so no cold-contact problem and no new data to buy.
Integrations
No app to install and no SDK to wait for. One authenticated POST, from wherever your work already happens.
Webhooks by Zapier → Custom Request. Nested fields flatten, so trades.roofing.year arrives as Trades Roofing Year.
POST https://permity.valyaai.us
/v1/permits/lookup
X-API-Key: $PERMITY_KEY
{"address": "{{address}}"}HTTP → Make a request, then a Router on status. The parsed body is a collection, so {{2.trades.roofing.year}} addresses it directly.
Method POST Body Raw / JSON Parse Yes Router ok | ambiguous | else
Anything that speaks HTTP. Signed webhooks, idempotency keys and a delivery log for when something goes wrong at 2am.
const r = await fetch(url, {
method: "POST",
headers: { "X-API-Key": key },
body: JSON.stringify({ address }),
})Capabilities
Everything the screens do is one authenticated POST away. Built for the tools this work actually runs on — no proprietary app to install, no SDK to wait for.
It is how everyone tests this, and the fastest way to find out whether it is worth anything to you.