Python SDK
There are two Python clients, both generated from — or tracking — the same operation registry, so neither can drift from the live API:
geopera— a friendly, hand-curated client with high-level namespaces (client.catalog,client.orders,client.processing,client.billing). Start here for application code.geopera_kernel— a fully generated, low-level client with one typed method per operation. Use it when you want the complete operation surface, exactly typed, with no curation.
Install
pip install geopera-pyAuthenticate
import geopera
# Machine-to-machine (servers, pipelines) — recommended
client = geopera.Client.from_api_key("gp_live_...")
# Or via your Geopera login (interactive scripts)
client = geopera.Client.from_password("[email protected]", "password")from_api_key exchanges the key for short-lived JWTs and refreshes them for you, so you
don’t manage token lifetimes. from_client_credentials is also available for the OIDC
client-credentials grant.
Search the catalog
results = client.catalog.search(
host="earthsearch-aws",
collections=["sentinel-2-l2a"],
bbox=[151.0, -34.0, 152.0, -33.0],
datetime_range="2024-01-01T00:00:00Z/2024-12-31T23:59:59Z",
cloud_cover_lte=20,
limit=25,
)
for feature in results.features:
print(feature.id, feature.properties["datetime"])Preview a price and place an order
# Server-authoritative price preview (a read — nothing is charged)
quote = client.orders.estimate(
data_product="phr",
feature_collection=fc, # a GeoJSON FeatureCollection over your AOI
)
print(quote["total_credits"], quote["total_aud"])
# Place the order
order = client.orders.create(
workspace_id="your-project-id",
data_product="phr",
display_name="Sydney harbour archive",
feature_collection=fc,
params={"id": "scene-abc"},
tags=["production"],
)
# Track to a terminal state
fetched = client.orders.get(order["results"][0]["id"])
print(fetched.status)Other order methods: client.orders.list(...), client.orders.update_tags(id, tags), client.orders.cancel(id), and client.orders.schema(data_product_id) to introspect a
product’s parameters.
Processing
# Discover available processes and their cost
processes = client.processing.list_processes()
cost = client.processing.cost(process_id, inputs={...})
# Run one
job = client.processing.execute(
process_id,
workspace_id="your-project-id",
inputs={"source_item_id": "it_3a9c...", "...": "..."},
)
# Track it
status = client.processing.get_job(job["id"])Billing
balance = client.billing.balance()
print(balance.credits)
# Attach a card via Stripe SetupIntent, then top up
intent = client.billing.setup_intent() # confirm client-side with Stripe.js
result = client.billing.topup(credits=50000) # charges the default card
# Automate it
client.billing.set_auto_topup(
enabled=True,
threshold_credits=5000,
topup_amount_credits=50000,
)If a top-up needs 3-D Secure, topup surfaces the client_secret to complete the
challenge — see the 3-D Secure retry.
Webhooks (event subscriptions)
Subscribe to platform events and stop polling. Each delivery is an HTTP POST signed
with an HMAC-SHA256 X-Geopera-Signature header so you can verify it came from
Geopera. Discover the full event catalogue with event_types().
sub = client.webhooks.subscribe(
url="https://your-app.example.com/hooks/geopera",
events=["order.fulfilled", "job.completed", "credits.low_balance"],
)
client.webhooks.list()
client.webhooks.event_types() # discover available event typesOn your receiver, verify the X-Geopera-Signature header against the subscription
secret before trusting a delivery:
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")Delivery is durable and at-least-once with retry/backoff, so make your handler
idempotent (dedupe on X-Geopera-Event-ID). See the Webhooks guide for the full event catalogue, the
delivery headers, and delivery semantics.
The generated low-level client
When you want the complete, exactly-typed surface — every operation, every input/output
model — use geopera_kernel. It’s a standard openapi-python-client package: one
module per operation plus a model for each input and output.
from geopera_kernel import AuthenticatedClient
from geopera_kernel.api.kernel_ops import items_search_org
from geopera_kernel.models import OrgItemSearchInput
client = AuthenticatedClient(base_url="https://api.geopera.com", token="<jwt>")
resp = items_search_org.sync_detailed(
client=client,
body=OrgItemSearchInput(limit=5),
)
print(resp.parsed)Because it’s generated from the kernel’s reflected OpenAPI, adding an operation to the platform adds a typed method here on the next regeneration — no hand-maintained types.
Errors
Both clients raise on non-2xx responses, surfacing the application/problem+json body (status, title, detail).
Handle 402 for payment problems and 409/422 for conflicts and validation as
described in Errors.