Purchasing Catalog Images
This page describes how to create an order for catalog images, complete the payment using your organisation's credit balance, and manage existing orders through the API.
NOTE
All endpoints require a valid bearer token. See the Authentication page for details.
Create an Order
Creates a new order for one or more catalog images. The order will be in UNPAID status until payment is completed.
Endpoint
POST https://app.open-cosmos.com/api/data/v0/order/orders
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
redirect_host | string | No | Override the default redirect URL after checkout completion. |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "IMAGE" for catalog purchases. |
data | object | Yes | Contains the order_line_items array. |
data.order_line_items | array | Yes | Array of items to purchase (see below). |
organisation | integer | Yes | Your organisation's numeric ID. |
contract_id | integer | Yes | The contract ID for this purchase. See how to retrieve your contract ID. |
Order Line Item fields:
| Field | Type | Required | Description |
|---|---|---|---|
collection | string | Yes | The STAC collection ID. |
item | string | Yes | The STAC item ID. |
level | string | Yes | The processing level (e.g. L2A). |
Response
The response includes the created order with a unique ID, status, and computed prices for each line item.
NOTE
If your organisation has sufficient credits, the order is paid immediately as part of this request. The response will show "status": "PAID" and "checkout_redirect_url": "". No separate checkout call is needed. See Payment with Credits below.
When credits cover the full order total (order already paid — no further action needed):
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "IMAGE",
"customer_id": "cus-abc123",
"organisation_id": 42,
"contract_id": 456,
"status": "PAID",
"payment_method": "NOT_REQUIRED",
"payment_reference_number": "",
"order_line_items": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"collection": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230615T100559_N0509_R022_T33UUP_20230615T135959",
"level": "L2A",
"price": {
"value": "150.00",
"discount": "0",
"final": "150.00",
"currency": "USD"
},
"is_downloaded": false,
"delivered": false,
"paid": true,
"visualized_count": 0,
"downloaded_count": 0
}
],
"checkout_redirect_url": "",
"created_by": "google-apps|user@example.com",
"created_at": "2026-01-21T12:00:00Z",
"updated_at": "2026-01-21T12:00:00Z"
}
}
When credits are insufficient (order remains unpaid — contact Open Cosmos support to purchase additional credits):
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "IMAGE",
"customer_id": "cus-abc123",
"organisation_id": 42,
"contract_id": 456,
"status": "UNPAID",
"payment_method": "NOT_REQUIRED",
"payment_reference_number": "",
"order_line_items": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"collection": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230615T100559_N0509_R022_T33UUP_20230615T135959",
"level": "L2A",
"price": {
"value": "150.00",
"discount": "0",
"final": "150.00",
"currency": "USD"
},
"is_downloaded": false,
"delivered": false,
"paid": false,
"visualized_count": 0,
"downloaded_count": 0
}
],
"checkout_redirect_url": "",
"created_by": "google-apps|user@example.com",
"created_at": "2026-01-21T12:00:00Z",
"updated_at": "2026-01-21T12:00:00Z"
}
}
Examples
Bash
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": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230615T100559_N0509_R022_T33UUP_20230615T135959",
"level": "L2A"
}
]
},
"organisation": 42,
"contract_id": 456
}'
Python
import requests
# Get bearer token and add to session (see Authentication docs)
order_payload = {
"type": "IMAGE",
"data": {
"order_line_items": [
{
"collection": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230615T100559_N0509_R022_T33UUP_20230615T135959",
"level": "L2A",
}
]
},
"organisation": 42,
"contract_id": 456,
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/order/orders",
json=order_payload,
)
order = response.json()
print(f"Order ID: {order['data']['id']}")
print(f"Status: {order['data']['status']}")
print(f"Checkout URL: {order['data']['checkout_redirect_url']}")
Purchasing Multiple Items in a Single Order
You can include multiple items in the order_line_items array to purchase them together in a single order:
order_payload = {
"type": "IMAGE",
"data": {
"order_line_items": [
{
"collection": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230615T100559_N0509_R022_T33UUP_20230615T135959",
"level": "L2A",
},
{
"collection": "sentinel-2-l2a",
"item": "S2A_MSIL2A_20230620T101021_N0509_R022_T33UUP_20230620T140000",
"level": "L2A",
},
]
},
"organisation": 42,
"contract_id": 456,
}
response = session.post(
"https://app.open-cosmos.com/api/data/v0/order/orders",
json=order_payload,
)
order = response.json()
for item in order["data"]["order_line_items"]:
print(f"Item: {item['item']} — Price: {item['price']['final']} {item['price']['currency']}")
Payment with Credits
If your organisation has a credit balance, credits are always applied automatically during the POST /orders request itself. This applies to both UI and API purchases.
When credits fully cover the order
When your organisation's available credit balance is equal to or greater than the order total, the POST /orders request completes the purchase immediately — no browser redirect is needed and no separate checkout call is required. Credits are deducted and the order status is set to PAID within the same request.
The create order response will show "status": "PAID" and an empty "checkout_redirect_url":
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "PAID",
"payment_method": "NOT_REQUIRED",
"checkout_redirect_url": ""
}
}
An empty checkout_redirect_url in the create response is not an error. It means the order has already been paid with credits and the purchased data is available.
TIP
For fully automated or M2M (machine-to-machine) workflows, ensure your organisation's credit balance covers expected orders. When it does, the entire purchase flow reduces to two API calls — create order, verify status — with no browser interaction required.
When credits do not fully cover the order
If your credit balance is insufficient to cover the full order total, the order status will be UNPAID and the checkout_redirect_url field will be empty. To proceed, contact Open Cosmos support to purchase additional credits. Once your balance has been topped up, submit the order again.
See the Credits user manual for details on credit balances, expiry, and top-ups.
Get Order Details
Retrieves the full details of a specific order, including its current status and line items.
Endpoint
GET https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | UUID | Yes | The ID of the order to retrieve. |
Response
Returns a full OrderResponse object (same structure as the create order response).
Examples
Bash
ORDER_ID="550e8400-e29b-41d4-a716-446655440000"
curl --request GET "https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session (see Authentication docs)
order_id = "550e8400-e29b-41d4-a716-446655440000"
response = session.get(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}",
)
order = response.json()
print(f"Order status: {order['data']['status']}")
Polling for Payment Completion
You can poll the order status to detect when payment has been completed. If the order was paid with credits, the status will already be PAID immediately and the first poll will return straight away:
import time
import requests
# Get bearer token and add to session (see Authentication docs)
order_id = "550e8400-e29b-41d4-a716-446655440000"
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}",
)
order = response.json()
status = order["data"]["status"]
if status == "PAID":
print("Payment completed successfully!")
break
elif status == "CANCELLED":
print("Order was cancelled.")
break
else:
print(f"Status: {status} — waiting {poll_interval_seconds}s...")
time.sleep(poll_interval_seconds)
List Orders
Retrieves a list of your orders, optionally filtered by order IDs.
Endpoint
GET https://app.open-cosmos.com/api/data/v0/order/orders
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | UUID[] | No | One or more order IDs to filter by. Can be repeated for multiple IDs. |
Response
Returns an array of OrderResponse objects.
Examples
Bash
# List all orders
curl --request GET "https://app.open-cosmos.com/api/data/v0/order/orders" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
# Filter by specific order IDs
curl --request GET "https://app.open-cosmos.com/api/data/v0/order/orders?order_id=550e8400-e29b-41d4-a716-446655440000&order_id=660f9500-f30c-52e5-b827-557766551111" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}"
Python
import requests
# Get bearer token and add to session (see Authentication docs)
# List all orders
response = session.get(
"https://app.open-cosmos.com/api/data/v0/order/orders",
)
orders = response.json()
for order in orders["data"]:
print(f"Order {order['id']}: {order['status']}")
Update or Cancel an Order
Updates an existing order's status or payment method. This can be used to cancel an unpaid order or change the payment method.
Endpoint
PATCH https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | UUID | Yes | The ID of the order to update. |
Request Body
All fields are optional. Only include the fields you want to update.
| Field | Type | Description |
|---|---|---|
status | string | New status: UNPAID, PAID, or CANCELLED. |
payment_method | string | New payment method: BANK_TRANSFER, CARD, or NOT_REQUIRED. |
Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Examples
Cancel an order (Bash)
ORDER_ID="550e8400-e29b-41d4-a716-446655440000"
curl --request PATCH "https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${DATACOSMOS_ACCESS_TOKEN}" \
--data-raw '{
"status": "CANCELLED"
}'
Cancel an order (Python)
import requests
# Get bearer token and add to session (see Authentication docs)
order_id = "550e8400-e29b-41d4-a716-446655440000"
response = session.patch(
f"https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}",
json={"status": "CANCELLED"},
)
result = response.json()
print(f"Order {result['data']['id']} has been cancelled.")
Error Responses
All ordering endpoints return errors in a consistent format:
{
"errors": [
{
"type": "invalid_input",
"message": "order line item must have collection, item and level",
"field": "order_line_item",
"source": "order-service",
"trace_id": "abc123def456"
}
]
}
Common Error Codes
| HTTP Status | Type | Description |
|---|---|---|
400 | invalid_input | The request body or parameters are invalid. |
401 | unauthorized | Missing or invalid bearer token. |
403 | forbidden | You do not have permission to access this resource. |
404 | not_found | The specified order or item was not found. |
500 | internal_error | An unexpected server error occurred. |
Where to Next
← Pricing API | API Reference →