End-to-End Ordering Quickstart
This guide walks you through the complete workflow for purchasing satellite imagery via the DataCosmos API — from authentication to downloading your data. Each step builds on the previous one, showing how data flows through the entire process.
By the end of this guide you will have:
- Authenticated and obtained an access token
- Searched the STAC catalogue for satellite imagery
- Placed an order and completed checkout
- Downloaded the purchased data
NOTE
A complete runnable script combining all steps is provided at the end of this page.
Prerequisites
Before you begin, make sure you have:
- A valid token (JWT) — To get API credentials follow the steps described in the Authentication page.
- Organisation ID — Your organisation's numeric identifier (associated with your account).
- Contract ID — The contract under which purchases are made.
For Bash examples: curl and jq must be installed.
For Python examples: Install the requests library:
pip install requests
Step 1: Authenticate
All DataCosmos API calls require a bearer token. Obtain one by following the steps described in the Authentication page.
Bash
# Authenticate and store the access token
DATACOSMOS_ACCESS_TOKEN="<your access token here>"
Python
import requests
access_token = "<your access token here>"
session = requests.Session()
session.headers.update(
{"Authorization": f'Bearer {access_token}'}
)
print("Authentication configuration completed.")
NOTE
The Python examples use a requests.Session object that automatically includes the bearer token in all subsequent requests. For full details see the Authentication page.
Step 2: Search the Catalogue
Use the STAC Search API to find satellite images matching your area of interest. This example searches for Sentinel-2 L2A images over a bounding box in Chile with less than 20% cloud cover.
Endpoint
POST https://app.open-cosmos.com/api/data/v0/stac/search
Bash
# Search for Sentinel-2 images with low cloud cover in a bounding box
SEARCH_RESULTS=$(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,
"query": {
"eo:cloudcover": {
"lte": 20
}
}
}')
# Extract the first result's collection and item IDs
COLLECTION=$(echo "$SEARCH_RESULTS" | jq -r '.features[0].collection')
ITEM_ID=$(echo "$SEARCH_RESULTS" | jq -r '.features[0].id')
echo "Found item: ${COLLECTION} / ${ITEM_ID}"
Python
# Search for Sentinel-2 images with low cloud cover
search_body = {
"collections": ["sentinel-2-l2a"],
"bbox": [-71.72, -27.68, -71.02, -27.06],
"limit": 5,
"query": {
"eo:cloudcover": {
"lte": 20,
},
},
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/stac/search",
json=search_body,
)
search_results = response.json()
features = search_results.get("features", [])
if not features:
print("No results found. Try adjusting your search parameters.")
else:
# Pick the first result
selected_item = features[0]
collection = selected_item["collection"]
item_id = selected_item["id"]
price = selected_item["properties"]["opencosmos:price"]
currency = selected_item["properties"]["opencosmos:price_currency"]
print(f"Found {len(features)} result(s). Selected: {collection} / {item_id} ({price} {currency})")
NOTE
The bbox parameter uses the format [west, south, east, north] in decimal degrees. The query parameter supports CQL filters such as eo:cloudcover. See the STAC Search API for all available search parameters.
Step 3: Place an Order
Create an order for the selected item. If required (depends on the user configuration), you will need to initiate the checkout with the payment gateway to complete payment.
3a. Create the Order
Endpoint
POST https://app.open-cosmos.com/api/data/v0/order/orders
Bash
# Create an order for the selected item
ORDER_RESPONSE=$(curl --request POST "https://app.open-cosmos.com/api/data/v0/order/orders" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw "{
\"type\": \"IMAGE\",
\"data\": {
\"order_line_items\": [
{
\"collection\": \"${COLLECTION}\",
\"item\": \"${ITEM_ID}\",
\"level\": \"L2A\"
}
]
},
\"organisation\": YOUR_ORGANISATION_ID,
\"contract_id\": YOUR_CONTRACT_ID,
\"licenses\": [
{
\"license_link\": \"https://example.com/license/eula-v1\",
\"license_name\": \"DataCosmos EULA\",
\"license_version\": \"1.0\",
\"accepted\": true
}
]
}")
ORDER_ID=$(echo "$ORDER_RESPONSE" | jq -r '.data.id')
ORDER_STATUS=$(echo "$ORDER_RESPONSE" | jq -r '.data.status')
echo "Order created: ${ORDER_ID} (status: ${ORDER_STATUS})"
Python
# Create an order for the selected item
order_payload = {
"type": "IMAGE",
"data": {
"order_line_items": [
{
"collection": collection,
"item": item_id,
"level": "L2A",
}
]
},
"organisation": YOUR_ORGANISATION_ID, # Replace with your organisation ID
"contract_id": YOUR_CONTRACT_ID, # Replace with your contract ID
"licenses": [
{
"license_link": "https://example.com/license/eula-v1",
"license_name": "DataCosmos EULA",
"license_version": "1.0",
"accepted": True,
}
],
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/order/orders",
json=order_payload,
)
order = response.json()["data"]
order_id = order["id"]
print(f"Order created: {order_id} (status: {order['status']})")
3b. Initiate Checkout
If the order requires payment, use the checkout endpoint to get a checkout payment URL. If the payment URL is not provided no redirection is needed.
Endpoint
GET https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}/checkout
Bash
# Get the checkout URL
CHECKOUT_RESPONSE=$(curl --request GET \
"https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}/checkout" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}")
CHECKOUT_URL=$(echo "$CHECKOUT_RESPONSE" | jq -r '.data.checkout_url')
echo "Complete payment at: ${CHECKOUT_URL}"
Python
# Get the checkout URL
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}/checkout",
)
checkout_url = response.json()["data"]["checkout_url"]
print(f"Complete payment at: {checkout_url}")
NOTE
The create order response may already include a checkout_redirect_url. If so, you can use that URL directly without calling the checkout endpoint separately. See Purchasing Catalog Images for full details on order management.
Step 4: Download Data
After completing payment, poll the order status until it changes to PAID, then download the assets from the STAC item.
4a. Wait for Payment Confirmation
Bash
# Poll until the order is paid
MAX_ATTEMPTS=30
POLL_INTERVAL=10
for i in $(seq 1 $MAX_ATTEMPTS); do
STATUS=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" | jq -r '.data.status')
echo "Attempt ${i}: status = ${STATUS}"
if [ "$STATUS" = "PAID" ]; then
echo "Payment confirmed!"
break
elif [ "$STATUS" = "CANCELLED" ]; then
echo "Order was cancelled."
break
fi
sleep $POLL_INTERVAL
done
Python
import time
# Poll until the order is paid
max_attempts = 30
poll_interval_seconds = 10
for attempt in range(max_attempts):
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}",
)
status = response.json()["data"]["status"]
if status == "PAID":
print("Payment confirmed!")
break
elif status == "CANCELLED":
print("Order was cancelled.")
break
else:
print(f"Attempt {attempt + 1}: status = {status} — waiting {poll_interval_seconds}s...")
time.sleep(poll_interval_seconds)
4b. Download Assets
Once the order is paid, retrieve the STAC item and download all associated assets.
Bash
# Download all assets from the purchased item
ITEM_RESPONSE=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/stac/collections/${COLLECTION}/items/${ITEM_ID}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}")
# Download each asset
echo "$ITEM_RESPONSE" | jq -r '.assets | to_entries[] | "\(.value.title)\t\(.value.href)"' | while IFS=$'\t' read -r title href; do
echo "Downloading: ${title}"
curl --silent --output "${title}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
"${href}"
done
echo "All assets downloaded."
Python
import os
# Retrieve the STAC item to get asset download links
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item_id}",
)
item_data = response.json()
# Download each asset
for asset_key, asset in item_data["assets"].items():
filename = asset.get("title", asset_key)
print(f"Downloading: {filename}")
asset_response = session.get(asset["href"])
with open(filename, "wb") as fp:
fp.write(asset_response.content)
print("All assets downloaded.")
Complete End-to-End Scripts
Below are complete, runnable scripts that combine all five steps into a single workflow.
Python
"""
DataCosmos End-to-End Ordering Example
Prerequisites:
- pip install requests
- data_cosmos_api_credentials.json in the same directory
- Replace YOUR_ORGANISATION_ID and YOUR_CONTRACT_ID with real values
"""
import json
import os
import time
import requests
# ──────────────────────────────────────────────
# Configuration
# ──────────────────────────────────────────────
CREDENTIALS_FILE = "data_cosmos_api_credentials.json"
ORGANISATION_ID = 42 # Replace with your organisation ID
CONTRACT_ID = 456 # Replace with your contract ID
DOWNLOAD_DIR = "downloads"
# ──────────────────────────────────────────────
# Step 1: Authenticate
# ──────────────────────────────────────────────
print("Step 1: Authenticating...")
with open(CREDENTIALS_FILE) as fp:
oauth_body = json.load(fp)
session = requests.Session()
token_response = session.post(
"https://login.open-cosmos.com/oauth/token",
data=oauth_body,
).json()
session.headers.update(
{"Authorization": f'{token_response["token_type"]} {token_response["access_token"]}'}
)
print(" Authenticated successfully.\n")
# ──────────────────────────────────────────────
# Step 2: Search the Catalogue
# ──────────────────────────────────────────────
print("Step 2: Searching the catalogue...")
search_body = {
"collections": ["sentinel-2-l2a"],
"bbox": [-71.72, -27.68, -71.02, -27.06],
"limit": 5,
"query": {
"eo:cloudcover": {
"lte": 20,
},
},
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/stac/search",
json=search_body,
)
response.raise_for_status()
features = response.json().get("features", [])
if not features:
print(" No results found. Try adjusting your search parameters.")
exit(1)
selected_item = features[0]
collection = selected_item["collection"]
item_id = selected_item["id"]
print(f" Found {len(features)} result(s). Selected: {collection} / {item_id}\n")
# ──────────────────────────────────────────────
# Step 3: Retrieve Pricing
# ──────────────────────────────────────────────
print("Step 3: Retrieving pricing...")
response = session.get(
"https://app.open-cosmos.com/api/data/v0/order/price",
params={"collection": collection, "item": item_id, "level": "L2A"},
)
response.raise_for_status()
price_data = response.json()["data"]
print(f" Price: {price_data['final']} {price_data['currency']}\n")
# ──────────────────────────────────────────────
# Step 4: Place an Order
# ──────────────────────────────────────────────
print("Step 4: Creating order...")
order_payload = {
"type": "IMAGE",
"data": {
"order_line_items": [
{
"collection": collection,
"item": item_id,
"level": "L2A",
}
]
},
"organisation": ORGANISATION_ID,
"contract_id": CONTRACT_ID,
"licenses": [
{
"license_link": "https://example.com/license/eula-v1",
"license_name": "DataCosmos EULA",
"license_version": "1.0",
"accepted": True,
}
],
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/order/orders",
json=order_payload,
)
response.raise_for_status()
order = response.json()["data"]
order_id = order["id"]
print(f" Order created: {order_id} (status: {order['status']})")
# Get checkout URL
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}/checkout",
)
response.raise_for_status()
checkout_url = response.json()["data"]["checkout_url"]
print(f" Complete payment at: {checkout_url}\n")
# ──────────────────────────────────────────────
# Step 5: Wait for Payment and Download Data
# ──────────────────────────────────────────────
print("Step 5: Waiting for payment confirmation...")
max_attempts = 30
poll_interval = 10
for attempt in range(max_attempts):
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}",
)
status = response.json()["data"]["status"]
if status == "PAID":
print(" Payment confirmed!\n")
break
elif status == "CANCELLED":
print(" Order was cancelled.")
exit(1)
else:
print(f" Attempt {attempt + 1}: status = {status} — waiting {poll_interval}s...")
time.sleep(poll_interval)
# Download assets
print("Downloading assets...")
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/stac/collections/{collection}/items/{item_id}",
)
response.raise_for_status()
item_data = response.json()
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
for asset_key, asset in item_data["assets"].items():
filename = asset.get("title", asset_key)
filepath = os.path.join(DOWNLOAD_DIR, filename)
print(f" Downloading: {filename}")
asset_response = session.get(asset["href"])
with open(filepath, "wb") as fp:
fp.write(asset_response.content)
print(f"\nDone! All assets saved to '{DOWNLOAD_DIR}/'.")
Bash
#!/usr/bin/env bash
#
# DataCosmos End-to-End Ordering Example
#
# Prerequisites:
# - curl and jq installed
# - data_cosmos_api_credentials.json in the same directory
# - Replace YOUR_ORGANISATION_ID and YOUR_CONTRACT_ID below
#
set -euo pipefail
# ──────────────────────────────────────────────
# Configuration
# ──────────────────────────────────────────────
CREDENTIALS_FILE="data_cosmos_api_credentials.json"
ORGANISATION_ID=42 # Replace with your organisation ID
CONTRACT_ID=456 # Replace with your contract ID
DOWNLOAD_DIR="downloads"
# ──────────────────────────────────────────────
# Step 1: Authenticate
# ──────────────────────────────────────────────
echo "Step 1: Authenticating..."
DATACOSMOS_ACCESS_TOKEN=$(curl --silent --request POST "https://login.open-cosmos.com/oauth/token" \
--header "Content-Type: application/json" \
-d @"${CREDENTIALS_FILE}" | jq -r ".access_token")
echo " Authenticated successfully."
echo ""
# ──────────────────────────────────────────────
# Step 2: Search the Catalogue
# ──────────────────────────────────────────────
echo "Step 2: Searching the catalogue..."
SEARCH_RESULTS=$(curl --silent --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,
"query": {
"eo:cloudcover": {
"lte": 20
}
}
}')
RESULT_COUNT=$(echo "$SEARCH_RESULTS" | jq '.features | length')
COLLECTION=$(echo "$SEARCH_RESULTS" | jq -r '.features[0].collection')
ITEM_ID=$(echo "$SEARCH_RESULTS" | jq -r '.features[0].id')
echo " Found ${RESULT_COUNT} result(s). Selected: ${COLLECTION} / ${ITEM_ID}"
echo ""
# ──────────────────────────────────────────────
# Step 3: Retrieve Pricing
# ──────────────────────────────────────────────
echo "Step 3: Retrieving pricing..."
PRICE_RESPONSE=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/order/price?collection=${COLLECTION}&item=${ITEM_ID}&level=L2A" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}")
FINAL_PRICE=$(echo "$PRICE_RESPONSE" | jq -r '.data.final')
CURRENCY=$(echo "$PRICE_RESPONSE" | jq -r '.data.currency')
echo " Price: ${FINAL_PRICE} ${CURRENCY}"
echo ""
# ──────────────────────────────────────────────
# Step 4: Place an Order
# ──────────────────────────────────────────────
echo "Step 4: Creating order..."
ORDER_RESPONSE=$(curl --silent --request POST "https://app.open-cosmos.com/api/data/v0/order/orders" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw "{
\"type\": \"IMAGE\",
\"data\": {
\"order_line_items\": [
{
\"collection\": \"${COLLECTION}\",
\"item\": \"${ITEM_ID}\",
\"level\": \"L2A\"
}
]
},
\"organisation\": ${ORGANISATION_ID},
\"contract_id\": ${CONTRACT_ID},
\"licenses\": [
{
\"license_link\": \"https://example.com/license/eula-v1\",
\"license_name\": \"DataCosmos EULA\",
\"license_version\": \"1.0\",
\"accepted\": true
}
]
}")
ORDER_ID=$(echo "$ORDER_RESPONSE" | jq -r '.data.id')
ORDER_STATUS=$(echo "$ORDER_RESPONSE" | jq -r '.data.status')
echo " Order created: ${ORDER_ID} (status: ${ORDER_STATUS})"
CHECKOUT_RESPONSE=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}/checkout" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}")
CHECKOUT_URL=$(echo "$CHECKOUT_RESPONSE" | jq -r '.data.checkout_url')
echo " Complete payment at: ${CHECKOUT_URL}"
echo ""
# ──────────────────────────────────────────────
# Step 5: Wait for Payment and Download Data
# ──────────────────────────────────────────────
echo "Step 5: Waiting for payment confirmation..."
MAX_ATTEMPTS=30
POLL_INTERVAL=10
for i in $(seq 1 $MAX_ATTEMPTS); do
STATUS=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" | jq -r '.data.status')
if [ "$STATUS" = "PAID" ]; then
echo " Payment confirmed!"
break
elif [ "$STATUS" = "CANCELLED" ]; then
echo " Order was cancelled."
exit 1
fi
echo " Attempt ${i}: status = ${STATUS} — waiting ${POLL_INTERVAL}s..."
sleep $POLL_INTERVAL
done
echo ""
echo "Downloading assets..."
mkdir -p "${DOWNLOAD_DIR}"
ITEM_RESPONSE=$(curl --silent --request GET \
"https://app.open-cosmos.com/api/data/v0/stac/collections/${COLLECTION}/items/${ITEM_ID}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}")
echo "$ITEM_RESPONSE" | jq -r '.assets | to_entries[] | "\(.value.title)\t\(.value.href)"' | while IFS=$'\t' read -r title href; do
echo " Downloading: ${title}"
curl --silent --output "${DOWNLOAD_DIR}/${title}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
"${href}"
done
echo ""
echo "Done! All assets saved to '${DOWNLOAD_DIR}/'."
Where to Next
For more detail on each step, see these pages:
- Authentication — Token management, OAuthlib examples, and credential setup.
- DataCosmos Developer Center — Full STAC search guide, project items, and advanced queries.
- Pricing API — Custom geometry pricing, batch pricing, and response details.
- Purchasing Catalog Images — Multi-item orders, order updates, cancellation, and error handling.
- Ordering API Reference — Full OpenAPI specification for all ordering endpoints.