Skip to content
Developer platform · v0.1

Build acquisition workflows on a source-aware city model.

Screen the five-borough parcel market, explain exact tax lots, and request reproducible aerial-change evidence through one REST API. Receipts expose access scope, source lineage, and output state so clients do not have to infer them.

published leads
5,000
public preview
125
NYC boroughs
5
run artifacts
4
Public first request

Resolve a live demo, then inspect its receipt.

The demo registry can change when outputs are regenerated. Resolve the current run id at request time; do not copy one from a screenshot or an old response.
Toggle Resolve a live demo, then inspect its receipt.
four-command quickstart
API_BASE=https://api.citylens.dev

# Resolve a currently published demo instead of hard-coding a run id.
SAMPLE_RUN=$(curl -fsS "$API_BASE/v1/demo/featured" \
  | jq -r '.Featured[0].run_id')

# Inspect the run receipt and its available artifacts.
curl -fsS "$API_BASE/v1/demo/runs/$SAMPLE_RUN" \
  | jq '{run_id, status, artifacts: [.artifacts[].name]}'

# Read pipeline QA and timing from the summary artifact.
curl -fsSL "$API_BASE/v1/demo/artifacts/$SAMPLE_RUN/run_summary.json" \
  | jq '{ok, qa: {change_counts: .qa.change_counts, lidar_used: .qa.lidar_used}, performance}'

# Download one real, precomputed output through the stable API proxy.
curl -fsSL "$API_BASE/v1/demo/artifacts/$SAMPLE_RUN/change.geojson" \
  -o change.geojson
Stable browser delivery
Demo artifact URLs are relative API proxy paths—not signed GCS URLs. Join them to https://api.citylens.dev, or call the documented proxy path directly as above.
Access

Use public routes, a browser session, or a revocable API key.

The product UI manages its own short-lived JWT. External scripts should use a user API key and keep it out of browser bundles, source control, logs, and URLs.
Toggle Use public routes, a browser session, or a revocable API key.
Public

Aggregates and demos

Health, run options, featured demos, demo artifacts, and the parcel preview require no credential.

Browser

Managed session

CityLens signs UI requests with a short-lived bearer JWT. A visible identity is not treated as proof of API access.

Recommended for code

User API key

Mint a clk_live_ key in Account → API keys. It inherits the account plan and can be revoked without changing the login password.

bearer API key
curl -fsS https://api.citylens.dev/v1/me \
  -H "Authorization: Bearer clk_live_…" \
  | jq '{user, quota}'
Primary data product

Treat inventory scope as a response contract.

Public access returns a bounded 25-per-borough preview. Any valid user credential returns the complete published citywide inventory, currently 5,000 unique tax lots.
Toggle Treat inventory scope as a response contract.
authenticated citywide map
curl -fsS "https://api.citylens.dev/v1/parcel-intel/map?top_per_borough=1000" \
  -H "Authorization: Bearer clk_live_…" \
  | jq '{access_scope, returned_count, available_count, inventory_complete}'
full-inventory receipt
{
  "access_scope": "authenticated_full",
  "returned_count": 5000,
  "available_count": 5000,
  "inventory_complete": true
}
Never infer access from row count alone
Require access_scope, returned_count, available_count, and inventory_complete to agree. An anonymous 125-row response is valid public_preview, not a truncated full inventory.
Continue a qualified parcel into site evidence
In the signed-in dashboard, Build site evidence carries a numbered selected parcel into a new imagery run. The address is editable before submission and travels in a one-time, tab-scoped session record—not in the URL or analytics.
GET/v1/parcel-intel/indexpublic

Aggregate generation, selection-policy, source-freshness, and borough receipts.

GET/v1/parcel-intel/maptiered

Compact mappable rows: public preview or complete authenticated inventory.

GET/v1/parcel-intel/parcel/{bbl}tiered

One ranked parcel plus its decision audit. Public access is limited to preview leads.

GET/v1/parcel-intel/screening/{bbl}bearer

Explains published, below-cutoff, screened-out, or not-evaluated status for an exact BBL.

POST/v1/parcel-intel/resolve-addressbearer

Maps an official NYC street address to zero, one, or multiple candidate BBLs without guessing.

