Ordering archive imagery
An archive order buys imagery that already exists in a provider’s catalog. The flow is three operations: search the catalog, estimate the price, place the order. Pricing is always computed by the backend over the area of interest — the client never decides the price.
| Step | Operation | Side-effect | Scope |
|---|---|---|---|
| Find captures | catalog.search | read | catalog:read |
| Preview price | orders.archive.estimate | read | orders:read |
| Place order | orders.archive.place | spend | orders:write |
| Track order | orders.get / orders.list | read | orders:read |
| Cancel | orders.cancel | spend | orders:write |
1. Search the catalog
catalog.search queries a host’s catalog with STAC-style filters and enriches
commercial results with price information.
curl -s -X POST https://api.geopera.com/v1/op/catalog.search \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"host_name": "the-host",
"collections": ["..."],
"bbox": [151.10, -33.92, 151.30, -33.78],
"datetime": "2024-01-01T00:00:00Z/2024-06-30T23:59:59Z",
"query": { "eo:cloud_cover": { "lte": 20 } },
"limit": 25
}'Key inputs: host_name (required), one of collections / ids, a spatial filter
(bbox or intersects), datetime (an instant or a start/end range), query for
property filters, and limit. Paginate with the next token returned in the response.
For very large result sets use catalog.search_stream, an NDJSON variant.
Each returned feature is a capture you can order. Note its id and geometry — those
are what you pass to the next steps.
2. Preview the price
orders.archive.estimate is a read that returns the exact, server-authoritative
price for a cart of captures. Nothing is persisted and no money moves.
curl -s -X POST https://api.geopera.com/v1/op/orders.archive.estimate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"captures": [
{ "id": "scene-abc", "geometry": { "type": "Polygon", "coordinates": [ ... ] } },
{ "id": "scene-def", "geometry": { "type": "Polygon", "coordinates": [ ... ] } }
],
"splitByDate": false
}'{
"groups": [
{ "captures": ["scene-abc", "scene-def"], "aoi_km2": 12.4, "credits": 4200, "aud": 42.00 }
],
"errors": [],
"total_aud": 42.00,
"total_credits": 4200
}total_creditsis an integer credit count (100 credits = A$1).total_audis the dollar equivalent.groupsbreaks the cart into priced groups (one per AOI/date depending onsplitByDate).errorslists any captures that couldn’t be priced (e.g. an unsupported product), so you can fix the cart before placing.
Set splitByDate: true to price each acquisition date as its own group.
3. Place the order
orders.archive.place reserves credits and creates the order. It’s an external_spend operation, so:
- it requires the
orders:writescope (an API key cannot place archive orders — this is a deliberate guard on the money path; use a user or delegated principal), and - it accepts an
Idempotency-Keyheader so a retry after a dropped connection never places two orders.
curl -s -X POST https://api.geopera.com/v1/op/orders.archive.place \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9d1f...-unique-per-order" \
-d '{
"projectId": "your-project-id",
"captures": [
{ "id": "scene-abc", "geometry": { "type": "Polygon", "coordinates": [ ... ] } }
],
"licenseType": "standard",
"splitByDate": false
}'{
"id": "f2b1c0de-...",
"status": "processing",
"orderType": "archive",
"billingMode": "credit",
"currency": "AUD",
"totalAud": 42.00,
"totalCredits": 4200,
"groups": [ { "...": "the priced groups, as ordered" } ]
}Inputs: captures (required, non-empty), projectId (the owning workspace), licenseType, and splitByDate. The response echoes the final server price and the
new order’s id and status.
Billing modes
billingMode tells you how the order was paid:
credit— credits were reserved from the org’s prepaid balance.card— a free org without a prepaid wallet authorized its card at checkout (a hold that is captured on delivery and voided if the order fails).enterprise— an invoiced enterprise org; the amount accrues to its monthly invoice.
Payment errors
If the order can’t be paid, you get 402 Payment Required:
- Insufficient credits — top up or enable auto top-up.
- No / declined card — attach a payment method.
- 3-D Secure required — the
402body carries aclient_secret; complete the bank challenge, then retry with the sameIdempotency-Key.
4. Track and cancel
Poll orders.get (or list with orders.list) until the order is terminal:
curl -s https://api.geopera.com/v1/op/orders.get \
-H "Authorization: Bearer $TOKEN" \
-G --data-urlencode 'id=f2b1c0de-...'When the order is delivered, its imagery lands in your project as STAC items, each carrying a provenance edge back to this order (see Provenance & lineage).
To cancel, call orders.cancel — it’s policy-gated (only cancellable states) and
refunds or voids the reservation:
curl -s -X POST https://api.geopera.com/v1/op/orders.cancel \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "id": "f2b1c0de-..." }'Resource-style route
The same capability is exposed on the familiar POST /v2/orders route for clients that
follow STAC/UP42 conventions. It runs the identical operation underneath, with the same
scope, pricing, idempotency, and provenance.