Metadata-Version: 2.4
Name: ionoflux
Version: 0.1.1
Summary: Official synchronous Python client for the IonoFlux data API
Project-URL: Homepage, https://ionoflux.runvia.app
Project-URL: Repository, https://github.com/hongjunna/ionoflux-python
Project-URL: Documentation, https://github.com/hongjunna/ionoflux-python#readme
Project-URL: Changelog, https://github.com/hongjunna/ionoflux-python/blob/main/CHANGELOG.md
Project-URL: Releases, https://github.com/hongjunna/ionoflux-python/releases
Project-URL: Issues, https://github.com/hongjunna/ionoflux-python/issues
License-Expression: PolyForm-Noncommercial-1.0.0
License-File: LICENSE
License-File: NOTICE
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<0.29,>=0.27
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: mypy<2,>=1.15; extra == 'dev'
Requires-Dist: pytest<10,>=8; extra == 'dev'
Requires-Dist: readme-renderer[md]<45,>=44; extra == 'dev'
Requires-Dist: ruff<1,>=0.11; extra == 'dev'
Requires-Dist: twine<7,>=6; extra == 'dev'
Description-Content-Type: text/markdown

<a href="https://ionoflux.runvia.app"><img src="https://ionoflux.runvia.app/brand/icon-512.png" width="96" height="96" alt="IonoFlux official logo: sun and radio waves on a blue background"></a>

# IonoFlux Python SDK

