Quickstart

From zero to a zoning answer.

1. Get a key

Sign in with your Pillar account, choose a plan, then create a key on Keys. The key is shown once. Store it as a server secret, for example PILLAR_API_KEY.

2. Look up a point

curl "https://api.pillar.codes/v1/zoning/lookup?lat=35.2271&lng=-80.8431" \
  -H "Authorization: Bearer $PILLAR_API_KEY"

Or from Node.js 18+:

const response = await fetch(
  'https://api.pillar.codes/v1/zoning/lookup?lat=35.2271&lng=-80.8431',
  { headers: { Authorization: `Bearer ${process.env.PILLAR_API_KEY}` } },
);
if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.code}: ${error.message}`);
}
const result = await response.json();
console.log(result.zoning.status, result.zoning.districts.map((d) => d.designator));

3. Read the result

{
  "data_version": "zm-…",
  "location": { "match": "inside" },
  "jurisdiction": {
    "id": "nc-municipality-3712000",
    "name": "Charlotte",
    "state": "NC",
    "page": "https://pillar.codes/zoning/nc/charlotte"
  },
  "zoning": {
    "status": "matched",
    "districts": [{
      "designator": "N1-A",
      "status": "available",
      "uses": [{
        "category": "single_family",
        "label": "Single-family",
        "status": "allowed",
        "evidence": [{ "use": "Single-family dwelling", "route": "by_right", "quote": "…" }]
      }],
      "standards": [{
        "field": "max_building_height_ft",
        "label": "Maximum height",
        "value": 48, "unit": "ft", "comparator": "max",
        "text": null, "derived": false, "quote": "…", "conditions": []
      }],
      "unverified": ["overlay_coverage_incomplete"]
    }]
  },
  "current_use": { "category": "Residential (1-4 Units)", "subcategory": "Single Family", "confidence": "confident", "estimate": true },
  "sources": [{ "title": "Charlotte Unified Development Ordinance", "url": "https://…" }],
  "notices": ["Likely, not verified: confirm with the jurisdiction before relying on it."]
}
  • zoning.status is matched, multiple_districts, not_matched, not_covered or no_parcel. See Coverage.
  • Each use’s status is allowed, allowed_with_approval, prohibited (only when the code says so), not_listed or unknown. Evidence rows quote the code.
  • Standards with conditions keep them in conditions; derived: true marks a computed value.
  • current_use is Pillar’s estimate, never a record.
  • Keep data_version with anything you store. It identifies exactly which data produced the answer.

Only matched and multiple_districts answers count toward your quota.