Metadata-Version: 2.4
Name: sibfly
Version: 0.1.0
Summary: Zero-dependency client for the SibFly ground-motion API (satellite-measured land subsidence/uplift, mm/yr, for any US address)
Author-email: SibFly <contact@sibfly.com>
License: MIT
Project-URL: Homepage, https://sibfly.com
Project-URL: Documentation, https://sibfly.com/llms.txt
Project-URL: API Reference, https://sibfly.com/openapi.json
Keywords: insar,subsidence,ground-motion,geospatial,nasa,opera,sentinel-1
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# sibfly

Zero-dependency Python client for [SibFly](https://sibfly.com) — satellite-measured
ground motion (sinking/uplift, mm/yr and in/yr) for any US address, from NASA
OPERA Sentinel-1 InSAR. Flat $0.40 per covered report; misses are free.

Pure stdlib (`urllib`), Python >= 3.8, no dependencies.

```bash
pip install sibfly
```

## Quickstart

```python
from sibfly import SibFly, InsufficientCredits

client = SibFly.register("agent@example.com")          # self-onboard: key + free credits
try:
    r = client.motion(address="425 Fremont St, Las Vegas, NV")
    print(r["velocity_vertical_mm_yr"], r["assessment"])
except InsufficientCredits as e:
    print("top up at:", e.top_up_url)                   # self-refill URL from the 402
```

Already have a key? `SibFly(api_key="sf_...")` or set `SIBFLY_API_KEY` in the env.

## Surface

| Method | Endpoint | Billed |
|---|---|---|
| `SibFly.register(email)` | `POST /api/v1/autonomous/register` — returns a ready client | free |
| `client.motion(address=... / lat=..., lon=..., **gates)` | `GET /api/v1/motion` | $0.40 (misses free) |
| `client.batch(items)` | `POST /api/v1/motion/batch` (max 1000; only covered rows billed) | per covered row |
| `client.timeseries(...)` | `GET /api/v1/timeseries` | yes |
| `client.coverage(...)` | `GET /api/v1/coverage` | free |
| `client.geocode(address)` | `GET /api/v1/geocode` | free |
| `client.balance()` / `client.usage()` | `GET /api/v1/balance` / `/usage` | free |

Gates (free-miss guards) pass straight through: `motion(address=..., dry_run=1)`,
`max_age_days=90`, `min_confidence=0.8`, `include="timeseries"`, `brief=1`, ...

## Built in

- **Auto-retry** — 3x exponential backoff on 429/5xx, honors `Retry-After`.
- **Idempotency** — a UUID `Idempotency-Key` is auto-attached to billed calls, so a
  retried request is never double-charged. Pass `idempotency_key="..."` to control it.
- **Typed errors** — `AuthError` (401), `InsufficientCredits` (402, carries
  `.top_up_url` / `.buy_credits_url` / `.suggested_top_up_usd`), `SibFlyError` base
  (`.status`, `.code`, `.request_id`, `.body`).

Full API contract: https://sibfly.com/llms.txt · MIT license.
