PermitCore refreshes permit data daily from each metro’s open-data portal. Cohort classification, DQ flagging, and parcel join happen in the same nightly pipeline.Documentation Index
Fetch the complete documentation index at: https://docs.permitcore.io/llms.txt
Use this file to discover all available pages before exploring further.
Refresh cadence
- Source pull: every metro’s open-data portal is pulled once per 24 hours, scheduled per metro to land before 02:00 local time.
- Cohort classify + DQ flag: runs immediately after each source pull. Adds ~15 minutes per metro for the classifier pass.
- Site + API publish: updated rows land in the API by 02:30 local
time per metro. The cohort distribution endpoint caches 1 hour
(
Cache-Control: max-age=3600).
The as_of_utc field
Every API response that returns aggregated state includes an as_of_utc
timestamp marking when the underlying data was last computed:
ISR caching on the site
The PermitCore site (permitcore.io) consumes the same cohort distribution endpoint via Next.js ISR withrevalidate: 3600. So the site’s cohort
breakdowns lag the underlying data by at most 1 hour beyond the
upstream pipeline’s own latency.
For real-time-critical use cases (e.g., webhook-driven CRM lead loading),
use the future /v1/permits endpoint directly + the webhook stream
shipping in Bucket 2+.
Field-level data-quality flags
Every permit row carries up to 12 data-quality flags surfaced per field. These tell you which fields are measured vs inferred vs placeholder:| Flag | Meaning |
|---|---|
val_zero | Valuation column is 0; treat as missing not as $0 |
val_missing | Valuation absent from source data |
roof_estimated | Roof area estimated via parcel join; not measured |
roof_missing | Roof area unavailable |
addr_unmatched | Address didn’t match the parcel layer; geometry absent |
type_ambiguous | Permit type couldn’t be cleanly classified to one cohort |
…and 6 more (see /v1/permits reference, shipping ~3 weeks) |