Python

Python SDK

Install, configure, and authenticate the SateAIs Python client.

The SateAIs Python SDK (sateais) is a typed client for the SateAIs API. It resolves credentials automatically, exposes one method per detection type, and includes a sateais command-line tool.

Packagesateais (PyPI)
Python≥ 3.10
Dependencieshttpx

Installation

pip install sateais

Authentication

Create an API key in the SateAIs API Console (see Authentication).

Get your free API keyYou get 500 free API credits every month during the beta. No credit card required.

The client resolves it from the first available source, in order:

  1. The api_key argument to Client(...).
  2. The SATEAIS_API_KEY environment variable.
  3. The credentials file at ~/.sateais/credentials (written by sateais login).
from sateais import Client

# 1. Explicit argument
client = Client(api_key="sk_live_xxxxx")

# 2. From SATEAIS_API_KEY (recommended)
client = Client()

If no key can be resolved, the constructor raises CredentialsNotFoundError.

Keep your key secret

Never hard-code sk_live_ keys in source control. Prefer the SATEAIS_API_KEY environment variable or sateais login.

Creating a client

from sateais import Client

client = Client(
    api_key=None,        # falls back to env / credentials file
    base_url=None,       # defaults to https://api.spcsft.com/api/v1
    timeout=30.0,        # per-request timeout in seconds
)

The base URL falls back to the SATEAIS_BASE_URL environment variable, then to the production endpoint.

Releasing resources

Client holds an HTTP connection pool. Use it as a context manager, or call close() when you are done:

with Client() as client:
    job = client.analyze.ship(scene_id="S1A_IW_GRDH_...")
    result = client.jobs.wait(job.job_id)

# or manually
client = Client()
try:
    ...
finally:
    client.close()

Your first detection

from sateais import Client

client = Client()

# Submit a job
job = client.analyze.ship(scene_id="S1A_IW_GRDH_...")
print(job.job_id, job.status)  # -> "...", JobStatus.PENDING

# Poll until completion and fetch the GeoJSON
result = client.jobs.wait(job.job_id, poll_interval=30, on_poll=lambda j: print(j.status))
print(len(result["features"]), "ships detected")

Handling errors

All SDK exceptions inherit from SateAIsError. API responses map to typed subclasses that mirror the API error codes:

from sateais import Client, RateLimitError, JobFailedError, InsufficientCreditsError

client = Client()

try:
    job = client.analyze.timeseries(
        polygon="POLYGON((...))",
        date_start="2026-01-01",
        date_end="2026-05-01",
    )
    result = client.jobs.wait(job.job_id, timeout=3600)
except InsufficientCreditsError:
    print("Top up credits in the Console")
except RateLimitError:
    print("Rate limited — back off and retry")
except JobFailedError as err:
    print("Job failed:", err.job.error_code, err.job.error_message)

See the Reference for the full exception hierarchy.

Command-line interface

Installing the package also provides a sateais CLI for quick, scriptable runs:

# Store your API key in ~/.sateais/credentials (prompts if --api-key is omitted)
sateais login --api-key sk_live_xxxxx

# Submit a job, wait for it, and save the result
sateais analyze ship --scene-id S1A_IW_GRDH_... --wait -o ships.geojson

# Polygon-period analyses
sateais analyze timeseries \
  --polygon "POLYGON((139.7 35.6, 139.8 35.6, 139.8 35.7, 139.7 35.7, 139.7 35.6))" \
  --date-start 2026-01-01 --date-end 2026-05-01 --wait -o result.geojson

# Inspect or fetch jobs
sateais jobs status <job_id>
sateais jobs result <job_id> -o result.geojson
sateais jobs wait <job_id> --poll-interval 30 -o result.geojson

# Decode a Sentinel-1 scene ID locally (no API call)
sateais scene S1A_IW_GRDH_...

Every analyze subcommand accepts --satellite-id, --wait, --poll-interval, --timeout, and -o/--output. ship and oilslick additionally take --scene-id, --polygon, --date, --date-direction, and --orbit-direction; the polygon-period types (newbuilding, disappearbuilding, timeseries) take --polygon, --date-start, and --date-end.

The polygon-period subcommands have no --orbit-direction flag. To filter by orbit direction from the CLI, pass the full request body with --json (a JSON string, @file.json, or - for stdin).

Next steps

On this page