Official synchronous Python SDK for [IonoFlux](https://ionoflux.runvia.app), providing space-weather, solar and geomagnetic data, alerts and public data metadata. Requires **Python 3.11+**.

```sh
pip install ionoflux
```

[PyPI](https://pypi.org/project/ionoflux/) · [GitHub](https://github.com/hongjunna/ionoflux-python) · [한국어](https://github.com/hongjunna/ionoflux-python/blob/main/README.ko.md) · [Official site](https://ionoflux.runvia.app) · [Releases](https://github.com/hongjunna/ionoflux-python/releases)

## Quickstart

Sign in at https://ionoflux.runvia.app/account and create a **Server** API key. Python runs outside the browser: a Web key can return 403. The current account flow requires a service URL even for Server keys; notebooks/batches without a website need an appropriate service URL under the existing policy. The SDK cannot issue keys or bypass that requirement.

```sh
export IONOFLUX_API_KEY='your-server-key'
```

```python
from ionoflux import Client

with Client() as client:
    current = client.space_weather.current()
    print(current.data)  # Original JSON fields, including nulls and timestamp strings
    print(current.rate_limit.remaining)
```

Explicit `Client(api_key="...")` overrides the environment. No key is required for `sources()` or `data.status()`. Keep keys out of source control, browsers and shared notebook outputs.

```python
from datetime import UTC, datetime
from ionoflux import Client, RateLimitError

with Client(timeout=10.0, max_retries=1) as client:
    try:
        series = client.solar.flux(
            start=datetime(2026, 10, 1, tzinfo=UTC),
            end=datetime(2026, 10, 2, tzinfo=UTC),
            interval="1h",
            limit=100,
        )
        print(series.data["unit"], series.data["attribution"])
        print(series.data["data"])
    except RateLimitError as error:
        print(error.retry_after, error.rate_limit.reset_seconds)
        # Return control to your application; no automatic daily-quota sleep.
```

## Supported calls

All return `APIResponse[T]`: `.data` (JSON dict, or list of dicts for alerts), `.raw_body` (original bytes), `.status_code`, `.headers` (quota/content-type only), `.rate_limit`. Nested JSON values are flexible (`Any`), not runtime-validated domain models; additive server fields survive. Timestamps remain ISO 8601 strings for lossless JSON; request datetimes must be aware and are converted to UTC. No automatic DataFrame conversion.

| Call | Options beyond shared time-series arguments |
|---|---|
| `client.space_weather.current()` | Current indicators and freshness |
| `client.solar.flux(...)` | SFI |
| `client.solar.sunspots(...)` | `source="swpc"` or `"silso"` |
| `client.solar.xray(...)` | `band="long"` or `"short"` |
| `client.solar.wind(...)` | `parameter="speed"`, `"density"`, `"bt"`, `"bz"` |
| `client.geomagnetic.kp(...)` | `source="swpc"` or `"gfz"`, `include_forecast=True` |
| `client.geomagnetic.ap(...)` | Ap |
| `client.statistics(metric, ...)` | `start`, `end`, metric-specific `source`; 10 metrics in contract |
| `client.alerts.list(...)` | `since`, repeatable `category` list, `limit=50` (1..500) |
| `client.alerts.scales()` | R/S/G levels and outlook |
| `client.sources()` | Public provider catalog and collector freshness |
| `client.data.status(dataset=None)` | Public summary or latest records of a dataset |

Shared time-series arguments: `start=None`, `end=None`, `interval="raw"`, `limit=5000` (1..10000). Omitting dates preserves endpoint-specific **server defaults**. The API keeps the newest limited points then returns them ascending. No cursor or automatic full-history download. `1mo` is a fixed **30-day** bucket. Requests with explicit start and end are limited to 3660 days; query allowance does not imply historical availability. Consult `data.status()` for retention and actual coverage.

## Errors, networking and security

`AuthenticationError` (401), `PermissionDeniedError` (403), `NotFoundError` (404), `ValidationError` (422), `RateLimitError` (429), `ServerError` (5xx) and `RedirectError` (3xx) extend `APIError`. Exceptions carry `status_code`, redacted textual `detail`, `rate_limit` and `retry_after`; no HTTP request object. Other failures use `TransportError`, `ResponseError` or `ConfigurationError`. Locally invalid method arguments raise `ValueError`.

Only GET is implemented. At most 0..3 retries (default 1) apply only to connection failures/timeouts, read failures/timeouts, remote protocol errors and HTTP 502/503/504; 401/403/404/422/429/500, response decoding errors, local protocol/configuration errors and pool timeouts are never retried. A 502/503/504 response with Retry-After or Remaining=0 is returned immediately as ServerError; the SDK does not ignore a server wait instruction. Backoff is 0.25, 0.5, 1 seconds (maximum aggregate sleep 1.75 seconds). Retry-After is exposed, never used to trigger a long wait. HTTPX `timeout` is a finite positive per-operation timeout, **not a total wall-clock deadline**. Every retry may count against the API quota. `X-RateLimit-Reset` is seconds remaining until UTC midnight, not an epoch timestamp. `Retry-After` remains its original string; unknown/malformed numeric quota headers (including more than 20 digits) become `None`.

The default API root is `https://ionoflux.runvia.app/v1`; a custom `base_url` must be HTTPS, end in `/v1`, and contain no credentials, query or fragment. Redirects are never followed. Environment proxies and netrc credentials are disabled (`trust_env=False`). Session/transport lifetime is owned by `Client`; call `close()` or use `with`. The SDK does not log credentials, send them to public metadata routes or put them in URLs. Custom HTTP transports and application-level HTTP debug logging are trusted caller code; do not log raw request headers. Raw success bodies can contain arbitrary server data: treat them as sensitive application data when sharing.

## Documentation and verification

[API contract and limits](https://github.com/hongjunna/ionoflux-python/blob/main/docs/api-contract.md) · [Development plan](https://github.com/hongjunna/ionoflux-python/blob/main/docs/development-plan.md) · [Changelog](https://github.com/hongjunna/ionoflux-python/blob/main/CHANGELOG.md)

This synchronous SDK does **not** provide async clients, pandas/DataFrame conversion, TEC/MUF, propagation, stations or WSPR/PSK queries. Those are [future work](https://github.com/hongjunna/ionoflux-python/issues/2).

v0.1.0 was released on PyPI on 2026-10-20. Its [release record](https://github.com/hongjunna/ionoflux-python/releases/tag/python-v0.1.0) preserves the original artifacts and verification evidence. A bounded nine-request Server-key acceptance passed for current/SFI/Kp/statistics/alerts/scales/public metadata; actual 403/429 responses and every provider/endpoint permutation were not exercised. See [acceptance and limits](https://github.com/hongjunna/ionoflux-python/blob/main/docs/release-review.md). This documentation patch does not claim new live API acceptance.

Development tests block network connections and use HTTPX MockTransport. CI checks Linux Python 3.11–3.15, Windows/macOS 3.14, minimum HTTPX 0.27.0, Ruff, mypy, README rendering, wheel/sdist builds and separate clean installations. Publishing uses protected GitHub environments and Trusted Publishing with manual approval; normal PR CI does not publish. Development setup and validation commands are in the [development plan](https://github.com/hongjunna/ionoflux-python/blob/main/docs/development-plan.md).

## SDK code license, API terms and data rights

The SDK code is licensed under **[PolyForm Noncommercial License 1.0.0](https://github.com/hongjunna/ionoflux-python/blob/main/LICENSE)**
(SPDX: `PolyForm-Noncommercial-1.0.0`). The standard text is unmodified. It permits
noncommercial use, including personal/hobby use, and its educational, public-research
and other listed institutional permissions apply in full, regardless of funding or
resulting funding obligations. Do not treat every company-funded university activity
as excluded from the standard code license.

Commercial SDK uses outside those permissions require a separate written license
from the authorized rights holder. For inquiries, contact the operator through the
[official IonoFlux service](https://ionoflux.runvia.app). An inquiry, payment or public
issue is not itself written authorization; do not post keys or confidential contract
details publicly. No unverified company name or legal rights-holder name is asserted.

When redistributing any SDK copy, preserve the license terms (or their official URL)
and the plain-text Required Notice in [NOTICE](https://github.com/hongjunna/ionoflux-python/blob/main/NOTICE):

```text
Required Notice: IonoFlux (https://ionoflux.runvia.app)
```

API access and attribution of API results are managed separately. The
[proposed API terms](https://github.com/hongjunna/ionoflux-python/blob/main/docs/api-terms-proposal.ko.md) remain **unapproved and not in effect**;
adopting the SDK license does not implement those proposed UI/publication obligations,
change current site terms or authorize uploads. The SDK's redistribution notice is
not an automatic requirement to display a credit on every website/paper.

Provider data licenses and attribution remain independent. An SDK commercial license
or API permission cannot grant third-party rights IonoFlux does not hold. Preserve
source/attribution and inspect provider-specific restrictions. This is not an
OSI open-source license; source visibility does not remove the noncommercial terms.

[Adopted policy and rights-holder review](https://github.com/hongjunna/ionoflux-python/blob/main/docs/licensing-review.ko.md) ·
[Bilingual usage notice](https://github.com/hongjunna/ionoflux-python/blob/main/docs/readme-usage-draft.md) ·
[Use cases](https://github.com/hongjunna/ionoflux-python/blob/main/docs/use-cases.ko.md) · [Attribution examples](https://github.com/hongjunna/ionoflux-python/blob/main/docs/attribution-examples.md) ·
[API terms pre-effective review checklist](https://github.com/hongjunna/ionoflux-python/blob/main/docs/api-terms-preflight.ko.md)
