Metadata-Version: 2.4
Name: flysafe-api
Version: 0.2.0
Summary: FlySafe airspace risk API client (Python)
Author-email: FlySafe <hello@flysafe.zone>
License: MIT
Project-URL: Homepage, https://flysafe.zone
Project-URL: Documentation, https://flysafe.zone/docs
Keywords: aviation,airspace,risk,notam,flightsafety
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# flysafe-api (Python)

Lightweight Python client for the [FlySafe](https://flysafe.zone) airspace
risk API. Synchronous, ~200 lines, only depends on `requests`.

## Install

```bash
pip install flysafe-api
```

## Quickstart

```python
from flysafe import Client

fs = Client(api_key="...")

# Score a route
risk = fs.route_risk("LHR", "DXB")
print(risk["score"], risk["risk_level"])
# 54 high

# Engine v2 — adds reroute analysis + adjusted_score
fs2 = Client(api_key="...", engine_version="v2")
r = fs2.route_risk("LHR", "DXB", carrier="IL")
print(r["adjusted_score"])
print(r["reroute_analysis"]["best_alternative"]["path"])
# 53
# ['LCCC', 'OJAC', 'OEJD', 'OTBD', 'OMAE']

# Self-serve introspection
print(fs.usage()["daily_quota"])
print(fs.queries(status="429", limit=10))
```

## Webhooks

Verify incoming webhook signatures:

```python
from flysafe import verify_webhook

@app.post("/flysafe-hooks")
def receive():
    if not verify_webhook(SECRET, request.get_data(), request.headers["X-FlySafe-Signature"]):
        return "", 401
    event = request.headers["X-FlySafe-Event"]
    payload = request.get_json()
    # ...
```

Register a webhook:

```python
created = fs.create_webhook(
    url="https://hooks.example.com/flysafe",
    events=["score.changed", "score.critical", "webhook.test"],
    description="Production OCC dashboard",
)
SECRET = created["signing_secret"]   # save it — shown only once

# Test it end-to-end
fs.fire_webhook_test(created["id"])
```

## Errors

```python
from flysafe import Client, FlySafeError, RateLimitError

try:
    fs.route_risk("LHR", "DXB")
except RateLimitError as e:
    print("retry after", e.retry_after, "seconds")
except FlySafeError as e:
    print("api error:", e.status, e.body)
```

## Reference

| Method                                  | Endpoint                            |
|-----------------------------------------|-------------------------------------|
| `route_risk(origin, destination, ...)`  | `/v1/route/risk`                    |
| `route_risk(..., detailed=True)`        | `/v1/route/risk/detailed`           |
| `firs()`                                | `/v1/firs`                          |
| `signals(limit=50)`                     | `/v1/signals`                       |
| `health()`                              | `/v1/health`                        |
| `usage()`                               | `/v1/me/usage`                      |
| `queries(...)`                          | `/v1/me/queries`                    |
| `list_webhooks()`                       | `GET /v1/me/webhooks`               |
| `create_webhook(url, events, ...)`      | `POST /v1/me/webhooks`              |
| `delete_webhook(id)`                    | `DELETE /v1/me/webhooks/:id`        |
| `fire_webhook_test(id)`                 | `POST /v1/me/webhooks/:id/test`     |
| `webhook_deliveries(id)`                | `GET /v1/me/webhooks/:id/deliveries`|

Full API documentation: https://flysafe.zone/docs

## License

MIT
