2026-07-20 — multifamily_mep is now a filterable target_segment
multifamily_mep (Multifamily MEP — multifamily mechanical, electrical, and
plumbing systems) was promoted into the API’s runtime target_segment validator
(pipeline PR #783). The canonical filterable segment enum on /v1/permits/target
went from 22 → 23, and multifamily_mep is now a valid target_segment and
cohort value. All 23 slugs are listed in Concepts → Cohorts.
2026-07-18 — Exports API, warehouse-native delivery, territory rollup
Three endpoint families that were live on the wire are now documented and announced.New endpoints
POST /v1/exports+GET /v1/exports+GET /v1/exports/{export_id}— asynchronous bulk CSV / XLSX exports of a filtered permit slice. Create a job, poll untilcompleted, download a short-lived signed URL. See Exports.GET /v1/exports/warehouse/latest— warehouse-native delivery: a manifest of the latest full-dataset drop as Parquet + gzipped CSV with signed R2 URLs, for loading straight into Snowflake / BigQuery / a lake.preserves_tristate_dq_flagskeeps the true/false/unknown DQ semantics intact.GET /v1/permits/target— the curated commercial / multifamily / ADU slice, filtered bytarget_segment(plusstate,metro_cbsa, value and enrichment filters). Same response envelope as/v1/permits; offset-only paging. See Permits → the/v1/permits/targetvariant.GET /v1/territory/rollup— grouped aggregate counts + valuation bystate/zip/metro_cbsa/jurisdiction, with the same filter surface as/target.
Segment taxonomy expanded to 22
The canonical segment taxonomy grew as new cohorts were admitted:commercial_hvac (2026-06-06), storage_residential (2026-06-23),
residential_pool (2026-06-26), and solar_residential. target_segment on
/v1/permits/target now accepts all 22 canonical segment slugs. See
Cohorts.
Error type URIs now resolve
Every RFC 9457 type URI the API emits (https://docs.permitcore.io/errors/<code>)
now resolves to a documented page under Errors → Error codes — so an
SDK can follow the type URI straight to a fix.
2026-06-27 — legacy_code removed from the 429 envelope
The deprecated legacy_code field (value "rate_limited"), retained for clients
written against the pre-RFC-9457 error shape, was removed from the 429
problem+json body. Branch on the type URI (and quota_kind) instead. See
Rate limits.
2026-06-04 — PD-7 enrichment promotion shipped
The enrichment fields are now on the live wire.New endpoint
-
GET /v1/permits/by-canonical-uid/{canonical_uid}— per-permit detail endpoint. Returns one fully enrichedPermitResponserow by its stable cross-jurisdictionalcanonical_uid. See Get a permit by canonical_uid for the encoding requirements + RFC 9457400/404shapes. Encoding heads-up: clients MUSTencodeURIComponentthecanonical_uidbefore placing it in the path. Real values contain:,|, spaces, AND/(e.g.1:982522764|Sidewalk Shed,182:BLD23/00099,85:2026-066944 PP). Skipping the encode is the most common integration mistake.
Additive fields on PermitResponse (both list + detail)
cohort— buyer-targeting bucket; one of the canonical segments, ornullfor unsegmented rows. Identical taxonomy totarget_segmenton/v1/permits/target. (The taxonomy has since grown to 23 — see the 2026-07-20 entry.)dq_flags— 12-key boolean object from the WS-PE-DQ-2 bounds-rule registry. Semantic note (SD-039):falseon a flag means “the rule has not flagged this value,” NOT “the value was independently verified clean.” NULL silver flag values are coerced tofalse. See Data freshness → field-level DQ flags for the full registry.- Top-level PLUTO-derived fields —
units_total,year_built,building_class,zoning_district,lot_area. Denormalized into the silver layer; populated where known. description_llm_enriched— LLM-extracted feature object (scope_summary,unit_count,square_footage,tenant_improvement_flag). Distinct column fromdescription_extracted. Coverage today: Austin + Chicagocommercial_newpermits only (~17,861 prod rows); broader cross-metro extraction is on the roadmap.
Nested pluto object — detail-endpoint only
The nested pluto object ({is_placeholder, oob} — PLUTO parcel-data
presence + per-flag DQ status, NYC only) is populated on
/v1/permits/by-canonical-uid/{canonical_uid} and ALWAYS null on
/v1/permits by design. The PLUTO LEFT JOIN required to populate
the DQ-status object would add ~75ms p95 to the list query, which
disqualifies it for the browse path. See the list-vs-detail
asymmetry note.
Docs corrections
- The previous
/v1/permitsexample’s “Coming with enrichment promotion” section is removed — the fields are on the wire now. - The data-freshness page’s “DQ flags appear in permit-listing responses” line flips to present tense.
- Corrected: the prior data-freshness DQ flag table listed
illustrative flag names (e.g.
val_zero,roof_estimated,addr_unmatched) that did not match the wire. Replaced with the canonical 12-key registry fromDqFlagsinopenapi.json(issued_date_*,valuation_usd_*,units_*,geocode_*).
2026-06-04 — /v1/permits example regenerated from live OpenAPI
The GET /v1/permits response example in the docs is now generated
from the live PermitResponse schema at
api.permitcore.io/openapi.json,
adopted as the permanent practice (examples are generated, never
hand-written, so the docs stop drifting from the wire).
Three documentation corrections rode along:
cohortremoved from the example. The/v1/permitsendpoint does not emit acohortfield today; the cohort surface is the aggregate/v1/jurisdictions/{slug}/cohorts/distributionendpoint and the/v1/permits/targetcurated variant. The plaincohort=query parameter on/v1/permitsarrives with the enrichment promotion (tracked alongside PD-7; lands within the Q2b window).dq_flagsremoved from the example. The 12-key DQ flag object is a pipeline-defined contract surfaced via the upstream recency artifact;/v1/permitsemission arrives with the same enrichment promotion. The data-freshness page’s “DQ flags appear in permit- listing responses” line has been reverted to roadmap phrasing.- Nested
plutoobject removed from the example. Same boat — documented when emission lands.
description_raw, current_status, geocode metadata
(lat/lng/geocode_confidence/geocode_source), architect_name,
engineer_name, owner_name, and the
first_seen_at/last_seen_at/last_changed_at timestamps.
2026-06-04 — Rate-limit reset surfaces now quota-kind-aware
TheX-RateLimit-Reset response header and the 429 problem+json envelope’s
reset_at field are now interpreted via the binding quota_kind:
daily— next UTC midnight (full ceiling restores at once).monthly— earliest moment usage ages out of the trailing 30-day window (slots restore progressively).- unlimited —
X-RateLimit-Resetis absent;reset_atis absent from the 429 body.
reset_at field has been added to the 429 envelope field map. The
previous “treat monthly 429s as non-sleepable” caveat is removed: both
kinds support sleep on retry_after_seconds / Retry-After /
X-RateLimit-Reset now. See Rate limits.
2026-06-04 — Bucket 2 shipped
The endpoint family announced at v1 launch as “Coming ~3 weeks (Bucket 2)” is live.Now live
GET /v1/permits— paginated permit-listing endpoint with cohort + jurisdiction + date filters. Returns per-row data with the field-level DQ flag object. See Permits (listing endpoint).POST /v1/keys+GET /v1/keys+DELETE /v1/keys/{prefix}— programmatic API key management. See API key management.GET /v1/keys/{prefix}/usage— per-key request counters + quota state. See API key management.- Tier-aware rate limits. Per-tier monthly request + export ceilings
enforced server-side. Every quota-gated response carries the
X-RateLimit-*header family (see Rate limits). - OpenAPI 3.1 spec at
https://api.permitcore.io/openapi.json— FastAPI-generated from the deployed code; always current. - Pricing: tier model simplified to Free / Pro (890/yr) / Enterprise. See permitcore.io/pricing for the buy flow.
2026-05-24 — v1 public launch
First public release.
Live at launch
GET /v1/jurisdictions/{slug}/cohorts/distribution— per-jurisdiction cohort breakdown across the canonical segment taxonomy (18 at launch; 23 today — see the 2026-07-20 entry). Cached 1 hour upstream (Cache-Control: max-age=3600).- US metro coverage across the top metros by permit volume — see the live map at permitcore.io/coverage and Concepts → Jurisdictions for the status model.
- Segment classification per permit via PermitCore’s LLM-1 classifier (18 segments at launch; 23 today). See Concepts → Cohorts.
- Free in-browser sandbox at permitcore.io/sandbox — client-side DuckDB-WASM queries against the last 10 days of permits across the live metros. No signup required.
- Self-serve signup + Stripe Checkout. See permitcore.io/pricing for the current tier breakdown.
Coming later
- Webhook stream — real-time permit-filing push delivery is on the roadmap and not yet available.
- Additional cohort splits (e.g., commercial_roofing, solar) are on the roadmap.
- Snowflake + BigQuery share endpoints for higher-volume customers.
- MCP server for AI-agent integration.
Deprecations
None as of this release.How to track changes
- This page is the canonical source.
- Major changes are also surfaced in the in-product
/accountdashboard. - Breaking changes are versioned (
/v2); the prior major version receives security patches but no new features.