Purchasing Catalog Images

This page describes how to create an order for catalog images, complete the payment 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

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.
licensesarrayYesArray of licenses the user accepts (see below).

Order Line Item fields:

FieldTypeRequiredDescription
collectionstringYesThe STAC collection ID.
itemstringYesThe STAC item ID.
levelstringYesThe processing level (e.g. L2A).
geometryobjectNoA GeoJSON geometry object for sub-area purchases. Must be paired with project_id.
project_idstringNoThe 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.

License fields:

FieldTypeRequiredDescription
license_linkstringYesURL to the full license text.
license_namestringYesThe name of the license.
license_versionstringYesThe version of the license.
acceptedbooleanYesMust be true to proceed with the order.

Response

The response includes the created order with a unique ID, status, computed prices for each line item, and a checkout URL if payment is required.

{
  "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"
        },
        "licenses": [
          {
            "license_link": "https://example.com/license/eula-v1",
            "license_name": "DataCosmos EULA",
            "license_version": "1.0",
            "accepted": true
          }
        ],
        "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,
  "licenses": [
    {
      "license_link": "https://example.com/license/eula-v1",
      "license_name": "DataCosmos EULA",
      "license_version": "1.0",
      "accepted": true
    }
  ]
}'

  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,
    "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()
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,
    "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()
for item in order["data"]["order_line_items"]:
    print(f"Item: {item['item']} — Price: {item['price']['final']} {item['price']['currency']}")

Initiate Checkout

After creating an order, you need to complete payment. This endpoint creates a Stripe checkout session and returns a URL where the user can enter payment details.

Endpoint

GET https://app.open-cosmos.com/api/data/v0/order/orders/{order_id}/checkout

Path Parameters

ParameterTypeRequiredDescription
order_idUUIDYesThe order ID returned from the create order response.

Response

{
  "data": {
    "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_..."
  }
}

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"

curl --request GET "https://app.open-cosmos.com/api/data/v0/order/orders/${ORDER_ID}/checkout" \
--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}/checkout",
)

checkout_data = response.json()
checkout_url = checkout_data["data"]["checkout_url"]
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

ParameterTypeRequiredDescription
order_idUUIDYesThe ID of the order to retrieve.

Query Parameters

ParameterTypeRequiredDescription
expandstringNoComma-separated list of fields to expand. Supported: credits_used.

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:

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