diff --git a/datasets/query/querying-data.mdx b/datasets/query/querying-data.mdx
index 496d38d..bdc578f 100644
--- a/datasets/query/querying-data.mdx
+++ b/datasets/query/querying-data.mdx
@@ -113,6 +113,8 @@ if err != nil {
```
+Some datasets include assets that point to files in object storage. After selecting one datapoint, use an [asset collection and the storage client](/datasets/assets-and-storage/read-and-download) to read or download those files.
+
To learn more about how to narrow down query results, see the following pages about filtering by time, geometry, custom
fields, or datapoint ID.
diff --git a/datasets/storage/clients.mdx b/datasets/storage/clients.mdx
index 5aec9b0..844dfb2 100644
--- a/datasets/storage/clients.mdx
+++ b/datasets/storage/clients.mdx
@@ -1,9 +1,13 @@
---
-title: Storage Clients
-description: Configure and use storage clients in the Tilebox Python SDK to access satellite data products from public providers and local file systems.
+title: Legacy storage clients
+description: Deprecated provider-specific clients for downloading open data products.
icon: hard-drive
---
+
+ The provider-specific storage clients on this page are deprecated. Use [asset collections and the storage client](/datasets/assets-and-storage/overview) for new integrations. Migration guidance for existing integrations will follow.
+
+
Tilebox does not host the actual open data satellite products but instead relies on publicly accessible storage providers for data access.
Tilebox ingests available metadata as [datasets](/datasets/concepts/datasets) to enable high performance querying and structured access of the data as [xarray.Dataset](/sdks/python/xarray).
diff --git a/docs.json b/docs.json
index 1f556bb..c418e7f 100644
--- a/docs.json
+++ b/docs.json
@@ -75,7 +75,16 @@
"datasets/delete",
"datasets/geometries",
"datasets/open-data",
- "datasets/storage/clients"
+ {
+ "group": "Assets and storage",
+ "icon": "boxes-stacked",
+ "pages": [
+ "datasets/assets-and-storage/overview",
+ "datasets/assets-and-storage/read-and-download",
+ "datasets/assets-and-storage/reference-assets",
+ "datasets/storage/clients"
+ ]
+ }
]
},
{
@@ -150,7 +159,6 @@
"pages": [
"guides/datasets/query-satellite-data",
"guides/datasets/access-sentinel2-data",
- "guides/datasets/access-usgs-landsat-data",
"guides/datasets/build-spatiotemporal-catalog",
"guides/datasets/ingest-into-spatiotemporal-catalog",
"guides/datasets/ingest-format"
@@ -235,6 +243,32 @@
"api-reference/python/tilebox.datasets/Collection.query"
]
},
+ {
+ "group": "tilebox.datasets.assets",
+ "pages": [
+ "api-reference/python/tilebox.datasets.assets/Asset",
+ "api-reference/python/tilebox.datasets.assets/AssetLocation",
+ "api-reference/python/tilebox.datasets.assets/Band",
+ "api-reference/python/tilebox.datasets.assets/AssetCollection",
+ "api-reference/python/tilebox.datasets.assets/AssetCollection.from_datapoint",
+ "api-reference/python/tilebox.datasets.assets/AssetCollection.from_assets",
+ "api-reference/python/tilebox.datasets.assets/AssetCollection.to_fields"
+ ]
+ },
+ {
+ "group": "tilebox.storage.aio",
+ "pages": [
+ "api-reference/python/tilebox.storage.aio/Client",
+ "api-reference/python/tilebox.storage.aio/AssetAccessPolicy",
+ "api-reference/python/tilebox.storage.aio/ResolvedAsset",
+ "api-reference/python/tilebox.storage.aio/Client.resolve",
+ "api-reference/python/tilebox.storage.aio/Client.read_bytes",
+ "api-reference/python/tilebox.storage.aio/Client.iter_bytes",
+ "api-reference/python/tilebox.storage.aio/Client.download",
+ "api-reference/python/tilebox.storage.aio/Client.open_geotiff",
+ "api-reference/python/tilebox.storage.aio/window_from_bounds"
+ ]
+ },
{
"group": "tilebox.workflows",
"pages": [
diff --git a/guides/cookbook.mdx b/guides/cookbook.mdx
index 5190baa..31155ec 100644
--- a/guides/cookbook.mdx
+++ b/guides/cookbook.mdx
@@ -21,31 +21,22 @@ export const cookbookSections = [
tags: ["Open data", "Sentinel-2", "Metadata queries", "Spatial filters"],
},
{
- title: "Access Copernicus data",
+ title: "Access Sentinel-2 assets",
href: "/guides/datasets/access-sentinel2-data",
- description: "Download Copernicus product files with the storage client, using Sentinel-2 as an example.",
+ description: "Read a COG window or download a Sentinel-2 image with the storage client.",
icon: "magnifying-glass-location",
level: "Beginner",
time: "10 min",
- tags: ["Copernicus", "Storage clients", "Sentinel-2", "Product files"],
- },
- {
- title: "Access USGS Landsat data",
- href: "/guides/datasets/access-usgs-landsat-data",
- description: "Download USGS Landsat product files with the storage client, using Landsat 8 as an example.",
- icon: "satellite-dish",
- level: "Beginner",
- time: "10 min",
- tags: ["USGS", "Landsat 8", "Storage clients", "Product files"],
+ tags: ["Assets", "COG", "Sentinel-2", "Storage client"],
},
{
title: "Build a spatio-temporal catalog",
href: "/guides/datasets/build-spatiotemporal-catalog",
- description: "Create, document, ingest, and query a custom geospatial catalog with the Python SDK.",
+ description: "Create, document, ingest, and query a geospatial catalog with asset references.",
icon: "globe",
level: "Intermediate",
time: "20 min",
- tags: ["Spatio-temporal datasets", "Dataset schemas", "Ingestion", "Python SDK"],
+ tags: ["Spatio-temporal datasets", "Assets", "Ingestion", "Python SDK"],
},
{
title: "Ingest into a spatio-temporal catalog",
diff --git a/guides/datasets/access-sentinel2-data.mdx b/guides/datasets/access-sentinel2-data.mdx
index ba299d2..08bbd2b 100644
--- a/guides/datasets/access-sentinel2-data.mdx
+++ b/guides/datasets/access-sentinel2-data.mdx
@@ -1,19 +1,19 @@
---
-title: Access Copernicus data
-description: Download Copernicus Data Space products with the Tilebox Copernicus storage client, using Sentinel-2 as an example.
-icon: database
+title: Access Sentinel-2 assets
+description: Query Sentinel-2 metadata and read or download the corresponding image assets.
+icon: satellite
---
-Use this guide when you already have a Copernicus datapoint from a Tilebox metadata query and want to access the product files behind it. The example uses Sentinel-2 Level-2A data, but the same storage client pattern applies to Copernicus products supported by Tilebox.
+Tilebox indexes Sentinel-2 metadata and asset locations in the `open_data.aws_earth.sentinel2` dataset. Query the metadata first, then use the storage client to read only the image data you need.
-Tilebox indexes product metadata as datasets. Product files remain in the Copernicus Data Space Ecosystem, so file access uses the `CopernicusStorageClient` with Copernicus S3 credentials.
+
+ Asset collections and the storage client are currently available in the Python SDK.
+
## Prerequisites
- You have a [Tilebox API key](/authentication).
-- You have installed the [Python SDK](/sdks/python/install).
-- You have a [Copernicus Data Space](https://dataspace.copernicus.eu/) account.
-- You have generated Copernicus [S3 credentials](https://eodata-s3keysmanager.dataspace.copernicus.eu/panel/s3-credentials).
+- You have installed the [Python SDK](/sdks/python/install) with Python 3.11 or newer.
```bash
uv add tilebox shapely
@@ -21,125 +21,88 @@ uv add tilebox shapely
## Select a Sentinel-2 datapoint
-Start with a small metadata query and select one datapoint to access. For a deeper guide to open data discovery and metadata filtering, see [Query open data metadata](/guides/datasets/query-satellite-data).
+Query a small time and area of interest, then select one low-cloud observation:
```python Python
-from shapely import Polygon
-from tilebox.datasets import Client
-
-area = Polygon(
- [
- (-109.05, 37.0),
- (-102.05, 37.0),
- (-102.05, 41.0),
- (-109.05, 41.0),
- (-109.05, 37.0),
- ]
-)
+from shapely import box
+from tilebox.datasets import Client, field
-client = Client()
-collection = client.dataset("open_data.copernicus.sentinel2_msi").collection("S2A_S2MSI2A")
+datasets = Client()
+collection = datasets.dataset("open_data.aws_earth.sentinel2").collection("L2A")
scenes = collection.query(
temporal_extent=("2025-10-01", "2025-11-01"),
- spatial_extent=area,
- show_progress=True,
+ spatial_extent=box(-106.0, 38.0, -105.9, 38.1),
+ filter=field("cloud_cover") < 10,
)
-selected = scenes.where(scenes.cloud_cover < 10, drop=True).isel(time=0)
-print(selected.granule_name.item())
+datapoint = scenes.isel(time=0)
+print(datapoint.stac_id.item())
```
-## Create the Copernicus storage client
-
-Create a `CopernicusStorageClient` with your Copernicus S3 credentials. The optional `cache_directory` controls where downloaded files are stored locally.
-
-```python Python
-from pathlib import Path
+See [Query open data metadata](/guides/datasets/query-satellite-data) for more query patterns.
-from tilebox.storage import CopernicusStorageClient
+## Resolve the assets
-storage = CopernicusStorageClient(
- access_key="YOUR_COPERNICUS_ACCESS_KEY",
- secret_access_key="YOUR_COPERNICUS_SECRET_ACCESS_KEY",
- cache_directory=Path("./data"),
-)
-```
-
-
- These credentials are Copernicus Data Space S3 credentials, not your Tilebox API key.
-
-
-## Download the complete product
-
-Use `download` when you need the complete Sentinel-2 product directory. The storage client resolves the product location from the Tilebox datapoint metadata and downloads the matching files into the local cache directory.
+Turn the selected datapoint into an asset collection. Each asset describes one file and the locations from which it can be accessed.
```python Python
-product_path = storage.download(selected)
+from tilebox.datasets.assets import AssetCollection
-print(f"Downloaded {product_path.name} to {product_path}")
-print("Contents:")
-for path in product_path.iterdir():
- print(f"- {path.relative_to(product_path)}")
-```
+assets = AssetCollection.from_datapoint(datapoint)
-```plaintext Output
-Downloaded S2A_MSIL2A_20251002T180751_N0511_R084_T13TEE_20251002T225842.SAFE to data/Sentinel-2/MSI/L2A/2025/10/02/S2A_MSIL2A_20251002T180751_N0511_R084_T13TEE_20251002T225842.SAFE
-Contents:
-- manifest.safe
-- GRANULE
-- INSPIRE.xml
-- MTD_MSIL2A.xml
-- DATASTRIP
-- HTML
-- rep_info
-- S2A_MSIL2A_20251002T180751_N0511_R084_T13TEE_20251002T225842-ql.jpg
+for key, asset in assets.items():
+ print(key, asset.media_type)
+
+red = assets["red"]
```
-## Download selected product files
+## Read a Cloud Optimized GeoTIFF window
-Sentinel-2 products contain many files, including metadata, masks, quicklook images, and bands at different resolutions. Use `list_objects` and `download_objects` when you only need specific files.
+The Sentinel-2 image assets are Cloud Optimized GeoTIFFs (COGs). Open an image remotely and request a pixel window without downloading the complete file:
```python Python
-objects = storage.list_objects(selected)
-
-wanted_bands = ["B02_10m", "B03_10m", "B04_10m", "B08_10m"]
-band_objects = [
- obj for obj in objects
- if any(band in obj for band in wanted_bands)
-]
-
-for obj in band_objects:
- print(obj)
-
-downloaded_files = storage.download_objects(selected, band_objects)
-print(downloaded_files)
+import asyncio
+
+from tilebox.storage.aio import Client
+from tilebox.storage.geotiff import window_from_bounds
+
+async def read_area():
+ storage = Client()
+ geotiff = await storage.open_geotiff(red)
+ window = window_from_bounds(
+ geotiff,
+ (-106.0, 38.0, -105.9, 38.1),
+ crs="EPSG:4326",
+ )
+ return await geotiff.read(window=window)
+
+pixels = asyncio.run(read_area())
+print(pixels.shape)
```
-Use this pattern when a workflow only needs a few bands or metadata files. It reduces transfer time and local storage compared with downloading the full `.SAFE` product.
+`window_from_bounds` transforms geographic bounds into the image coordinate system and clips the resulting window to the image.
-## Preview the product
+## Download an asset
-Many Copernicus products include a quicklook image. In a notebook, use `quicklook` to display the product preview without downloading the full product first.
+Use `download` when you need the complete file locally:
```python Python
-storage.quicklook(selected)
-```
+async def download_red_band():
+ storage = Client()
+ return await storage.download(red, "data/sentinel-2-red.tif")
-
-
-
+path = asyncio.run(download_red_band())
+print(path)
+```
## Next steps
-
- Find Copernicus products by time, location, and metadata fields.
-
-
- Learn about the other Tilebox storage clients for open data products.
+
+ Learn about streaming, downloads, GeoTIFF access, and location selection.
-
- Download Landsat product files with the USGS Landsat storage client.
+
+ Understand how asset metadata connects dataset queries to file storage.
diff --git a/guides/datasets/access-usgs-landsat-data.mdx b/guides/datasets/access-usgs-landsat-data.mdx
deleted file mode 100644
index 38fa5f3..0000000
--- a/guides/datasets/access-usgs-landsat-data.mdx
+++ /dev/null
@@ -1,138 +0,0 @@
----
-title: Access USGS Landsat data
-description: Download USGS Landsat products with the Tilebox Landsat storage client, using Landsat 8 as an example.
-icon: satellite-dish
----
-
-Use this guide when you already have a Landsat datapoint from a Tilebox metadata query and want to access the product files behind it. The example uses Landsat 8 Collection 2 Level-2 surface reflectance data.
-
-Tilebox indexes Landsat metadata as datasets. Product files remain in the USGS public cloud archive, so file access uses the `USGSLandsatStorageClient` and your AWS requester-pays setup.
-
-## Prerequisites
-
-- You have a [Tilebox API key](/authentication).
-- You have installed the [Python SDK](/sdks/python/install).
-- You have AWS credentials configured in your environment.
-- Your AWS account can access [requester-pays S3 buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RequesterPaysBuckets.html).
-
-```bash
-uv add tilebox shapely
-```
-
-
- USGS Landsat data is stored in a requester-pays S3 bucket. AWS charges for requests and data transfer according to your AWS account settings.
-
-
-## Select a Landsat 8 datapoint
-
-Start with a small metadata query and select one datapoint to access. For a deeper guide to open data discovery and metadata filtering, see [Query open data metadata](/guides/datasets/query-satellite-data).
-
-```python Python
-from shapely import Polygon
-from tilebox.datasets import Client
-
-area = Polygon(
- [
- (-109.05, 37.0),
- (-102.05, 37.0),
- (-102.05, 41.0),
- (-109.05, 41.0),
- (-109.05, 37.0),
- ]
-)
-
-client = Client()
-collection = client.dataset("open_data.usgs.landsat8_oli_tirs").collection("L2_SR")
-
-scenes = collection.query(
- temporal_extent=("2024-08-01", "2024-08-15"),
- spatial_extent=area,
- show_progress=True,
-)
-
-selected = scenes.where(scenes.cloud_cover < 10, drop=True).isel(time=0)
-print(selected.granule_name.item())
-```
-
-## Create the Landsat storage client
-
-Create a `USGSLandsatStorageClient`. The client uses AWS credentials from your environment, such as `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` when needed.
-
-```python Python
-from tilebox.storage import USGSLandsatStorageClient
-
-storage = USGSLandsatStorageClient()
-```
-
-## Download the complete product
-
-Use `download` when you need the complete Landsat product directory. The storage client resolves the product location from the Tilebox datapoint metadata and downloads the matching files into the local cache.
-
-```python Python
-product_path = storage.download(selected)
-
-print(f"Downloaded {product_path.name} to {product_path}")
-print("Contents:")
-for path in product_path.iterdir():
- print(f"- {path.relative_to(product_path)}")
-```
-
-```plaintext Output
-Downloaded LC08_L2SP_033033_20240808_20240814_02_T1 to ~/.cache/tilebox/collection02/level-2/standard/oli-tirs/2024/033/033/LC08_L2SP_033033_20240808_20240814_02_T1
-Contents:
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B1.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B2.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B3.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B4.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B5.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B6.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_SR_B7.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_QA_PIXEL.TIF
-- LC08_L2SP_033033_20240808_20240814_02_T1_MTL.json
-- LC08_L2SP_033033_20240808_20240814_02_T1_thumb_small.jpeg
-```
-
-## Download selected product files
-
-Landsat products contain surface reflectance bands, quality masks, thermal bands, metadata, and preview images. Use `list_objects` and `download_objects` when you only need specific files.
-
-```python Python
-objects = storage.list_objects(selected)
-
-rgb_bands = ["B4", "B3", "B2"]
-rgb_objects = [
- obj for obj in objects
- if any(obj.endswith(f"_{band}.TIF") for band in rgb_bands)
-]
-
-for obj in rgb_objects:
- print(obj)
-
-downloaded_files = storage.download_objects(selected, rgb_objects)
-print(downloaded_files)
-```
-
-Use this pattern when a workflow only needs a few bands, masks, or metadata files. It reduces transfer time and local storage compared with downloading the full product.
-
-## Preview the product
-
-Many Landsat products include a thumbnail image. In a notebook, use `quicklook` to display the product preview without downloading the full product first.
-
-```python Python
-storage.quicklook(selected)
-```
-
-
-
-
-
-## Next steps
-
-
-
- Find Landsat products by time, location, and metadata fields.
-
-
- Learn about the other Tilebox storage clients for open data products.
-
-
diff --git a/guides/datasets/build-spatiotemporal-catalog.mdx b/guides/datasets/build-spatiotemporal-catalog.mdx
index 50aabb3..a578658 100644
--- a/guides/datasets/build-spatiotemporal-catalog.mdx
+++ b/guides/datasets/build-spatiotemporal-catalog.mdx
@@ -6,7 +6,7 @@ icon: globe
Use a spatio-temporal dataset when each datapoint has both a time and a geometry. This is useful for internal imagery catalogs, derived products, ground truth data, regions of interest, and processing outputs that need geospatial lookup.
-This guide creates an imagery catalog from code. You will define the dataset schema with the Python SDK, add field descriptions and examples for generated schema documentation, create a collection, ingest geospatial metadata, and query the catalog by time, location, and custom fields.
+This guide creates an imagery catalog from code. You will define the dataset schema with the Python SDK, reference the image files as assets, ingest geospatial metadata, and query the catalog by time, location, and custom fields.
## Prerequisites
@@ -21,11 +21,12 @@ uv add tilebox geopandas shapely
Start by choosing the spatio-temporal dataset kind and the custom fields for your catalog. Tilebox adds the required `time`, `id`, `ingestion_time`, and `geometry` fields automatically.
-The example catalog tracks imagery products with a provider product ID, a storage location, cloud cover, and processing level. Field descriptions and example values become part of the generated schema documentation.
+The example catalog tracks imagery products with a provider product ID, file assets, cloud cover, and processing level. Field descriptions and example values become part of the generated schema documentation.
```python Python
from tilebox.datasets import Client
from tilebox.datasets.data.datasets import DatasetKind
+from tilebox.datasets.schema import Assets
client = Client()
@@ -37,10 +38,9 @@ fields = [
"example_value": "LC08_L2SP_033033_20240808_20240814_02_T1",
},
{
- "name": "location",
- "type": str,
- "description": "Storage path, object key, or provider-specific product location.",
- "example_value": "s3://example-bucket/landsat/LC08_L2SP_033033_20240808_20240814_02_T1",
+ "name": "assets",
+ "type": Assets,
+ "description": "Files associated with the imagery product.",
},
{
"name": "cloud_cover",
@@ -97,7 +97,7 @@ For this catalog, the complete schema includes:
| `ingestion_time` | Required | No | Time when Tilebox ingested the datapoint. |
| `geometry` | Required | Dedicated spatial filter | Geometry used for spatial queries. |
| `product_id` | Custom | No | Stable product or scene identifier. |
-| `location` | Custom | No | Storage path or provider product location. |
+| `assets` | Custom | No | Files associated with the imagery product. |
| `cloud_cover` | Custom | Yes | Cloud cover percentage for filtering. |
| `processing_level` | Custom | Yes | Provider processing level or product type. |
@@ -149,21 +149,46 @@ products = products.rename(
columns={
"timestamp": "time",
"scene": "product_id",
- "path": "location",
+ "path": "source_href",
}
)
products = products[
- ["time", "geometry", "product_id", "location", "cloud_cover", "processing_level"]
+ ["time", "geometry", "product_id", "source_href", "cloud_cover", "processing_level"]
]
```
+## Add asset references
+
+Convert each source file into an asset collection, then add its dataset fields to the record:
+
+```python Python
+from tilebox.datasets.assets import Asset, AssetCollection, AssetLocation, MediaType
+
+records = []
+for record in products.to_dict(orient="records"):
+ source_href = record.pop("source_href")
+ assets = AssetCollection.from_assets(
+ [
+ Asset(
+ key="image",
+ primary=AssetLocation(source_href),
+ media_type=MediaType.CLOUD_OPTIMIZED_GEOTIFF,
+ roles=frozenset({"data"}),
+ )
+ ]
+ )
+ records.append({**record, **assets.to_fields()})
+```
+
+`AssetCollection.from_assets` validates and normalizes the metadata into the structure consumed by the storage client. It does not upload the referenced file or test its availability.
+
## Ingest the catalog
Ingest the prepared records into a collection.
```python Python
-collection.ingest(products)
+collection.ingest(records)
```
## Query by time, location, and custom fields
diff --git a/guides/datasets/query-satellite-data.mdx b/guides/datasets/query-satellite-data.mdx
index d417192..584af04 100644
--- a/guides/datasets/query-satellite-data.mdx
+++ b/guides/datasets/query-satellite-data.mdx
@@ -1,12 +1,10 @@
---
title: Query open satellite data
-description: Explore available Tilebox open data catalogs and query Sentinel-2 metadata by time and location.
+description: Query Sentinel-2 metadata by time, location, and cloud cover.
icon: satellite
---
-Use this guide when you want to find satellite products in Tilebox open data catalogs before downloading any files. You will first inspect the available open data datasets, then query Sentinel-2 metadata by time and location.
-
-Tilebox Datasets stores searchable metadata for open Earth observation catalogs. Metadata queries are the fastest way to narrow a large catalog to the scenes that match your workflow, notebook, or agent task.
+Tilebox indexes searchable metadata for public Earth observation catalogs. Use metadata queries to find relevant observations before reading or downloading their image assets.
## Prerequisites
@@ -17,106 +15,55 @@ Tilebox Datasets stores searchable metadata for open Earth observation catalogs.
uv add tilebox shapely
```
-## Explore available open data datasets
+## Select the Sentinel-2 catalog
-Tilebox exposes open data catalogs through the same dataset API as your private datasets. To get a list of available open data satellite datasets, run the following snippet.
+Open the Sentinel-2 dataset and its Level-2A collection:
```python Python
-from tilebox.datasets import Client
+from tilebox.datasets import Client, field
client = Client()
-datasets = client.datasets()
-print(datasets.open_data)
+sentinel2 = client.dataset("open_data.aws_earth.sentinel2")
+collection = sentinel2.collection("L2A")
```
-The output groups datasets by provider. Open data datasets include Copernicus Sentinel missions, USGS Landsat products, ASF SAR products, and other public catalogs that Tilebox has indexed.
-
-```plaintext Output
-asf:
- ers_sar: European Remote Sensing Satellite (ERS) Synthetic Aperture Radar ...
-copernicus:
- sentinel1_sar: The Sentinel-1 mission is the European Radar Observatory ...
- sentinel2_msi: Sentinel-2 is equipped with an optical instrument payload ...
- sentinel3_olci: OLCI (Ocean and Land Colour Instrument) is an optical ...
- ...
-usgs:
- ...
- landsat8_oli_tirs: Landsat-8 Operational Land Imager and Thermal Infrared ...
- landsat9_oli_tirs: Landsat-9 Operational Land Imager and Thermal Infrared ...
-```
+You can browse other open datasets and inspect their schemas in the [Tilebox Console](https://console.tilebox.com/datasets/open-data).
-You can also browse open data datasets in the [Tilebox Console](https://console.tilebox.com/datasets/open-data) when you want descriptions, provider details, the dataset schema, and available collections before writing code.
-
-## Select the Sentinel-2 catalog
+## Query observation metadata
-Access the Sentinel-2 MSI dataset by its slug. The dataset contains collections for Sentinel-2 products such as `S2A_S2MSI2A`.
+Query by time and area of interest. The result contains metadata and asset references, but does not download image bytes.
```python Python
-sentinel2 = client.dataset("open_data.copernicus.sentinel2_msi")
+from shapely import box
-for name, collection in sentinel2.collections().items():
- print(name, collection)
-```
-
-## Define the search area
-
-Create a polygon for the area you want to inspect. This example uses a bounding box around Colorado.
-
-```python Python
-from shapely import Polygon
-
-area = Polygon(
- [
- # lon, lat
- (-109.05, 37.0),
- (-102.05, 37.0),
- (-102.05, 41.0),
- (-109.05, 41.0),
- # close the square (repeat the first element)
- (-109.05, 37.0),
- ]
-)
-```
-
-## Query Sentinel-2 metadata
-
-Query the Sentinel-2 Level-2A collection by time and location. This returns metadata for matching scenes; it does not download image products.
-
-```python Python
-collection = sentinel2.collection("S2A_S2MSI2A")
+area = box(-109.05, 37.0, -102.05, 41.0)
scenes = collection.query(
temporal_extent=("2025-10-01", "2025-11-01"),
spatial_extent=area,
+ filter=field("cloud_cover") < 10,
show_progress=True,
)
-print(scenes[["granule_name", "processing_level", "product_type"]])
+print(scenes[["stac_id", "cloud_cover", "platform"]])
```
-The result is an `xarray.Dataset` containing scene metadata. Use it to inspect candidate scenes, filter by metadata fields, or pass selected datapoints to a workflow task.
-
-## Filter the metadata result
-
-Metadata results behave like regular `xarray.Dataset` objects. You can filter, sort, or select scenes before deciding what to process next.
+The result is an `xarray.Dataset`. Use regular xarray operations to sort or select observations:
```python Python
-low_cloud = scenes.where(scenes.cloud_cover < 10, drop=True)
-latest = low_cloud.sortby("time").isel(time=-1)
+latest = scenes.sortby("time").isel(time=-1)
-print(latest.granule_name.item())
+print(latest.stac_id.item())
print(latest.cloud_cover.item())
```
-Metadata queries do not download product files. Use a [storage client](/datasets/storage/clients) when you want to read or download the files referenced by a datapoint.
-
## Next steps
-
- Download Copernicus product files with the storage client.
+
+ Read a COG window or download an image from a selected datapoint.
-
- Configure provider-specific clients for product access.
+
+ Learn more dataset query patterns.
diff --git a/index.mdx b/index.mdx
index 58fa7a3..e9d3dec 100644
--- a/index.mdx
+++ b/index.mdx
@@ -309,7 +309,7 @@ func (t *ComputeVisibleChange) Execute(ctx context.Context) error {
-
+
diff --git a/sdks/python/async.mdx b/sdks/python/async.mdx
index 3e8bcc8..1fbf6c2 100644
--- a/sdks/python/async.mdx
+++ b/sdks/python/async.mdx
@@ -78,6 +78,25 @@ datapoint = await collection.find(datapoint_uuid)
`await some_async_call()` as the output of a code cell.
+## Accessing assets asynchronously
+
+The storage client is asynchronous. Resolve the assets from one queried datapoint, then await the storage operation:
+
+```python Python
+from tilebox.datasets.assets import AssetCollection
+from tilebox.storage.aio import Client as StorageClient
+
+datasets = await client.datasets()
+collections = await datasets.open_data.aws_earth.sentinel2.collections()
+data = await collections["L2A"].query(temporal_extent=("2025-01-01", "2025-01-02"))
+
+assets = AssetCollection.from_datapoint(data.isel(time=0))
+storage = StorageClient()
+contents = await storage.read_bytes(assets["thumbnail"], max_bytes=10_000_000)
+```
+
+See [Read and download assets](/datasets/assets-and-storage/read-and-download) for streaming, downloads, and GeoTIFF window reads.
+
## Fetching data concurrently
The primary benefit of the async client is that it allows concurrent requests, enhancing performance.
diff --git a/sdks/python/install.mdx b/sdks/python/install.mdx
index 311cefe..363661f 100644
--- a/sdks/python/install.mdx
+++ b/sdks/python/install.mdx
@@ -15,6 +15,9 @@ Tilebox offers a Python SDK for accessing Tilebox services. The SDK includes sep
Workflow client and runner for Tilebox
+
+ Read and download assets from object storage
+
## Installation
@@ -68,8 +71,8 @@ from tilebox.datasets import Client
client = Client()
datasets = client.datasets()
-collection = datasets.open_data.copernicus.landsat8_oli_tirs.collection("L1T")
-data = collection.query(temporal_extent=("2015-01-01", "2020-01-01"), show_progress=True)
+collection = datasets.open_data.aws_earth.sentinel2.collection("L2A")
+data = collection.query(temporal_extent=("2025-01-01", "2025-01-02"), show_progress=True)
data
```