GET/v1/parcel-intel/official-parcel/{bbl}bearer

Current, source-specific PLUTO and ACRIS facts. This dossier does not alter rank.

Workflow, evidence-review, saved-view, and product-event routes remain pilot application contracts. Contact CityLens before building an external integration against them.

Aerial evidence

Create a run, poll its state, then fetch named artifacts.

Run options are intentionally locked. Discover the accepted values first, submit only public fields, and read QA or timing from run_summary.json.
Toggle Create a run, poll its state, then fetch named artifacts.
GET/v1/run-optionspublic
Discover the accepted request schema
The server currently fixes the imagery year, baseline year, SAM2 backend, outputs, and 250-meter AOI.
Request
bash
curl -fsS https://api.citylens.dev/v1/run-options | jq
Response
json
{
  "imagery_years": [2024],
  "baseline_years": [2017],
  "segmentation_backends": ["sam2"],
  "outputs": ["change", "mesh", "previews"],
  "defaults": {
    "imagery_year": 2024,
    "baseline_year": 2017,
    "segmentation_backend": "sam2",
    "outputs": ["previews", "change", "mesh"],
    "aoi_radius_m": 250
  }
}
POST/v1/runsrequires bearer
Queue one imagery run
Reserves quota and returns immediately. Poll the returned run id; do not hold the create request open.
Request
bash
curl -fsS https://api.citylens.dev/v1/runs \
  -H "Authorization: Bearer clk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "100 E 21st St Brooklyn, NY 11226",
    "outputs": ["previews", "change", "mesh"]
  }'
Response
json
{
  "run_id": "…",
  "status": "queued",
  "stage": "queued",
  "progress": 0,
  "artifacts": []
}
Do not send internal fields such as aoi_radius_m, sam2_cfg, or local input paths.
GET/v1/runs?limit&cursorbearer

Owned runs, newest first, with an opaque next cursor.

GET/v1/runs/{run_id}bearer

Owned run state and artifact metadata. Other users' ids return 404.

GET/v1/demo/featuredpublic

The current allowlisted precomputed demonstrations.

GET/v1/demo/artifacts/{run_id}/{name}public

Streams an allowlisted demo artifact through the API.

Where QA actually lives
A run detail returns artifact metadata. Pipeline diagnostics and stage timings live inside the downloadable run_summary.json artifact under qa and performance.
Failure handling

Branch on status and structured product codes.

Policy and quota failures expose detail.code. Generic authentication, ownership, and infrastructure errors may use a plain detail message. Failed asynchronous runs carry a structured error object on the run.
Toggle Branch on status and structured product codes.
CityLens API response codes and recommended client behavior
HTTP / stateStable codeClient action
400INVALID_RUN_OPTIONRefresh /v1/run-options and correct the request.
401Replace or refresh the bearer credential.
404Treat an unknown or unowned run id as unavailable.
429MONTHLY_QUOTA_EXCEEDEDRead quota from /v1/me and wait for the next UTC month or change plan.
429CONCURRENT_LIMIT_EXCEEDEDWait for the active run to reach a terminal state.
run.errorLIDAR_NO_COVERAGE / WORKER_FAILEDShow the run's message and stage; do not render empty viewers.
Interpretation

Keep provenance, model quality, and commercial outcomes separate.

CityLens exposes evidence needed to audit a response. Those receipts narrow uncertainty; they do not turn a screening product into a title report, zoning opinion, appraisal, or prediction of seller behavior.
Toggle Keep provenance, model quality, and commercial outcomes separate.

Source receipt

Generation ids, source dates, input hashes, and official links identify the evidence used.

Pipeline QA

Mask overlap, mesh coverage, change counts, and stage timings describe technical output—not acquisition accuracy.

Parcel rank

A rank orders the published screen. It is not seller intent, transaction probability, or a parcel-level confidence score.

Reproducibility boundary
Matching input hashes prove that two runs used the same bytes. Byte-identical outputs additionally require the same code, model, configuration, and deterministic runtime; compare output hashes rather than assuming equivalence.

Planning an integration?

Bring the intended workflow, request volume, and evidence requirements—not just an endpoint list.

Discuss an integration