Step 2 — Visit your Dashboard and generate an API key. Copy the key and store it securely.
Base URL: All examples use http://localhost:8000. Replace with your production domain in deployment.
Use your_api_key_here as a placeholder — never commit real keys to source control.
2 Zoning Lookup API Key
Look up zoning rules for any parcel by ID and city code. Returns the district, FAR, height limits, setbacks, and overlays.
The /interpret endpoint returns a plain-English summary, viable development paths, risk signals, approval difficulty, and a decision frame for any parcel.
GET /api/v1/parcel/{parcel_id}/interpret?city=nyc
resp = requests.get(
f"{BASE}/parcel/1008720030/interpret",
params={"city": "nyc"},
headers={"X-API-Key": API_KEY},
)
result = resp.json()
print(result["summary"])
print(f"Decision: {result['decision_summary']}")
print(f"Approval difficulty: {result['approval_difficulty_label']}")
print(f"Confidence: {result['effective_confidence']}")
for sig in result.get("risk_signals", []):
print(f" [{sig['severity']}] {sig['category']}: {sig['rationale']}")
const resp = await fetch(
`${BASE}/parcel/1008720030/interpret?city=nyc`,
{ headers: { "X-API-Key": API_KEY } }
);
const result = await resp.json();
console.log(result.summary);
console.log(`Decision: ${result.decision_summary}`);
console.log(`Approval difficulty: ${result.approval_difficulty_label}`);
console.log(`Confidence: ${result.effective_confidence}`);
for (const sig of result.risk_signals || []) {
console.log(` [${sig.severity}] ${sig.category}: ${sig.rationale}`);
}
{
"summary": "This R6B parcel in NYC appears feasible for residential development...",
"viable_paths": [
{ "path": "by_right", "description": "Residential up to FAR 2.0" }
],
"red_flags": [],
"citations": ["NYC ZR \u00a723-145", "NYC ZR \u00a723-632"],
"confidence": 0.85,
"confidence_label": "HIGH",
"risk_signals": [
{
"category": "LEGAL_COMPLEXITY",
"severity": "LOW",
"rationale": "Simple by-right path with no overlays",
"evidence": ["Single district, no special permits"],
"confidence": 0.9
}
],
"approval_difficulty": 10,
"approval_difficulty_label": "EASY",
"dead_end": false,
"effective_confidence": 0.85,
"decision_summary": "Good candidate"
}
Tip: You can also append ?interpret=true to the standard
/api/v1/zoning/{id} endpoint to get zoning data with interpretation included in a single call.
4 Search Parcels API Key
Find parcels using structured filters. Supports filtering by zoning family, lot area, FAR, height, flood zone, and transit proximity. Operators include eq, gt, lt, gte, lte, in, and near.
The screening workflow lets you create a project, add parcels, run automated GO/REVIEW/NO_GO classification, and review ranked results. This is a 5-step pipeline.
Authentication: Project endpoints require a JWT Bearer token.
Include Authorization: Bearer <your_jwt_token> in all requests below.
Get your token by logging in via /api/v1/auth/magic-link.
Step A — Create a Project
POST /api/v1/projects
JWT = "your_jwt_token_here"
AUTH = {"Authorization": f"Bearer {JWT}"}
# Create a screening project with custom thresholds
resp = requests.post(f"{BASE}/projects", headers=AUTH, json={
"name": "Brooklyn Residential Sites",
"intended_use": "residential", # immutable after creation
"assumptions": {"min_units": 10},
"screening_profile": { # optional — custom GO/NO-GO thresholds
"no_go_min_friction": 70, # stricter: flag as NO_GO at friction 70 (default: 80)
"go_min_confidence": 0.8, # stricter: require 80% confidence for GO (default: 0.7)
}
})
project = resp.json()
PROJECT_ID = project["id"]
print(f"Project created: #{PROJECT_ID} - {project['name']}")
Screening Profile: The optional screening_profile field customizes GO/NO-GO classification thresholds for this project.
All parameters are bounded (e.g., no_go_min_friction range: 60–95, go_min_confidence range: 0.5–0.9).
Both intended_use and screening_profile are frozen at creation and cannot be changed.
Omit to use defaults that match standard risk tolerance.
Download screening results in JSON, CSV, Markdown, or PDF format. Each export references its source ScreenRun for full reproducibility.
GET /api/v1/projects/{id}/export?format=csv
# Export as CSV
resp = requests.get(
f"{BASE}/projects/{PROJECT_ID}/export",
params={"format": "csv"},
headers=AUTH,
)
# Save to file
with open("screening_results.csv", "wb") as f:
f.write(resp.content)
print("Exported to screening_results.csv")
# Other formats: json, md, pdf
resp_json = requests.get(
f"{BASE}/projects/{PROJECT_ID}/export",
params={"format": "json"},
headers=AUTH,
)
print(resp_json.json())
Compare 2-10 parcels across different cities. Returns normalized zoning data, entitlement calculations (GFA, units, height), and per-field deltas so you can evaluate sites side-by-side.
Rate limits are enforced per API key based on your subscription tier. Limits apply to billable endpoints (zoning, interpret, search). Project management endpoints (create, screen, export) are limited by your session, not your API key.
Tier
Per Hour
Per Day
Parcels/Month
Explorer
50
200
5
Professional
1,000
10,000
500
Team
5,000
50,000
2,000
Developer
20,000
200,000
10,000
Enterprise
Custom
Custom
Unlimited
When you exceed a limit, the API returns 429 Too Many Requests with a Retry-After header. Rate limit headers are included in every response: