Metadata-Version: 2.5
Name: hypersr
Version: 0.1.0
Summary: Typed Python client for the HyperSR multispectral super-resolution API.
Project-URL: Homepage, https://hypersr.com
Project-URL: Documentation, https://github.com/HyperalisLabs/hypersr/blob/main/packages/sdk-python/README.md
Project-URL: Repository, https://github.com/HyperalisLabs/hypersr
Project-URL: Issues, https://github.com/HyperalisLabs/hypersr/issues
Author: Hyperalis Labs
License-Expression: LicenseRef-Proprietary
Keywords: api-client,geospatial,satellite,sentinel-2,super-resolution
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pydantic<3,>=2.7
Provides-Extra: dev
Requires-Dist: mypy<2,>=1.11; extra == 'dev'
Requires-Dist: pytest-cov<6,>=5; extra == 'dev'
Requires-Dist: pytest<10,>=9.0.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.6; extra == 'dev'
Provides-Extra: rasterio
Requires-Dist: rasterio<2,>=1.3; extra == 'rasterio'
Description-Content-Type: text/markdown

# HyperSR Python SDK

`hypersr` is a typed, synchronous Python client for the HyperSR asynchronous
Sentinel-2 super-resolution API. It requires Python 3.11 or newer.

## Install

```bash
python -m pip install hypersr
# or, in a uv-managed project:
uv add hypersr
```

Set an API key through the environment or a secret manager:

```bash
export HYPERSR_API_KEY="hs_live_..."
export HYPERSR_SCENE_ID="<provider scene identifier>"
export HYPERSR_BBOX='[2.10, 41.30, 2.11, 41.31]'
```

The default endpoint is `https://api.hypersr.com/v1`. Pass `base_url` to use a
local or staging API, for example `HyperSR(api_key=key,
base_url="http://localhost:8000/v1")`.
Replace the example bounding box with `[west, south, east, north]` coordinates
covered by your selected scene. Installing the client does not activate the
hosted service; a reachable API and an account with an API key are required.

## Discover, quote, submit, and poll

The server owns model availability and pricing. Discover enabled models first,
then request a quote for a provider scene and WGS84 bounding box. A quote
contains integer `required_credits`; the client never calculates or submits a
billable amount. Confirmation is an explicit `jobs.submit` call using the
quote ID and an idempotency key.

```python
import json
import os
from uuid import uuid4

from hypersr import HyperSR, HyperSRError

with HyperSR(
    os.environ["HYPERSR_API_KEY"],
    base_url=os.environ.get("HYPERSR_BASE_URL", "https://api.hypersr.com/v1"),
) as client:
    bbox = json.loads(os.environ["HYPERSR_BBOX"])
    models = client.models()
    model = next(item for item in models if item.slug == "hypersr_v1" and item.enabled)
    quote = client.jobs.quote(
        scene_id=os.environ["HYPERSR_SCENE_ID"],
        bbox=bbox,
        model=model.slug,
    )
    print(f"quote {quote.id}: {quote.required_credits} internal units")
    try:
        job = client.jobs.submit(quote_id=quote.id, idempotency_key=f"quickstart-{uuid4()}")
        result = client.jobs.wait(job.id, timeout=1800)
    except HyperSRError as exc:
        print(f"HyperSR request failed: {exc}")
    else:
        print(result.status, result.error_code, result.error_message)
```

`wait` returns all service terminal outcomes: `completed`, `failed`, and
`cancelled`. It raises `hypersr.TimeoutError` when its deadline expires. A
failed or cancelled queued job does not consume the reserved processing
credits. One displayed credit equals **1,000 internal units**; for example,
`client.credits().available / 1000` gives the displayed balance. Credit expiry
is available through `credit_lots` and `next_expiry` on the balance response.

## Download the product bundle

Completed jobs expose four typed artifacts: `reflectance`, `scl`, `cloud_mask`,
and `provenance`. Each has its own signed URL and checksum. The URLs are
short-lived bearer capabilities; do not log or share them.

```python
import os
from pathlib import Path

from hypersr import HyperSR

with HyperSR(
    os.environ["HYPERSR_API_KEY"],
    base_url=os.environ.get("HYPERSR_BASE_URL", "https://api.hypersr.com/v1"),
) as client:
    job = client.jobs.get(os.environ["HYPERSR_JOB_ID"])
    if job.status == "completed":
        output_dir = Path("hypersr-output")
        for role in ("reflectance", "scl", "cloud_mask", "provenance"):
            suffix = ".json" if role == "provenance" else ".tif"
            client.jobs.download_role(job.id, role, output_dir / f"{role}{suffix}")
```

Set `HYPERSR_JOB_ID` to the ID returned by submission. Downloads use a separate
HTTP client without the API key, stream to a temporary file, verify available
size/SHA-256 metadata and replace the destination only after success.

Rasterio is optional. Install `hypersr[rasterio]` to inspect a downloaded
reflectance COG; see `examples/rasterio_metadata.py`.

## Retries, errors, and service limits

Safe reads retry transient HTTP failures. Mutations retry only when an
idempotency key is present and the server operation supports replay; reuse the
same key when retrying a submission. Key creation and saved-area creation are
never automatically retried because their secrets/results cannot be replayed.
`HyperSRError` is the common exception, with typed `APIError` subclasses for
authentication, validation, not-found, conflict, and rate-limit responses.
Retries are bounded (`max_retries=2` by default), and each `wait` call has a
deadline.

The service validates scene identifiers, WGS84 boxes, supported bands, model
availability, quote expiry, area and queue limits. It may reject a well-formed
request when a model or provider scene is unavailable. The initial release is
asynchronous and supports Sentinel-2 Level-2A scenes covered by an enabled
model; a 2.5 m output grid is reconstructed output spacing, not a native 2.5 m
observation. See the repository API guide for the current contract and
`examples/` for runnable scripts.

The client also exposes saved AOIs (`aois`, `get_aoi`, `create_aoi`,
`update_aoi`, `delete_aoi`), notification preferences, account summaries,
server-configured billing packages, and filtered/paginated job history.
Use `client.scenes.search(bbox=bbox, target_date="2026-11-01")` to discover
provider acquisitions before requesting a quote. Search returns a selected
scene plus candidates and does not create a job or reserve credits.
