Metadata-Version: 2.4
Name: first-forecast
Version: 0.1.1
Summary: Official Python SDK for the First Forecast B2B2C API.
Project-URL: Homepage, https://first-forecast.app
Author-email: First Forecast <partners@first-forecast.com>
License: MIT
License-File: LICENSE
Keywords: api,first-forecast,forecast,sdk,stocks
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Provides-Extra: dev
Requires-Dist: mypy>=1.11.2; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.3.3; extra == 'dev'
Requires-Dist: respx>=0.21.1; extra == 'dev'
Requires-Dist: ruff>=0.6.8; extra == 'dev'
Description-Content-Type: text/markdown

# first-forecast

Official Python SDK for the [First Forecast](https://first-forecast.com)
B2B2C API.

```bash
pip install first-forecast
```

## Quick start (sync)

```python
import os

from first_forecast import FirstForecast

ff = FirstForecast(api_key=os.environ["FF_API_KEY"])  # ff_live_... or ff_test_...

result = ff.forecast("AAPL", persona="balanced")
print(result["compliance"]["jurisdiction"])  # 'US'
print(result["forecast"]["horizons"][0]["most_probable"])
```

## Quick start (async)

```python
import asyncio

from first_forecast import AsyncFirstForecast


async def main():
    async with AsyncFirstForecast(api_key=...) as ff:
        result = await ff.forecast("AAPL", jurisdiction="EU")
        print(result["compliance"]["rules_applied"])


asyncio.run(main())
```

## Sandbox

```python
ff = FirstForecast(
    api_key=os.environ["FF_SANDBOX_KEY"],            # ff_test_<...>
    base_url="https://api-sandbox.first-forecast.app",
)
```

## Methods

| Method                          | Endpoint                              |
|---------------------------------|---------------------------------------|
| `ff.forecast(ticker, ...)`      | `GET /v1/forecast/{ticker}`           |
| `ff.multi(tickers, ...)`        | `GET /v1/multi`                       |
| `ff.tickers(...)`               | `GET /v1/tickers`                     |
| `ff.usage()`                    | `GET /v1/usage`                       |

The SSE stream endpoint (`/v1/forecast/{ticker}/stream`) is not
bundled — use [`httpx-sse`](https://pypi.org/project/httpx-sse/)
or `aiohttp` directly.

## Errors

```python
from first_forecast import FirstForecast, FirstForecastError

try:
    ff.forecast("NOTAREAL")
except FirstForecastError as e:
    if e.kind == "auth":         # 401 / 403
        ...
    elif e.kind == "not_found":  # 404
        ...
    elif e.kind == "bad_request":
        ...
    elif e.kind == "rate_limited":
        wait = e.retry_after or 5
        ...
    elif e.kind == "server_error":
        ...
    elif e.kind == "network":    # httpx.HTTPError
        ...
    elif e.kind == "parse":      # server returned non-JSON
        ...
    print(e.status, e.body)
```

## Versioning

Tracks `packages/schemas/openapi.yml` in the
[first-forecast monorepo](https://github.com/first-forecast/first-forecast).
Major-version bumps indicate a breaking change to that contract.

## License

MIT.
