Start here.
Ship in an afternoon
Quickstart
Install the client, set a key, ask for a bounding box. Three lines and you have a tile on disk.
# install
$ pip install orbit-imagery
# your first tile
$ export ORBIT_KEY="sk_live_..."
$ orbit tiles get --bbox 4.71,52.30,4.98,52.42 --newest
$ pip install orbit-imagery
# your first tile
$ export ORBIT_KEY="sk_live_..."
$ orbit tiles get --bbox 4.71,52.30,4.98,52.42 --newest
Authentication
Keys are scoped to a project and a region. A key issued in the EU cannot read tiles stored in Singapore — that is deliberate.
import orbit
client = orbit.Client(api_key="sk_live_...", region="eu-central")
client = orbit.Client(api_key="sk_live_...", region="eu-central")
Fetching tiles
A request is a bounding box, a time window and a cloud ceiling. Everything else has a sane default.
scenes = client.tiles.search(
bbox=[4.71, 52.30, 4.98, 52.42],
since="2026-06-01",
max_cloud=0.1,
sensor="optical",
)
for s in scenes:
s.download("./tiles") # cloud-optimised GeoTIFF
bbox=[4.71, 52.30, 4.98, 52.42],
since="2026-06-01",
max_cloud=0.1,
sensor="optical",
)
for s in scenes:
s.download("./tiles") # cloud-optimised GeoTIFF
Archive queries
The archive answers to the same fields as today's pass. No per-year branches in your code.
history = client.tiles.search(
bbox=field.bounds,
since="2005-01-01",
cadence="monthly",
)
# 252 scenes, one schema
bbox=field.bounds,
since="2005-01-01",
cadence="monthly",
)
# 252 scenes, one schema
Webhooks
Rather than polling, register a bounding box and we call you when a pass that matches it lands.
client.watch.create(
bbox=field.bounds,
max_cloud=0.2,
url="https://terravia.example/hooks/orbit",
)
bbox=field.bounds,
max_cloud=0.2,
url="https://terravia.example/hooks/orbit",
)
Rate limits
Sixty search calls a minute on Free, six hundred on Scale. Downloads are not rate limited — only counted.
Every response carries X-Orbit-Remaining and X-Orbit-Reset. Back off on 429 and the client library will do it for you.