List, tag, rename, and delete point clouds
You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.
Point clouds are the heaviest data in v2 and carry the tightest count quotas, so knowing what you have — and removing what you do not need — matters more here than for other resources.
Prerequisites
Section titled “Prerequisites”- An API key: my-api-key.
List across every domain
Section titled “List across every domain”Use the - wildcard in place of a domain id to see everything you own:
curl -X 'GET' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/-/pointclouds?size=5&sort_by=created_on&sort_order=descending' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
# Omit the domain argument to list across every domain you own. The SDK returns# the requested page as a plain list of PointCloud objects (the raw envelope's# current_page / total_items are not surfaced — page through with page/size).point_clouds = ff.list_point_clouds( size=5, sort_by="created_on", sort_order="descending")for pc in point_clouds: print(pc.name, pc.type_, pc.to_dict()["source"]["name"]){ "current_page": 0, "page_size": 5, "total_items": 3, "point_clouds": [ { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Scan with no CRS", "description": "", "status": "failed", "progress": { "percent": 100, "message": "Failed" }, "created_on": "2026-08-03T19:51:16.253376Z", "modified_on": "2026-08-03T19:51:18.051700Z", "checksum": "2b0bea9318fc4a4dba360bbdf764c0d7", "source": { "name": "upload", "object_name": "pointclouds/your-point-cloud-id/upload" }, "georeference": null, "summary": null, "error": { "code": "MISSING_CRS", "message": "The point cloud has no coordinate reference system. Assign a CRS before uploading.", "suggestion": "Set the CRS in your processing software, e.g. `pdal translate in.laz out.laz --writers.las.a_srs=EPSG:<code>`." }, "tags": [] }, { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "tls", "name": "Plot 14 terrestrial scan", "description": "Tripod scan of a single plot.", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-08-03T19:50:52.256220Z", "modified_on": "2026-08-03T19:51:13.653143Z", "checksum": "d2710a9b8ac043abad3adb536e9f73bd", "source": { "name": "upload", "object_name": "pointclouds/your-point-cloud-id/upload" }, "georeference": { "crs": "EPSG:32612", "bounds": [ 294200.005, 5199100.005, 1230.013, 294599.997, 5199499.981, 1259.118 ] }, "summary": { "point_count": 60000, "point_classes": [2, 5], "density": 0.3750300019503444 }, "error": null, "tags": ["plot-14"] }, { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", "description": "Pinned to a single 3DEP acquisition so the fetch is reproducible.", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-08-03T19:48:51.536751Z", "modified_on": "2026-08-03T19:53:46.572405Z", "checksum": "690b4bf260244d8db52e1eaa6888ad49", "source": { "name": "3dep", "requested_datasets": ["MT_Statewide_P3_4_B21"], "coverage_fraction": 1.0, "catalog_fetched_on": "2026-08-03T19:49:06.976913+00:00", "datasets": ["MT_Statewide_P3_4_B21"] }, "georeference": { "crs": "EPSG:32612", "bounds": [ 294094.992, 5198981.67, 1026.3600000000001, 294784.075, 5199749.485, 1274.19 ] }, "summary": { "point_count": 10496309, "point_classes": [1, 2, 7, 9, 18, 20], "density": 19.838483899989324 }, "error": null, "tags": ["blackfoot", "3dep", "pinned", "documented"] } ]}The envelope is current_page, page_size, total_items, and point_clouds.
Pagination is page (zero-indexed) and size (1–1000, default 100).
The SDK returns the page as a plain list of PointCloud objects — the
envelope fields (total_items, current_page) are not surfaced, so page
through with page / size when one page is not enough.
Filter within a domain
Section titled “Filter within a domain”Drop the wildcard for a single domain, and narrow with type, source, or
tag:
curl -X 'GET' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/pointclouds?type=als' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
# Filter within one domain by scan type. Note the SDK kwarg is point_cloud_type# (the API query parameter is `type`).als_clouds = ff.list_point_clouds("your-domain-id", point_cloud_type="als"){ "current_page": 0, "page_size": 100, "total_items": 2, "point_clouds": [ { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Scan with no CRS", "description": "", "status": "failed", "progress": { "percent": 100, "message": "Failed" }, "created_on": "2026-08-03T19:51:16.253376Z", "modified_on": "2026-08-03T19:51:18.051700Z", "checksum": "2b0bea9318fc4a4dba360bbdf764c0d7", "source": { "name": "upload", "object_name": "pointclouds/your-point-cloud-id/upload" }, "georeference": null, "summary": null, "error": { "code": "MISSING_CRS", "message": "The point cloud has no coordinate reference system. Assign a CRS before uploading.", "suggestion": "Set the CRS in your processing software, e.g. `pdal translate in.laz out.laz --writers.las.a_srs=EPSG:<code>`." }, "tags": [] }, { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", "description": "Pinned to a single 3DEP acquisition so the fetch is reproducible.", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-08-03T19:48:51.536751Z", "modified_on": "2026-08-03T19:53:46.572405Z", "checksum": "690b4bf260244d8db52e1eaa6888ad49", "source": { "name": "3dep", "requested_datasets": ["MT_Statewide_P3_4_B21"], "coverage_fraction": 1.0, "catalog_fetched_on": "2026-08-03T19:49:06.976913+00:00", "datasets": ["MT_Statewide_P3_4_B21"] }, "georeference": { "crs": "EPSG:32612", "bounds": [ 294094.992, 5198981.67, 1026.3600000000001, 294784.075, 5199749.485, 1274.19 ] }, "summary": { "point_count": 10496309, "point_classes": [1, 2, 7, 9, 18, 20], "density": 19.838483899989324 }, "error": null, "tags": ["blackfoot", "3dep", "pinned", "documented"] } ]}curl -X 'GET' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/pointclouds?tag=pinned' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
pinned = ff.list_point_clouds("your-domain-id", tag="pinned"){ "current_page": 0, "page_size": 100, "total_items": 1, "point_clouds": [ { "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", "description": "Pinned to a single 3DEP acquisition so the fetch is reproducible.", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-08-03T19:48:51.536751Z", "modified_on": "2026-08-03T19:53:46.572405Z", "checksum": "690b4bf260244d8db52e1eaa6888ad49", "source": { "name": "3dep", "requested_datasets": ["MT_Statewide_P3_4_B21"], "coverage_fraction": 1.0, "catalog_fetched_on": "2026-08-03T19:49:06.976913+00:00", "datasets": ["MT_Statewide_P3_4_B21"] }, "georeference": { "crs": "EPSG:32612", "bounds": [ 294094.992, 5198981.67, 1026.3600000000001, 294784.075, 5199749.485, 1274.19 ] }, "summary": { "point_count": 10496309, "point_classes": [1, 2, 7, 9, 18, 20], "density": 19.838483899989324 }, "error": null, "tags": ["blackfoot", "3dep", "pinned", "documented"] } ]}| Parameter | Values |
|---|---|
type | als, tls |
source | 3dep, upload |
tag | any tag on the cloud |
sort_by | created_on, modified_on, name |
sort_order | ascending, descending |
page, size | zero-indexed page, 1–1000 per page |
Rename and retag
Section titled “Rename and retag”PATCH edits metadata only — name, description, and tags. tags replaces
the whole list rather than appending to it:
curl -X 'PATCH' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/pointclouds/your-point-cloud-id' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "name": "Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", "tags": ["blackfoot", "3dep", "pinned", "documented"]}'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
point_cloud = ff.get_point_cloud("your-domain-id", "your-point-cloud-id")
# update() edits metadata only. `tags` replaces the whole list rather than# appending. The content checksum is unchanged by a metadata edit.point_cloud.update( name="Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", tags=["blackfoot", "3dep", "pinned", "documented"],){ "id": "your-point-cloud-id", "domain_id": "your-domain-id", "type": "als", "name": "Blackfoot ALS 2021 (MT_Statewide_P3_4_B21)", "description": "Pinned to a single 3DEP acquisition so the fetch is reproducible.", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "2026-08-03T19:48:51.536751Z", "modified_on": "2026-08-03T19:53:46.572405", "checksum": "690b4bf260244d8db52e1eaa6888ad49", "source": { "name": "3dep", "requested_datasets": ["MT_Statewide_P3_4_B21"], "coverage_fraction": 1.0, "catalog_fetched_on": "2026-08-03T19:49:06.976913+00:00", "datasets": ["MT_Statewide_P3_4_B21"] }, "georeference": { "crs": "EPSG:32612", "bounds": [ 294094.992, 5198981.67, 1026.3600000000001, 294784.075, 5199749.485, 1274.19 ] }, "summary": { "point_count": 10496309, "point_classes": [1, 2, 7, 9, 18, 20], "density": 19.838483899989324 }, "error": null, "tags": ["blackfoot", "3dep", "pinned", "documented"]}A metadata edit never moves the checksum. That is deliberate, and it is
what makes the staleness check below meaningful: the checksum tracks content,
so renaming a cloud does not make every grid derived from it look stale.
Check whether a derived grid has gone stale
Section titled “Check whether a derived grid has gone stale”A grid built from a point cloud records the checksum it was built from, under
source.source_point_cloud_checksum. Compare it against the cloud’s current
checksum:
"""Tell whether a grid was built from the point cloud as it exists today.
The API does not flag, warn, or block on staleness — this comparison is yoursto make."""
import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
grid = ff.get_grid("your-domain-id", "your-chm-grid-id")source = grid.to_dict()["source"]built_from = source["source_point_cloud_checksum"]
point_cloud = ff.get_point_cloud("your-domain-id", source["source_point_cloud_id"])
print(f"grid was built from: {built_from}")print(f"point cloud is now: {point_cloud.checksum}")
if built_from != point_cloud.checksum: print("STALE — the point cloud's content changed after this grid was built.")else: print("Current.")grid was built from: 690b4bf260244d8db52e1eaa6888ad49point cloud is now: 690b4bf260244d8db52e1eaa6888ad49Current.Delete
Section titled “Delete”curl -X 'DELETE' \ 'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/pointclouds/your-point-cloud-id' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -o /dev/null -w 'HTTP %{http_code}\n'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
point_cloud = ff.get_point_cloud("your-domain-id", "your-point-cloud-id")
# The stored points are gone; a later get raises NotFoundException (404).point_cloud.delete(){ "detail": "Document not found: pointclouds/your-point-cloud-id"}A 204, and the stored points are gone.
Two consequences worth knowing:
- Derived grids are not cascaded. A CHM built from this cloud keeps working;
it holds its own raster data. What it loses is the ability to resolve
source.source_point_cloud_id— the checksum it recorded now refers to something that no longer exists. - Deleting the domain is different. A domain holding point clouds returns a
412 unless you pass
force=true, which deletes the clouds with it.
Next steps
Section titled “Next steps”- Inspect a point cloud — decide what is worth keeping.
- About quotas — the limits point clouds consume.
- About point clouds — the checksum contract and the lifecycle behind it.
Common pitfalls
Section titled “Common pitfalls”sort_order=desc. Returns a 422; usedescending.- Expecting
tagsto append.PATCHreplaces the list. Send the full set. - Expecting
PATCHto change the data. Content is immutable — there is no endpoint that edits points. - Assuming a metadata edit invalidates derived grids. It does not, by design.
- Deleting a cloud to free storage and expecting derived grids to shrink. They hold their own data and are unaffected.