SpatioTemporal Asset Catalogs (STAC)
STAC provides a common standard for organising and displaying geospatial information that is simple and lightweight. Any asset that captures information of the Earth in both time and geospatial extents can be considered a spatio-temporal asset.
This page describes the STAC entities used in DataCosmos and includes code examples for common catalog operations.
NOTE
The Python examples on this page require the requests library.
Catalog
A Catalog is a top-level object that logically groups together other Catalogs, Collections and Items. It contains an array of Link objects, each of which links to another resource, typically another Catalog or Collection.
- id - Unique identifier used when querying for Items in this Collection.
- title - Title of the Collection: e.g. "Mantis L1D Data Products".
- description - A human readable description of the Collection.
- links - List of objects containing URLs to other related STAC objects.
- href - A URL link to the corresponding object.
- rel - Relationship between the current and linked documents can be either self, root, parent, child or Item.
- type - Specifies the content-type of the linked object.
- title - Human readable title that can be rendered in displays of the link.
Collection
The STAC Collection specification defines a set of common fields to describe a group of Items that share properties and metadata, and is represented in a JSON format. More information on the required and optional fields of the Collection can be found in the STAC specification.
DataCosmos Collections use the following fields with corresponding descriptions of their purpose.
- id - Unique identifier used when querying for Items in this Collection.
- title - Title of the Collection: e.g. "Mantis L1D Data Products".
- description - A human readable description of the Collection.
- license - A string that identifies the applicable license for the Collection and data contained within it. This will contain the DataCosmos EULA.
- providers - A list of providers that includes the organisations responsible for capturing, processing and hosting the data in a chronological order.
- extent
- spatial - The spatial range in latitude and longitude that the Collection covers. This value is updated over time as new Items are assigned to the Collection.
- temporal - The temporal range specifying the time window the Collection covers. This value is updated over time as new Items are assigned to the Collection.
- summaries - A mapping of key:value summaries where the value can be either a string, range or JSON object. When present, summaries are enforced during Item creation and update: each Item's properties must satisfy the constraints defined in the Collection's summaries (see Creating Items for details). This validation does not apply to project collections.
- platform - List of strings specifying the satellite platform the data product is captured from.
- instrument - List of strings specifying the payload instruments used to capture the data products.
- gsd - The minimum and maximum GSD of the data products.
- eo:bands - Defined as part of the EO extension
- name - Name of the corresponding band in the Collection's Items.
- common_name - Name commonly used to refer to the band from an accepted list of names to allow for searching across instruments.
- description - Description of the corresponding band.
- center_wavelength - The center wavelength of the band in micrometers.
- links - List of objects containing URLs to other related STAC objects.
- item_assets - List of asset objects that match the assets contained within each Item of the Collection. This is used to predetermine the keys of the assets before searching the Collection. Defined as part of the Item Assets extension.
Item
A STAC Item is an augmented GeoJSON Feature object that contains additional fields as part of the STAC specification. These additional fields provide more information on the data contained within the Item and can be used for filtering during searches. The STAC Item inherits the id, type, bbox, geometry and properties fields from the GeoJSON standard. More information on the specification and fields used in the Item definition can be found in the STAC Item specification
- id - Unique ID corresponding to the Item.
- geometry - GeoJSON object that describes the footprint of the Item. Coordinates specified in longitude and latitude. This geometry object is used when searching for data products within a specified geographical region. Formatted according to RFC 7946.
- bounding box - Bounding box of the Item, formatted according to RFC 7946.
- collection - ID of the Collection the Item belongs to.
- properties - Dictionary of additional metadata
- datetime - The acquisition time of the image. Field used when searching for data products within a specified time range.
- created - Timestamp for when the data product was created in the database.
- updated - Timestamp for when the data product was created in the database.
- platform - String specifying the satellite platform the data product is captured from.
- instruments - List of strings specifying the payload instruments used to capture the data products.
- gsd - The GSD of the data product.
- view:off_nadir - Angle between nadir and the pointing of the sensor.
- view:incidence_angle - Angle between the normal to the intercepting surfaces and line of sight to the sensor from the scene center.
- view:azimuth - Angle measured from the sub-satellite point between the scene center and true north.
- view:sun_azimuth - Angle from true north at the scene center to the center point of the sun.
- view:sun_elevation - Angle from the tangent of the scene center point to the sun.
- eo:cloud_cover - The percentage of cloud coverage in the data products. Added as part of the STAC EO extension.
- opencosmos:price - The price of the data product for the authenticated user. This value is dynamically computed on each request and reflects the terms of the user's contract. See the note on pricing below.
- opencosmos:price_currency - The currency of the price (e.g.
GBP,USD). - opencosmos:high_resolution_read_permission - A boolean indicating whether the authenticated user has access to the high-resolution assets of this item.
- opencosmos:data_area_km2 - The area of the data product footprint in square kilometres.
- assets - Contain a list of objects that describe each of the associated assets with the data product such as the image data and metadata files.
- title - Title of the asset.
- description - Human readable description of what the asset contains.
- href - Required. Contains an absolute URL (
https://...) pointing to the asset in DataCosmos file storage. Relative or local file paths are not accepted. The URL must follow the storage path structure described in Storage Structure and Paths. - type - Contains the content-type of the asset to enable end user applications to automatically read the source data.
- roles - Defined by the STAC specification, roles are used to describe the purpose of each asset. More information can be found in the Item specification.
- links - List of objects containing URLs to other related STAC objects.
Extensions
There are several extensions which have been proposed and added to the STAC specification. In order to make the DataCosmos STAC database easier to navigate and richer with information we have adopted the following extensions as standard.
- View Geometry - Adds metadata related to angles of sensors and other radiance angles that affect the view of resulting data.
- Electro-Optical - Adds metadata relating to the EO data bands and cloud coverage.
- Item Assets - Adds common Item assets to the Collection to provide a human readable and programmatic way of determining assets available in the Collection's Items.
- Query - Enables property-based filtering of Items during searches using comparison operators such as
eq,neq,lt,lte,gt,gte,startsWith,endsWith,contains, andin.
IMPORTANT
The DataCosmos STAC API uses the STAC Query Extension for advanced property filtering. This is distinct from the OGC CQL2 Filter Extension (/filter), which is a newer standard used by some other STAC implementations. The Query Extension uses a query field in the POST body of search requests with operator-based constraints (e.g. {"eo:cloud_cover": {"lte": 20}}).
A Note on Pricing
When retrieving Items from the catalog (whether through the search endpoint, listing items in a collection, or fetching a single item) each Item can include pricing information in its properties (opencosmos:price and opencosmos:price_currency).
Getting prices in search results
Prices are not returned by default. To include opencosmos:price and opencosmos:price_currency in the results you must provide one of the following:
You only need to provide one of the following — they are alternatives, not both required:
| Parameter | Where (POST) | Where (GET) | Description |
|---|---|---|---|
project | JSON body | Query parameter | A project ID. The service resolves the contract automatically via the project's organisation. This is the most common approach. |
contract_id | JSON body | Query parameter | The contract ID to use for pricing directly. Use this if you already know your contract ID and are not working in a project context. |
If neither is provided, opencosmos:price and opencosmos:price_currency are omitted from all returned Items.
Example — POST search using a project ID (recommended):
curl --request POST "https://app.open-cosmos.com/api/data/v0/stac/search" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"collections": ["sentinel-2-l2a"],
"bbox": [-71.72, -27.68, -71.02, -27.06],
"limit": 5,
"project": "your-project-id"
}'
Example — POST search using a contract ID directly:
curl --request POST "https://app.open-cosmos.com/api/data/v0/stac/search" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"collections": ["sentinel-2-l2a"],
"bbox": [-71.72, -27.68, -71.02, -27.06],
"limit": 5,
"contract_id": 456
}'
Example — read the price from a single item:
import requests
# Get bearer token and add to session
collection = "mantis-l1d-cogs"
item_id = "MANTIS_L1D_000000_20211001000000_20211001101010_E274"
response = session.get(f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item_id}")
item = response.json()
price = item.get("properties", {}).get("opencosmos:price")
currency = item.get("properties", {}).get("opencosmos:price_currency")
print(f"Price: {price} {currency}")
Example — read prices from search results:
import requests
# Get bearer token and add to session
body = {
"bbox": [-71.71875, -27.68, -71.01, -27.05],
"collections": ["mantis-l1d-cogs"],
}
response = session.post("https://app.open-cosmos.com/api/data/v0/stac/search", json=body)
results = response.json()
for feature in results.get("features", []):
item_id = feature["id"]
price = feature.get("properties", {}).get("opencosmos:price")
currency = feature.get("properties", {}).get("opencosmos:price_currency")
print(f"Item: {item_id} - Price: {price} {currency}")
Important considerations
- Prices are calculated dynamically on every request. They are not stored as part of the Item metadata. Each time you request an Item, the price is freshly computed based on your account's contract terms.
- Prices are personalised. The price returned is specific to the authenticated user making the request. Different users may see different prices for the same Item depending on their contract.
- Do not store or cache prices. Because prices depend on your contract terms and may change over time, you should always retrieve a fresh price from the API before presenting it to end users or using it in purchasing decisions. Any previously retrieved price should be treated as indicative only.
- The currency is included alongside the price. Always use the
opencosmos:price_currencyfield to determine the currency of the quoted price rather than assuming a default.
Storage Structure and Paths
Assets uploaded to DataCosmos file storage must follow a consistent directory structure. For catalog storage, the path format is:
https://app.open-cosmos.com/api/data/v0/storage/catalog/<collection>/<year>/<month>/<day>/<item_id>/<asset_name>.<extension>
Where:
<collection>must match the target collection ID (e.g.satellite-l1a-cogs)<year>/<month>/<day>must correspond to the acquisition date of the data (i.e. thedatetimeproperty of the STAC Item, or within thestart_datetimetoend_datetimerange). It must not use the processing time or upload time.<item_id>must match theidfield of the STAC Item
Creating Items (Assets-First Workflow)
When creating a STAC Item via the API (POST /collections/<collection-id>/items), the following requirements must be met:
- Write permission and collection existence — The user must have write permission on the target collection, and the collection must already exist. A missing permission results in
403 Forbidden; a non-existent collection results in404 Not Found. - Absolute URLs — Asset
hrefvalues must be absolute URLs (https://...) pointing to files in DataCosmos file storage. Relative paths, local file paths, or other URI schemes are not accepted. - Assets must exist before item creation — The server performs a HEAD request on each asset href and will reject the Item with a
422error if any asset is not accessible (e.g. returns 404). Assets that have not yet been generated should be omitted from the Item and added later via an update. - Date matching — The date component in the storage path (
<year>/<month>/<day>) must match the Item's acquisition date. The server uses thedatetimeproperty to determine the expected date. Only ifdatetimeis not set will it fall back to thestart_datetimeandend_datetimerange. The processing time (e.g. theupdatedproperty) must not be used in the storage path. - Item ID matching — The item ID directory in the storage path must match the Item's
idfield. - Collection matching — The storage path must correspond to the correct collection. The
<collection>segment in the path must match the target collection (e.g. for collectionheleo-vhr-vnir-l1a-cogs, the path usesstorage/catalog/heleo-vhr-vnir-l1a-cogs/...). - Collection summaries enforcement — If the target collection defines summaries, each summary field is enforced against the Item's properties. The rules are: (a) if the summary is a list of values, the Item's property must be one of the listed values; (b) if the summary defines a range (
minimum/maximum), the Item's property must fall within that range; (c) if the summary is a JSON Schema, the Item's property must validate against it; (d) if the summary is a single constant, the Item's property must match exactly. If a summary field is declared on the collection but the corresponding property is missing ornullon the Item, the request is rejected with a422error. This validation does not apply to project collections. - Items without assets — Items may be created with no assets. In that case, asset validation is skipped entirely and assets can be added later via an update.
Example:
curl --request POST "https://app.open-cosmos.com/api/data/v0/stac/collections/satellite-l1a-cogs/items" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"id": "SATELLITE_L1A_000000001_20240211120932_20240211121015_A1B2C3D4",
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[-24.94, 64.59], [-19.66, 64.59], [-19.66, 63.12], [-24.94, 63.12], [-24.94, 64.59]]]
},
"properties": {
"datetime": "2024-02-11T12:09:32Z",
"processing:level": "L1A"
},
"links": [],
"assets": {
"thumbnail": {
"href": "https://app.open-cosmos.com/api/data/v0/storage/catalog/satellite-l1a-cogs/2024/02/11/SATELLITE_L1A_000000001_20240211120932_20240211121015_A1B2C3D4/thumbnail.webp",
"title": "Thumbnail",
"type": "image/webp",
"roles": ["thumbnail"]
},
"data": {
"href": "https://app.open-cosmos.com/api/data/v0/storage/catalog/satellite-l1a-cogs/2024/02/11/SATELLITE_L1A_000000001_20240211120932_20240211121015_A1B2C3D4/data.tiff",
"title": "Image data",
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"roles": ["data"]
}
},
"collection": "satellite-l1a-cogs",
"bbox": [-24.94, 63.12, -19.66, 64.59]
}'
NOTE
In this example, the date in the asset path (2024/02/11) matches the datetime property (2024-02-11T12:09:32Z), and the collection name in the storage path (satellite-l1a-cogs) matches the target collection. All assets must have been uploaded to file storage before this request is made.
API Examples
Search Collections
Requesting all available Collections is useful when initially exploring the API to see what data is available to you.
Bash
curl --request GET "https://app.open-cosmos.com/api/data/v0/stac/collections" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session
response = session.get("https://app.open-cosmos.com/api/data/v0/stac/collections")
print(response.json())
Search Items in a Collection
Once you have found a Collection that you are interested in, you can search through all the Items it contains.
The search endpoint accepts a collections query parameter to filter by collection. Search parameters are passed as URL query parameters.
This example returns a list of items from the specified Collection within a bounding box. If the results exceed the limit, they will be paginated. The full list of query parameters is documented in the Search API.
Bash
curl --request GET "https://app.open-cosmos.com/api/data/v0/stac/search?collections=mantis-l1d-cogs&bbox=160.6,-55.95,-170,-25.89&limit=100/2021-03-18T12:31:12Z" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session
params = {
"collections": "mantis-l1d-cogs",
"bbox": [160.6, -55.95, -170, -25.89],
"limit": 100,
}
response = session.get("https://app.open-cosmos.com/api/data/v0/stac/search", params=params)
print(response.json())
Advanced Search
The search endpoint also supports a POST request, allowing search parameters to be specified in the request body rather than the URL.
The body supports all the same parameters as the GET request. In addition, the query field supports advanced property filtering using the STAC Query Extension, which defines comparison operators (eq, neq, lt, lte, gt, gte, startsWith, endsWith, contains, in).
NOTE
The DataCosmos API uses the STAC Query Extension for property-based filtering — not the OGC CQL2 Filter Extension. While CQL2 is the newer OGC standard adopted by some STAC APIs, our implementation supports the Query Extension syntax shown below.
This example searches for all Items within a given bounding box with less than 20% cloud coverage.
Bash
curl --request POST "https://app.open-cosmos.com/api/data/v0/stac/search" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"bbox": [
-71.71875,-27.683528083787767,-71.015625,-27.05912578437406
],
"query":{
"eo:cloudcover":{
"lte": 20
}
}
}'
Python
import requests
# Get bearer token and add to session
body = {
"bbox": [-71.71875,-27.683528083787767,-71.015625,-27.05912578437406],
"query": {
"eo:cloudcover": {
"lte": 20,
},
},
}
response = session.post("https://app.open-cosmos.com/api/data/v0/stac/search", json=body)
print(response.json())
Working with Project Items
If you have access to a specific project, you can retrieve and search for items within that project using dedicated endpoints. These endpoints behave similarly to the regular STAC collection endpoints but are specific to project data.
Get all Items from a Project
Bash
curl --request GET "https://app.open-cosmos.com/api/data/v0/scenario/scenario/YOUR-PROJECT-ID/items" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session
project_id = "YOUR-PROJECT-ID"
response = session.get(f"https://app.open-cosmos.com/api/data/v0/scenario/scenario/{project_id}/items")
print(response.json())
Search for Items in a Project
To find specific items within a project, such as the newest items, use the project search endpoint. This endpoint only accepts POST and allows filtering by various parameters including dates.
Bash
curl --request POST "https://app.open-cosmos.com/api/data/v0/scenario/scenario/YOUR-PROJECT-ID/search" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"datetime": "2023-01-01T00:00:00Z/2023-12-31T23:59:59Z"
}'
Python
import requests
# Get bearer token and add to session
project_id = "YOUR-PROJECT-ID"
body = {
"datetime": "2023-01-01T00:00:00Z/2023-12-31T23:59:59Z"
}
response = session.post(f"https://app.open-cosmos.com/api/data/v0/scenario/scenario/{project_id}/search", json=body)
print(response.json())
Get an Item
A single Item can be retrieved when its ID is known. This is useful for storing a reference to an Item and querying it again later.
Bash
curl --request GET "https://app.open-cosmos.com/api/data/v0/stac/collections/mantis-l1d-cogs/items/MANTIS_L1D_000000_20211001000000_20211001101010_E274" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session
collection = "mantis-l1d-cogs"
item = "MANTIS_L1D_000000_20211001000000_20211001101010_E274"
response = session.get(f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item}")
print(response.json())
Checking Item Access Permissions
Each Item contains a property indicating whether you have full access to its high-resolution assets:
opencosmos:high_resolution_read_permission:truemeans the authenticated user has full access to all assets;falseindicates limited access.
import requests
# Get bearer token and add to session
collection = "mantis-l1d-cogs"
item_id = "MANTIS_L1D_000000_20211001000000_20211001101010_E274"
response = session.get(f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item_id}")
item = response.json()
has_full_access = item.get("properties", {}).get("opencosmos:high_resolution_read_permission", False)
print(f"Has full access to high-resolution assets: {has_full_access}")
Download Assets from an Item
The assets field of an Item contains links to all source data. The most relevant field is href, which provides a direct download URL.
This example retrieves a specific item and downloads all its assets to local storage.
Bash
curl --request GET "https://app.open-cosmos.com/api/data/v0/stac/collections/mantis-l1d-cogs/items/MANTIS_L1D_000000_20211001000000_20211001101010_E274" \
--header "Content-Type: application/json" --header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session
collection = "mantis-l1d-cogs"
item = "MANTIS_L1D_000000_20211001000000_20211001101010_E274"
response = session.get(f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item}")
item = response.json()
for _, asset in item["assets"].items():
asset_content = session.get(asset["href"])
with open(asset["title"], "wb") as fp:
fp.write(asset_content.content)
Asset Data Integrity Validation
Downloaded assets can be verified for corruption by inspecting the digest header in the HTTP response. The header contains MD5 and CRC32C checksums:
HTTP/1.1 200 OK
content-length: 648299
content-type: application/json
digest: md5=53t0Dmr45bDtRPLBdR7K-g==,crc32c=3521063897
last-modified: Tue, 27 May 2025 12:58:51 GMT
You can compare these values against the downloaded file to ensure data integrity.
Asset Data Types
DataCosmos provides the most specific MIME type for each asset. For example:
- JSON files:
application/json - Cloud-Optimized GeoTIFFs:
image/tiff; application=geotiff; profile=cloud-optimized - Thumbnails:
image/webp
The type field of each asset object indicates the content type, enabling client applications to automatically select the appropriate reader for the source data.
Webhooks
The platform supports webhook notifications when new data is added to a specific collection. This functionality must be configured by an Open Cosmos administrator.
Configuration
To set up webhooks, provide Open Cosmos with the public URL of the endpoint you would like to receive notifications on. Once configured, the platform will send an HTTP POST request to that endpoint whenever a new item is created in the monitored collection.
Webhook Payload
The body of the POST request contains a JSON object with the following format:
{
"type": "stac-item",
"status": "created",
"detail": {
"collection_id": "menut-l1c-cogs",
"item_id": "MENUT_L1C_000002344_20250612212638_20250612212647_8E020E6A",
"url": "https://app.open-cosmos.com/api/data/v0/stac/collections/menut-l1c-cogs/items/MENUT_L1C_000002344_20250612212638_20250612212647_8E020E6A",
"datetime": "2025-06-12T21:26:47Z",
"bbox": [-17.0159586786598, 64.0540935633377, -16.1038985287222, 64.7314354132683]
}
}
| Field | Description |
|---|---|
type | The type of resource that triggered the notification (e.g. stac-item) |
status | The event that occurred (e.g. created) |
detail.collection_id | The ID of the collection the new item belongs to |
detail.item_id | The ID of the newly created item |
detail.url | The full URL to fetch the complete STAC item via the API |
detail.datetime | The acquisition datetime of the item |
detail.bbox | The bounding box of the item |
Once a webhook notification is received, you can use the url field to query the full STAC item and retrieve all associated assets and metadata.
NOTE
Webhook configuration is managed by Open Cosmos. Contact the DataCosmos team to set up webhooks for your collections.
Where to Next