Get a permit by canonical_uid
API Reference
Get a permit by canonical_uid
Per-permit detail endpoint. Returns one fully enriched row by its stable cross-jurisdictional canonical_uid — including the nested PLUTO presence + DQ object.
GET
Get a permit by canonical_uid
The per-permit detail endpoint. Returns a single fully enriched
The
The Encoding requirement — clients MUST
Every client MUST percent-encode the
Worked examples:
Skipping the encode is the most common integration mistake: an
unencoded
Elided fields above resolve from the same The nested
Returned when the path segment can be parsed but doesn’t conform to
the
Returned when the
Returned when the
JavaScript / TypeScript:
Python:
PermitResponse row by its stable cross-jurisdictional canonical_uid.
The shape returned is the same PermitResponse schema as
/v1/permits, with one difference: the
nested pluto object (PLUTO parcel-data presence + DQ status) is
populated here, NULL on the list endpoint — see the
asymmetry note.
Authentication
Authorization: Bearer <your-api-key> — see Authentication.
The canonical_uid path parameter
canonical_uid is the stable cross-jurisdictional permit identifier:
source_permit_id portion routinely contains characters that are
reserved or unsafe in a URL path segment.
Encoding requirement — clients MUST encodeURIComponent
Every client MUST percent-encode the canonical_uid before placing
it in the path (JavaScript: encodeURIComponent(canonical_uid);
Python: urllib.parse.quote(canonical_uid, safe="")). Four hostile
shape classes appear in real canonical_uid values:
| Character | Where it appears | Encoded form |
|---|---|---|
: | Jurisdiction separator — every canonical_uid | %3A |
| | NYC scaffold/class separator (e.g. Suspended Scaffold) | %7C |
(space) | Austin (e.g. 2026-066944 PP), Orlando | %20 |
/ | Orlando (e.g. BLD23/00099), fort_worth, philadelphia | %2F |
/ will be parsed as a path-segment break, and an unencoded
| or space is invalid in a URL path segment per RFC 3986. The server
returns 400 Malformed canonical_uid for the shapes it can detect at
parse time, and falls through to 404 for shapes that produce a
valid-looking but non-matching key.
Response shape
Identical toPermitResponse on /v1/permits — 53 fields including the enrichment set (cohort, dq_flags, top-level PLUTO-derived fields, description_llm_enriched). The differences on this endpoint are:
plutois populated when the row’sparcel_apnmatches a PLUTObblrow (NYC only today). For NYC rows where the parcel does not match a PLUTO row, AND for all non-NYC rows,plutoremainsnull.- The response body is the single row object — not wrapped in
items: [...]— and there is nopaginationenvelope.
PermitResponse schema — see the listing endpoint’s response shape for the full field list.
The nested pluto object semantics
pluto reports the PLUTO join + per-flag DQ status, not the PLUTO
values themselves (those are denormalized into top-level fields like
year_built, building_class).
is_placeholder—year_builtflagged as a placeholder in PLUTO.oob—year_builtflagged as out-of-bounds in PLUTO.
false when the join landed
but the upstream PLUTO DQ flag was NULL (the “rule has not flagged
this value” meaning). pluto: null (the field itself) means the join
didn’t land at all — either non-NYC, or no parcel_apn ↔ bbl match.
Errors
All error responses follow RFC 9457 problem+json — see Errors for the envelope.400 Malformed canonical_uid
Returned when the path segment can be parsed but doesn’t conform to
the {jurisdiction_id}:{source_permit_id} shape (e.g. missing the :
separator, or jurisdiction_id is non-numeric).
404 Permit not found
Returned when the canonical_uid is well-formed but no matching permit
exists.
422 Validation Error
Returned when the canonical_uid is path-parameter-invalid (rare —
typically caught at the framework layer before the endpoint runs).
Quotas
Quotas are tier-based and apply to every successful request against this endpoint. See Rate limits for the matrix- the
X-RateLimit-*response headers + the 429 problem+json shape.
Example request
Related
- Permits (listing endpoint) — the paginated browse path.
- Data freshness → field-level DQ flags — the 12-key
dq_flagsregistry + the SD-039 semantic. - Cohorts — the 18-cohort taxonomy that
cohortdraws from.