Modify an inventory
You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.
You don’t have to regenerate a tree inventory to edit it. POST .../modifications applies rules to an inventory’s current stored trees and
writes the result back under the same id — no re-running the point process, no
new resource. Use it to remove trees by attribute, by a multi-attribute
expression, or by location, or to scale a numeric attribute, once the
inventory already exists.
The rules you submit are appended to the inventory’s list and applied on
top of whatever it already holds. To instead apply the same rules as you
first build an inventory, see
Remove trees with features
— same rule shape, applied at create time. For
the concepts — conditions, actions, the inventory-only remove action and
expression conditions, and the create-time-vs-in-place distinction — see
About modifications.
Prerequisites
Section titled “Prerequisites”-
An API key: my-api-key.
-
A domain in a projected CRS: your-domain-id. See Create a domain.
-
A completed tree inventory: your-inventory-id. See Generate a tree inventory from TreeMap.
-
Optional — a completed road and water feature in the same domain, for the spatial recipes. See Create road and water features from OpenStreetMap and record your-road-feature-id and your-water-feature-id.
Removing small trees in one script:
import time
import requests
API_KEY = "my-api-key"DOMAIN_ID = "your-domain-id"# A completed tree inventory (e.g. from inventories/tree/pim).INVENTORY_ID = "your-inventory-id"BASE = "https://api-v2-prod-nyvjyh5ywa-uw.a.run.app"HEADERS = {"api-key": API_KEY}
def poll(inventory_id: str) -> dict: while True: r = requests.get( f"{BASE}/domains/{DOMAIN_ID}/inventories/{inventory_id}", headers=HEADERS, ).json() if r["status"] in ("completed", "failed"): return r time.sleep(5)
def rows(inventory_id: str) -> int: return requests.get( f"{BASE}/domains/{DOMAIN_ID}/inventories/{inventory_id}/data/metadata", headers=HEADERS, ).json()["total_rows"]
before = rows(INVENTORY_ID)
# Remove every tree under 5 cm DBH. `remove` must be the only action in its rule.inventory = requests.post( f"{BASE}/domains/{DOMAIN_ID}/inventories/{INVENTORY_ID}/modifications", headers=HEADERS, json={ "modifications": [ { "conditions": [ {"attribute": "dbh", "operator": "lt", "value": 5} ], "actions": [{"modifier": "remove"}], } ] },).json()print(inventory["status"]) # -> pending
inventory = poll(INVENTORY_ID)print(inventory["status"], len(inventory["modifications"])) # -> completed 1print(before, "->", rows(INVENTORY_ID)) # fewer treesThe rest of this page walks the individual recipes. The inventory below starts with 81,908 trees.
Remove small trees
Section titled “Remove small trees”Match trees by a single attribute, delete them. Here every tree under 5 cm
DBH: an attribute condition plus a remove action. remove must be the
only action in its rule — you can’t both drop a tree and edit it.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id/modifications' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "modifications": [ { "conditions": [ { "attribute": "dbh", "operator": "lt", "value": 5 } ], "actions": [ { "modifier": "remove" } ] } ]}'{ "id": "your-inventory-id", "domain_id": "your-domain-id", "type": "tree", "name": "TreeMap tree inventory", "description": "", "status": "pending", "progress": null, "created_on": "2026-07-09T19:28:23.911399Z", "modified_on": "2026-07-09T19:28:30.969142", "checksum": "d58341841ef34b2589132168caf44ae4", "source": { "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72", "source_pim_grid_id": "your-pim-grid-id", "name": "pim" }, "modifications": [], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718368.2978944418, "std": 249.21595322248714 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 5326540.000291519, "max": 5328249.995875615, "mean": 5327465.665030207, "std": 565.3952806317172 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 15 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 2.54, "max": 72.898, "mean": 10.23889356351028, "std": 8.927722282527832 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 1.8287999999999998, "max": 41.452799999999996, "mean": 7.8216135078380615, "std": 5.610684318007391 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5959423987888851, "std": 0.22980870294800645 } } ], "forestry_metrics": null, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": []}The 200 comes back pending with a freshly rotated checksum. The
modifications array is still empty here; the submitted rule lands there once
the job completes (see Poll to completion). This
inventory has a lot of saplings — the rule removes 31,825 trees
(81,908 → 50,083).
Remove by expression
Section titled “Remove by expression”An expression condition tests several attributes at once — something a single
attribute condition can’t do, and something only inventories support. Here,
trees that are both thin and short: dbh < 5 and height < 2.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id/modifications' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "modifications": [ { "conditions": [ { "expression": "dbh < 5 and height < 2" } ], "actions": [ { "modifier": "remove" } ] } ]}'{ "id": "your-inventory-id", "domain_id": "your-domain-id", "type": "tree", "name": "TreeMap tree inventory", "description": "", "status": "pending", "progress": null, "created_on": "2026-07-09T19:28:31.323539Z", "modified_on": "2026-07-09T19:28:38.299411", "checksum": "c45d5dea27d649948e0e1cd4263fce71", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718368.2978944418, "std": 249.21595322248714 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 5326540.000291519, "max": 5328249.995875615, "mean": 5327465.665030207, "std": 565.3952806317172 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 15 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 2.54, "max": 72.898, "mean": 10.23889356351028, "std": 8.927722282527832 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 1.8287999999999998, "max": 41.452799999999996, "mean": 7.8216135078380615, "std": 5.610684318007391 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5959423987888851, "std": 0.22980870294800645 } } ], "forestry_metrics": null, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": []}The and inside the expression is the same ANDing as stacking conditions — it
narrows. Where the dbh < 5 rule above removed 31,825 trees, adding
height < 2 cuts that to just 8 (81,908 → 81,900): almost every thin stem
is still taller than 2 m. Expressions accept dbh, height, and
crown_ratio, always in native units (cm, m, fraction).
Remove trees under roads or water
Section titled “Remove trees under roads or water”To drop trees wherever they fall near a road or near water, use two
rules — one per feature. Each is a within test against the feature,
widened by a buffer_m, with a remove action.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id/modifications' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "modifications": [ { "conditions": [ { "source": "feature", "operator": "within", "feature_id": "your-road-feature-id", "buffer_m": 5 } ], "actions": [ { "modifier": "remove" } ] }, { "conditions": [ { "source": "feature", "operator": "within", "feature_id": "your-water-feature-id", "buffer_m": 5 } ], "actions": [ { "modifier": "remove" } ] } ]}'{ "id": "your-inventory-id", "domain_id": "your-domain-id", "type": "tree", "name": "TreeMap tree inventory", "description": "", "status": "pending", "progress": null, "created_on": "2026-07-09T19:28:38.627889Z", "modified_on": "2026-07-09T19:28:39.330146", "checksum": "596730fe06d84c70b5535f2714573f69", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718368.2978944418, "std": 249.21595322248714 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 5326540.000291519, "max": 5328249.995875615, "mean": 5327465.665030207, "std": 565.3952806317172 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 15 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 2.54, "max": 72.898, "mean": 10.23889356351028, "std": 8.927722282527832 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 1.8287999999999998, "max": 41.452799999999996, "mean": 7.8216135078380615, "std": 5.610684318007391 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5959423987888851, "std": 0.22980870294800645 } } ], "forestry_metrics": null, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": []}Together the two rules remove 3,613 trees (81,908 → 78,295) — those in the road and water corridors plus the 5 m tolerance.
Scale an attribute
Section titled “Scale an attribute”Not every edit removes trees. A non-remove action edits an attribute on the
matching trees and leaves the tree count unchanged. Here, tall trees
(height > 25 m) have their dbh scaled to 90% — a multiply action gated by
a condition.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id/modifications' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "modifications": [ { "conditions": [ { "attribute": "height", "operator": "gt", "value": 25 } ], "actions": [ { "attribute": "dbh", "modifier": "multiply", "value": 0.9 } ] } ]}'{ "id": "your-inventory-id", "domain_id": "your-domain-id", "type": "tree", "name": "TreeMap tree inventory", "description": "", "status": "pending", "progress": null, "created_on": "2026-07-09T19:28:39.575804Z", "modified_on": "2026-07-09T19:28:46.403615", "checksum": "5cb4777c29644c2ead9fca2070f1682e", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718368.2978944418, "std": 249.21595322248714 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 5326540.000291519, "max": 5328249.995875615, "mean": 5327465.665030207, "std": 565.3952806317172 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 15 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 81908, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 2.54, "max": 72.898, "mean": 10.23889356351028, "std": 8.927722282527832 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 1.8287999999999998, "max": 41.452799999999996, "mean": 7.8216135078380615, "std": 5.610684318007391 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 81908, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5959423987888851, "std": 0.22980870294800645 } } ], "forestry_metrics": null, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": []}The tree count is unchanged (81,908 → 81,908) — this rewrites dbh on the
matching trees rather than deleting anything. multiply, divide, add, and
subtract all edit in place; only remove deletes.
Poll to completion
Section titled “Poll to completion”The checksum rotates the instant you POST, but the trees are rewritten and
the modifications list is updated only when the job completes. Poll the
inventory:
curl -X 'GET' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'Status walks pending → running → completed. When it lands, the submitted
rule appears in modifications:
{ "id": "your-inventory-id", "domain_id": "your-domain-id", "type": "tree", "name": "TreeMap tree inventory", "description": "", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-07-09T19:28:23.911399Z", "modified_on": "2026-07-09T19:29:35.631889Z", "checksum": "d58341841ef34b2589132168caf44ae4", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [ { "conditions": [ { "attribute": "dbh", "operator": "lt", "value": 5, "unit": null } ], "actions": [ { "modifier": "remove" } ] } ], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718365.8836694711, "std": 252.44197956672994 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5326540.000592403, "max": 5328249.990101517, "mean": 5327485.855720593, "std": 559.5766552337327 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 14 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5.08, "max": 72.898, "mean": 14.479704051274885, "std": 9.153580443050032 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 2.7432, "max": 41.452799999999996, "mean": 10.530476976219477, "std": 5.662240505216165 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5807293892139049, "std": 0.22081371525657967 } } ], "forestry_metrics": { "type": "tree", "tree_count": 50083, "basal_area_per_area": 9.375725095011157, "tree_density": 37.79318312050426, "quadratic_mean_diameter": 6.744224242220545, "dominant_species_groups": [ { "spgrpcd": 2, "name": "Douglas-fir", "basal_area_share": 0.45768974649180144 }, { "spgrpcd": 4, "name": "Pine", "basal_area_share": 0.20342386693258668 }, { "spgrpcd": 1, "name": "Cedar/larch", "basal_area_share": 0.15923405289259357 }, { "spgrpcd": 3, "name": "True fir/hemlock", "basal_area_share": 0.10696149796976803 }, { "spgrpcd": 5, "name": "Spruce", "basal_area_share": 0.036172433028793964 } ] }, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": []}The rotated checksum is the staleness signal for anything derived from this
inventory — a voxelization, an export. To keep the pre-edit inventory around,
branch it first.
Branch a scenario instead of overwriting
Section titled “Branch a scenario instead of overwriting”In-place modification edits the inventory under its own id — the pre-edit trees are gone. When you’d rather keep the original and explore a variant stand, duplicate first, then modify the copy.
POST .../duplicate makes a byte-for-byte clone: it copies the stored parquet
(it does not re-run the point process), carrying the inventory’s source,
modifications, treatments, and checksum over verbatim.
curl -X 'POST' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id/duplicate' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "name": "Inventory with small trees removed (scenario B)", "tags": ["scenario-b"]}'{ "id": "id-of-the-duplicated-inventory", "domain_id": "your-domain-id", "type": "tree", "name": "Inventory with small trees removed (scenario B)", "description": "", "status": "pending", "progress": null, "created_on": "2026-07-09T19:35:38.055373", "modified_on": "2026-07-09T19:35:38.055373", "checksum": "d58341841ef34b2589132168caf44ae4", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [ { "conditions": [ { "attribute": "dbh", "operator": "lt", "value": 5, "unit": null } ], "actions": [ { "modifier": "remove" } ] } ], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718365.8836694711, "std": 252.44197956672994 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5326540.000592403, "max": 5328249.990101517, "mean": 5327485.855720593, "std": 559.5766552337327 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 14 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5.08, "max": 72.898, "mean": 14.479704051274885, "std": 9.153580443050032 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 2.7432, "max": 41.452799999999996, "mean": 10.530476976219477, "std": 5.662240505216165 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5807293892139049, "std": 0.22081371525657967 } } ], "forestry_metrics": { "type": "tree", "tree_count": 50083, "basal_area_per_area": 9.375725095011157, "tree_density": 37.79318312050426, "quadratic_mean_diameter": 6.744224242220545, "dominant_species_groups": [ { "spgrpcd": 2, "name": "Douglas-fir", "basal_area_share": 0.45768974649180144 }, { "spgrpcd": 4, "name": "Pine", "basal_area_share": 0.20342386693258668 }, { "spgrpcd": 1, "name": "Cedar/larch", "basal_area_share": 0.15923405289259357 }, { "spgrpcd": 3, "name": "True fir/hemlock", "basal_area_share": 0.10696149796976803 }, { "spgrpcd": 5, "name": "Spruce", "basal_area_share": 0.036172433028793964 } ] }, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": ["scenario-b"]}The 201 mints a new inventory id — record it: id-of-the-duplicated-inventory.
The copy starts pending while the background copy runs, but its checksum
already equals the source’s and its modifications are carried over intact.
Poll it to completed:
{ "id": "id-of-the-duplicated-inventory", "domain_id": "your-domain-id", "type": "tree", "name": "Inventory with small trees removed (scenario B)", "description": "", "status": "completed", "progress": null, "created_on": "2026-07-09T19:35:38.055373Z", "modified_on": "2026-07-09T19:35:38.358291Z", "checksum": "d58341841ef34b2589132168caf44ae4", "source": { "name": "pim", "point_process": "inhomogeneous_poisson", "seed": 42, "source_pim_grid_id": "your-pim-grid-id", "source_pim_grid_checksum": "f3d2608693f8440b9ee4234d11c37e72" }, "modifications": [ { "conditions": [ { "attribute": "dbh", "operator": "lt", "value": 5, "unit": null } ], "actions": [ { "modifier": "remove" } ] } ], "treatments": [], "columns": [ { "key": "x", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 717157.6880869393, "max": 718695.9982627264, "mean": 718365.8836694711, "std": 252.44197956672994 } }, { "key": "y", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5326540.000592403, "max": 5328249.990101517, "mean": 5327485.855720593, "std": 559.5766552337327 } }, { "key": "fia_species_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 14 } }, { "key": "fia_status_code", "type": "categorical", "unit": null, "summary": { "type": "categorical", "count": 50083, "null_count": 0, "unique_count": 2 } }, { "key": "dbh", "type": "continuous", "unit": "cm", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 5.08, "max": 72.898, "mean": 14.479704051274885, "std": 9.153580443050032 } }, { "key": "height", "type": "continuous", "unit": "m", "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 2.7432, "max": 41.452799999999996, "mean": 10.530476976219477, "std": 5.662240505216165 } }, { "key": "crown_ratio", "type": "continuous", "unit": null, "summary": { "type": "continuous", "count": 50083, "null_count": 0, "min": 0.0, "max": 0.97, "mean": 0.5807293892139049, "std": 0.22081371525657967 } } ], "forestry_metrics": { "type": "tree", "tree_count": 50083, "basal_area_per_area": 9.375725095011157, "tree_density": 37.79318312050426, "quadratic_mean_diameter": 6.744224242220545, "dominant_species_groups": [ { "spgrpcd": 2, "name": "Douglas-fir", "basal_area_share": 0.45768974649180144 }, { "spgrpcd": 4, "name": "Pine", "basal_area_share": 0.20342386693258668 }, { "spgrpcd": 1, "name": "Cedar/larch", "basal_area_share": 0.15923405289259357 }, { "spgrpcd": 3, "name": "True fir/hemlock", "basal_area_share": 0.10696149796976803 }, { "spgrpcd": 5, "name": "Spruce", "basal_area_share": 0.036172433028793964 } ] }, "georeference": { "crs": "EPSG:32611", "bounds": [717140.0, 5326524.0, 718696.0, 5328250.0] }, "error": null, "tags": ["scenario-b"]}Same checksum, same source, same modifications — only the id, name,
and tags differ. Now apply any recipe above to id-of-the-duplicated-inventory
and only the copy changes; the original keeps the checksum shown here. Two
things to watch:
-
Using the copy before it’s
completed. The clone ispendinguntil the background copy finishes; its/dataendpoints422until then. Poll first.{"detail": "inventories/id-of-the-duplicated-inventory status is 'pending', expected 'completed'."} -
Duplicating a non-
completedinventory. The source must becompleted— there’s nothing stable to copy until it finishes building.{"detail": "inventories/your-inventory-id status is 'pending', expected 'completed'."}
If it fails
Section titled “If it fails”If processing fails, the inventory lands in status: failed with an error
message, and its stored trees are left unchanged — a failed in-place edit
never partially rewrites the inventory. The rules you submitted stay queued,
so once you’ve addressed the cause you can POST the same (or a corrected)
modification again to retry.
Common pitfalls
Section titled “Common pitfalls”-
One rule for two features (AND vs OR). A road condition and a water condition in one rule match only trees inside both — almost none. Use one rule per feature, as in Remove trees under roads or water.
-
removecombined with another action.removemust be the sole action in its rule; pairing it with an attribute edit is a422. To edit some trees and remove others, use two separate rules.{"detail": [{"type": "value_error","loc": ["body", "modifications", 0],"msg": "Value error, RemoveAction must be the sole action if present","input": {"conditions": [{"attribute": "dbh","operator": "lt","value": 5}],"actions": [{"modifier": "remove"},{"attribute": "height","modifier": "multiply","value": 0.9}]},"ctx": {"error": {}}}]} -
A road feature with no
buffer_m. Road features are thin. Trees are points, and a point rarely lands inside a bare road polygon, so awithintest with no buffer removes almost nothing.buffer_mgives the feature the width to actually catch trees — set it to the corridor you mean.
Next steps
Section titled “Next steps”- Inspect the result — fetch and stream the inventory data.
- Do the same to grids — modify a grid.