Skip to content

Create road and water features from OpenStreetMap

You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.

A Feature is a named, reusable piece of vector geometry attached to a domain. The most common ones come straight from OpenStreetMap: the road network and water bodies within your domain. Once created, a feature is a single source of truth you can reference by id — most often to mask a fuel grid or remove trees where roads and water cross your data.

Creating one is a POST to the OSM extractor plus a short poll while the service fetches and processes the geometry.

  1. An API key. Set it once — it propagates to every code block: my-api-key.

  2. A domain in a projected CRS. Plug its id in once: your-domain-id. If you don’t have one, see Create a domain. The extractor clips OSM data to this domain’s extent and stores the result in the domain’s CRS.

POST to /domains/{{DOMAIN_ID}}/features/road/osm. The body is minimal — type and an optional name/description/tags.

POST road/osm
curl -X 'POST' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/features/road/osm' \
-H 'accept: application/json' \
-H 'api-key: my-api-key' \
-H 'Content-Type: application/json' \
-d '{
"type": "road",
"name": "OSM road"
}'

The 201 mints a feature id — record it: your-road-feature-id. Status starts pending; the extractor fetches OSM data asynchronously.

Identical shape against the water extractor:

POST water/osm
curl -X 'POST' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/features/water/osm' \
-H 'accept: application/json' \
-H 'api-key: my-api-key' \
-H 'Content-Type: application/json' \
-d '{
"type": "water",
"name": "OSM water"
}'

Record this id too: your-water-feature-id.

GET feature status
curl -X 'GET' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/features/your-road-feature-id' \
-H 'accept: application/json' \
-H 'api-key: my-api-key'

Status walks pending → running → completed. When it lands, the georeference.bounds are populated:

{
"id": "your-road-feature-id",
"domain_id": "your-domain-id",
"type": "road",
"name": "OSM road",
"description": "",
"status": "completed",
"progress": {
"percent": 100,
"message": "Complete"
},
"created_on": "2026-06-02T19:01:51.770011Z",
"modified_on": "2026-06-02T19:02:10.308061Z",
"source": {
"product": "osm",
"extent_buffer_m": 0.0,
"description": "OpenStreetMap road network"
},
"georeference": {
"crs": "EPSG:32611",
"bounds": [
717141.6556112946, 5326524.549818624, 718694.8955395881, 5328248.228078655
]
},
"error": null,
"tags": []
}

Here are the two features over the domain — the Bigfork, Montana area at the head of Flathead Lake:

Domain Roads Water
The domain (grey outline) with its extracted OSM roads (red) and water (blue).

A completed feature stores its geometry as polygons in the domain CRS — the road extractor widens OSM centerlines into footprint polygons by road class, and water bodies are already areal. Check how many geometries it holds with the data metadata endpoint:

{
"total_features": 112,
"partition_count": 1,
"partitions": [
{
"index": 0,
"num_features": 112
}
]
}

The geometry itself streams from /domains/{{DOMAIN_ID}}/features/{{ROAD_FEATURE_ID}}/data/{partition_index} as GeoJSON (application/geo+json) in the domain CRS — iterate partition_index from 0 to partition_count.

These features are inputs to the feature-based modification guides:

  • Zero features back. A completed feature with total_features: 0 means OSM has no roads/water in your domain extent (common for remote areas, especially water). Referencing an empty feature in a modification masks nothing — and an inventory modification against an empty feature fails during processing. Confirm the count via data/metadata before you rely on it, and consider extent_buffer_m if the feature you want sits just outside the domain.
  • Geographic-CRS domain. Features inherit the domain CRS, and the extractor needs metric units. Domains are rejected at creation time if they’re in a geographic CRS (e.g. EPSG:4326), so use a projected CRS (the appropriate UTM zone) for the domain.
  • Polling the wrong id. Each extractor call returns its own feature id. Poll road and water separately — they complete independently.