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

ParameterTypeRequiredDescription
redirect_hoststringNoOverride the default redirect URL after checkout completion.

Request Body

FieldTypeRequiredDescription
typestringYesMust be "IMAGE" for catalog purchases.
dataobjectYesContains the order_line_items array.
data.order_line_itemsarrayYesArray of items to purchase (see below).
organisationintegerYesYour organisation's numeric ID.
contract_idintegerYesThe contract ID for this purchase. See how to retrieve your contract ID.

Order Line Item fields:

FieldTypeRequiredDescription
collectionstringYesThe STAC collection ID.
itemstringYesThe STAC item ID.
levelstringYesThe 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

ParameterTypeRequiredDescription
order_idUUIDYesThe 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

ParameterTypeRequiredDescription
order_idUUID[]NoOne 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

ParameterTypeRequiredDescription
order_idUUIDYesThe ID of the order to update.

Request Body

All fields are optional. Only include the fields you want to update.

FieldTypeDescription
statusstringNew status: UNPAID, PAID, or CANCELLED.
payment_methodstringNew 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 StatusTypeDescription
400invalid_inputThe request body or parameters are invalid.
401unauthorizedMissing or invalid bearer token.
403forbiddenYou do not have permission to access this resource.
404not_foundThe specified order or item was not found.
500internal_errorAn unexpected server error occurred.

Where to Next

Pricing API | API Reference