Developer docs
Lotmark exposes source-cited parcel enrichment records for the countywide Sonoma, CA dataset. Use this page to verify authentication, lookup behavior, response shape, provenance, and batch workflows before scheduling implementation time.
Base URLs
Parcel API: https://lotmark-parcel-api-production.up.railway.app
Public site and access requests: https://lotmark.io
The parcel API is a separate protected service. Use the parcel API base URL for every /v1 request, not the public landing page URL.
Interactive OpenAPI docs are available on the parcel service at https://lotmark-parcel-api-production.up.railway.app/docs. The machine-readable schema is available at https://lotmark-parcel-api-production.up.railway.app/openapi.json.
Current Coverage
Production currently serves the official Sonoma County bundle loaded on 2026-07-24.
- Parcel records: 189,239
- Canopy: 189,239 parcels from USDA Forest Service NLCD Tree Canopy Cover 2023 raster sampling.
- Terrain: 189,233 elevation rows and 189,186 slope rows from USGS 3DEP 30 m raster sampling.
- Wildfire hazard potential: 189,239 parcels from USDA Forest Service WHP 2023 raster sampling.
- Soil: 189,213 parcels with SSURGO
mukey; 183,924 with hydrologic group from USDA NRCS SDA attributes. - Hazards: 40,969 CAL FIRE FHSZ rows, 184,594 FEMA flood-zone rows, and 171,407 burn-distance rows.
Authentication
All /v1 endpoints require a bearer API key. Keep the key in server-side secrets and send it with each request:
Authorization: Bearer LOTMARK_API_KEY
GET /health is open and can be used before credentials are provisioned. API keys are issued for sandbox evaluation or through checkout, and are shown once at delivery.
Endpoint Table
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET |
/health |
No | Checks that the parcel API service and database are configured. |
GET |
/v1/parcels/:parcel_id |
Yes | Returns one curated parcel enrichment record by Lotmark parcel ID. |
GET |
/v1/parcels/by-apn/:apn |
Yes | Looks up a parcel by county APN and returns the same enrichment shape. |
GET |
/v1/parcels/search?address=...&limit=10 |
Yes | Searches loaded parcel addresses. limit is clamped from 1 to 25. |
POST |
/v1/parcels:batch-enrich |
Yes | Resolves parcel IDs, APNs, and address queries in one request. Maximum 100 total lookups. |
GET |
/v1/parcels/:parcel_id/qa |
Yes | Returns the persisted QA report for a generated parcel response. |
GET |
/v1/usage |
Yes | Returns request counts for the current API key. |
Curl Examples
Set the base URL and key once, then run the smoke tests below.
export LOTMARK_API_BASE="https://lotmark-parcel-api-production.up.railway.app"
export LOTMARK_API_KEY="ltm_live_..."
curl -s "$LOTMARK_API_BASE/health"
curl -s -H "Authorization: Bearer $LOTMARK_API_KEY" "$LOTMARK_API_BASE/v1/parcels/lm_ca_028-030-009"
curl -s -H "Authorization: Bearer $LOTMARK_API_KEY" "$LOTMARK_API_BASE/v1/parcels/by-apn/028-030-009"
curl -s -H "Authorization: Bearer $LOTMARK_API_KEY" "$LOTMARK_API_BASE/v1/parcels/search?address=FRANZ%20VALLEY&limit=5"
curl -s -X POST "$LOTMARK_API_BASE/v1/parcels:batch-enrich" -H "Authorization: Bearer $LOTMARK_API_KEY" -H "Content-Type: application/json" -d '{"parcel_ids":["lm_ca_028-030-009"],"apns":["028-040-023"],"addresses":["PORTER CREEK RD"]}'
curl -s -H "Authorization: Bearer $LOTMARK_API_KEY" "$LOTMARK_API_BASE/v1/parcels/lm_ca_028-030-009/qa"
curl -s -H "Authorization: Bearer $LOTMARK_API_KEY" "$LOTMARK_API_BASE/v1/usage"
Response Shape
Parcel responses are JSON objects with source blocks on major sections, compact per-field source references, and an LLM-ready narrative grounded in structured fields. Embedding vectors are not returned by default; the response exposes embedding metadata.
{
"parcel_id": "lm_ca_001-011-004",
"freshness_days": 0,
"parcel": {
"apn": "001-011-004",
"address": "721 CLOVERDALE BLVD N",
"county": "Sonoma",
"state": "CA",
"land_acres": 0.77,
"source": {
"agency": "County of Sonoma",
"product": "Parcels Public",
"accessed": "2026-07-24",
"record_count": 189239
}
},
"risk_features": {
"fire": {
"wildfire_hazard_potential_value": 4,
"wildfire_hazard_potential_class": "high",
"distance_to_burn_perimeter_m": 792.7,
"last_burn_year_within_5km": 2021,
"source": {
"agency": "CAL FIRE",
"product": "California Fire Perimeters public view nearest feature within 5 km"
},
"confidence": 0.8
},
"flood": {
"fema_zone": "X",
"in_sfha": false,
"source": {
"agency": "FEMA",
"product": "National Flood Hazard Layer Flood Hazard Zones point intersect"
},
"confidence": 0.9
}
},
"building": {
"primary_year_built": 1952,
"primary_size_sqft": 4705,
"source": {
"agency": "County of Sonoma",
"product": "Parcels Public building attributes"
},
"confidence": 0.85
},
"terrain": {
"elevation_ft": 1275.4,
"local_relief_150m_ft": 429.8,
"slope_degrees": 23.59,
"aspect_degrees": 179.2,
"source": {
"agency": "USGS",
"product": "3DEP Bare Earth DEM Dynamic service 30 m raster export sample"
},
"confidence": 0.9
},
"soil": {
"mukey": "459841",
"musym": "PcB",
"mapunit_name": "Pajaro clay loam, overwash, 2 to 5 percent slopes",
"hydrologic_group": "C/D",
"drainage_class": "Somewhat poorly drained",
"source": {
"agency": "USDA NRCS",
"product": "SSURGO mapunit polygon centroid intersect with SDA mapunit attributes"
}
},
"vegetation": {
"canopy": {
"canopy_percent": 0,
"year": 2023,
"source": {
"agency": "USDA Forest Service",
"product": "NLCD Tree Canopy Cover 2023 raster export sample"
}
}
},
"narrative": {
"text": "0.77 acre parcel, with a 1952 primary structure, at 1275.4 ft elevation.",
"grounded_in": ["parcel", "building", "terrain", "risk.fire", "risk.flood"]
},
"embedding": {
"dim": 1536,
"model": "text-embedding-3-small",
"status": "metadata_only"
},
"sources": {
"parcel_boundaries": {
"agency": "County of Sonoma",
"source_file": "parcels.geojson"
},
"parcel_terrain_attributes": {
"agency": "USGS",
"source_file": "terrain.csv"
},
"soil_attributes": {
"agency": "USDA NRCS",
"source_file": "soil.csv"
},
"flood_hazard_zones": {
"agency": "FEMA",
"source_file": "flood_zones.geojson"
}
},
"field_sources": {
"parcel.apn": "parcel_boundaries",
"terrain.elevation_ft": "parcel_terrain_attributes",
"soil.mukey": "soil_attributes",
"risk_features.flood.fema_zone": "flood_hazard_zones",
"narrative.grounded_in": ["parcel_boundaries", "parcel_building_attributes", "parcel_terrain_attributes", "burn_perimeters", "flood_hazard_zones"]
}
}
Error Responses
Errors use JSON bodies with ok: false and a short error string.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
{"ok":false,"error":"Missing bearer token."}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
{"ok":false,"error":"Invalid API key."}
HTTP/1.1 400 Bad Request
{"ok":false,"error":"Provide an address query."}
HTTP/1.1 404 Not Found
{"ok":false,"error":"Parcel not found."}
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{"ok":false,"error":"Too many requests. Try again later."}
Batch requests also return 400 when the body is empty or contains more than 100 total parcel IDs, APNs, and address queries.
Rate Limits
Sandbox access is intended for functional evaluation, integration tests, and response-shape validation. Coordinate before scripted load tests or bulk runs.
/v1/parcels:batch-enrich: up to 100 total lookups per request./v1/parcels/search: defaultlimitis 10; maximum returned matches is 25./api/waitlist: 8 submissions per IP per 10 minutes./api/checkout: 20 checkout starts per IP per 10 minutes./api/checkout/status: 60 checks per IP per 10 minutes./v1/usagereports request counts for the current API key.
Test Parcels
Provisioned sandboxes and production API keys currently load the countywide Sonoma source bundle. These records are good smoke tests for APN lookup, direct parcel lookup, address search, and enrichment coverage.
| Parcel ID | APN | Address Query |
|---|---|---|
lm_ca_001-011-004 |
001-011-004 |
721 CLOVERDALE BLVD N |
lm_ca_028-030-009 |
028-030-009 |
3225 FRANZ VALLEY RD |
lm_ca_079-020-011 |
079-020-011 |
10275 LOCH HAVEN DR |
lm_ca_091-340-003-112542 |
091-340-003 |
1830 BOXHEART DR |
Some APNs have multiple county geometries. If a direct parcel ID misses or an APN has duplicates, retry with /v1/parcels/by-apn/:apn and inspect the returned parcel IDs.
Sandbox Access
To evaluate Lotmark, send the team a work email, company name, intended use case, expected test volume, and whether you need APN lookup, address search, batch enrichment, or QA reports. We will provision a sandbox bearer key and confirm the bundle loaded for your tests.
curl -s -X POST "https://lotmark.io/api/waitlist" -H "Content-Type: application/json" -d '{"email":"you@company.com","name":"Your Name","company":"Company","role":"proptech-ai","plan":"developer","message":"Please provision sandbox API access for APN lookup, address search, batch enrichment, and QA reports.","request_demo":false}'
After credentials are provisioned, start with /health, then run APN lookup and /v1/usage. Keep API keys out of client-side code and browser logs.