Purchasing Catalog Images
This page describes how to create an order for catalog images, complete the payment (automatically with credits or via Stripe), 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). |
geometry | object | No | A GeoJSON geometry object for sub-area purchases. Must be paired with project_id. |
project_id | string | No | The project ID to associate the item with. Must be paired with geometry. |
NOTE
The geometry and project_id fields must either both be provided or both be omitted. You cannot set one without the other.
Response
The response includes the created order with a unique ID, status, computed prices for each line item, and a checkout URL if Stripe payment is required.
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",
"geometry": null,
"project_id": null,
"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 Stripe payment is required (credits insufficient — proceed to the checkout endpoint):
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "IMAGE",
"customer_id": "cus-abc123",
"organisation_id": 42,
"contract_id": 456,
"status": "UNPAID",
"payment_method": "CARD",
"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",
"geometry": null,
"project_id": null,
"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": "https://checkout.stripe.com/c/pay/cs_test_...",
"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 Stripe session is created, 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 POST /orders response will contain a non-empty checkout_redirect_url pointing to a Stripe hosted checkout page, and the order status will be UNPAID. You must then call the checkout endpoint (see Initiate Stripe Checkout below) to obtain a fresh Stripe session URL and complete payment by card.
Credits and card payment cannot be combined on a single order — if credits do not fully cover the order, the full amount is payable via Stripe.
See the Credits user manual for details on credit balances, expiry, and top-ups.
Initiate Stripe Checkout
This section applies when the POST /orders response returned a non-empty checkout_redirect_url, meaning your organisation's credit balance does not cover the full order total. Call this endpoint to obtain a fresh Stripe checkout session URL where the user can complete payment by card.
If credits fully cover the order, the order is already PAID in the create response and this endpoint is not needed. If you call it anyway, it will return an empty checkout_url and leave the order status unchanged. See Payment with Credits above.
Endpoint
GET https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}/checkout
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | UUID | Yes | The order ID returned from the create order response. |
Response
{
"data": {
"checkout_url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
}
The checkout_url field will be:
- Non-empty — redirect the user to this Stripe URL to complete card payment.
- Empty string — the order has been paid with credits; no further action is required.
NOTE
If the order creation response already includes a checkout_redirect_url, you can use that URL directly without calling this endpoint separately. This endpoint is useful when you need to generate a new checkout session for an existing unpaid order.
Examples
Bash
ORDER_ID="550e8400-e29b-41d4-a716-446655440000"
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')
if [ -z "$CHECKOUT_URL" ]; then
echo "Order paid with credits — no Stripe checkout required."
else
echo "Complete payment at: ${CHECKOUT_URL}"
fi
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}/checkout",
)
checkout_url = response.json()["data"]["checkout_url"]
if not checkout_url:
print("Order paid with credits — no Stripe checkout required.")
else:
print(f"Complete payment at: {checkout_url}")
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
After redirecting the user to the Stripe checkout page, 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 after the checkout call 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 →