Metadata-Version: 2.5
Name: bev-cera
Version: 0.1.0a1
Summary: Python SDK and CLI for the External Weather API.
Author: BirdsEyeView Data Science Team
Maintainer-email: BirdsEyeView Data Science Team <albert.dow@birdseyeview.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: api,insurance,risk,sdk,weather
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
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: platformdirs<5,>=4
Requires-Dist: pydantic<3,>=2.10
Requires-Dist: rich<16,>=15
Requires-Dist: typer<1,>=0.25
Description-Content-Type: text/markdown

# bev-cera

Python SDK and CLI for the external BirdsEyeView CERA API.

The SDK talks to BirdsEyeView's CERA APIs over HTTPS and authenticates with an
API key in the `X-API-Key` header. Credentials can be obtained by contacting
BirdsEyeView directly.

## Installation

Requires Python 3.11 or later.

```bash
pip install "bev-cera==0.1.0a1"
```

This installs both the Python SDK and the bev-cera command-line interface.

## Authentication

Set your API key in the environment:

```bash
export BEV_CERA_API_KEY="your-api-key"
```

To override the production API URL for staging or testing:

```bash
export BEV_CERA_BASE_URL="https://your-api-host"
```

Custom base URLs must use HTTPS. `http://localhost` with an optional port is
allowed for local testing; other HTTP URLs, credentials, queries, and fragments
are rejected.

Never commit API keys to source control.

## Example usage

### In-Depth v2

Use `calculate()` for both non-cumulative and cumulative perils. Events use
`EventWithCoords`, so each event must provide a non-empty location or both
latitude and longitude. A location may also be provided with either coordinate.
When dates are omitted, the API defaults `start_date` to today and `end_date`
to one calendar year after `start_date`, minus one day.

```python
from bev_cera import Client, EventWithCoords

events = [
    EventWithCoords(
        latitude=51.5,
        longitude=-0.1,
        start_date="2026-01-01",
        end_date="2026-01-01",
    )
]

with Client() as client:
    result = client.in_depth.calculate(perils=["Rain", "Hail"], events=events)
    print(result.results)
```

For cumulative rain or snowfall, supply a window of 0 to 7 days:

```python
with Client() as client:
    result = client.in_depth.calculate(
        perils=["CumulativeRain"], events=events, window_days=3
    )
```

### Lite scores

```python
from bev_cera import Client

with Client() as client:
    score = client.lite.score(latitude=51.5, longitude=-0.1)
    print(score.scores.root)
```

Lite scores default to the `return_period` calculation method. Pass
`calculation_method="globally_relative"` only when that explicit mode is required.

### Async

```python
import asyncio

from bev_cera import AsyncClient


async def main() -> None:
    async with AsyncClient() as client:
        perils = await client.perils.list()
        print(perils.daily)


asyncio.run(main())
```

### In-Depth Daily

```python
from bev_cera import Client, EventWithCoords

events = [
    EventWithCoords(
        location="London", start_date="2026-01-01", end_date="2026-01-01"
    )
]

with Client() as client:
    result = client.in_depth.daily(perils=["Rain"], events=events)
    print(result.results)
```

### Batch

```python
from bev_cera import Client

with Client() as client:
    uploaded = client.batch.upload("events.csv")
    submitted = client.batch.submit(file_id=uploaded.file_id, perils=["Rain"])
    status = client.batch.status(submitted.job_id)
    print(status.progress_percentage, status.processed_rows, status.total_rows)
    result = client.batch.wait_for(submitted.job_id)
    print(result)
```

`batch.submit()` generates an idempotency key automatically and reuses it for
transport retries. Supply `idempotency_key=` when the same logical submission
may be retried by your own application. Use `client.batch.cancel(job_id)` to
cancel a pending or running job.

Retryable `GET` requests and idempotent requests retry transport errors and
`5xx` responses with exponential back-off. `429` responses are surfaced to the
caller as `RateLimitError`.

Status and completion responses expose `attempt`, `processed_rows`,
`total_rows`, and `progress_percentage`. Progress is per processing attempt and
reaches 100 only after the result artefacts are committed. Polling returns typed
status models; completed responses contain pre-signed result, report, and
workbook URLs rather than downloaded or parsed files.

The SDK performs an early client-side check of the configured 100,000-row CSV
limit. The server remains authoritative. Large jobs can take several hours, so
`batch.wait_for()` defaults to a 4 hour timeout.
Date columns are optional. Missing `start_date` values default to the job
submission date, and missing `end_date` values default to `start_date` plus
one calendar year minus one day. A CSV containing only a `location` column is
valid.

### Lite Batch

```python
from bev_cera import Client

with Client() as client:
    uploaded = client.lite_batch.upload("events.csv")
    submitted = client.lite_batch.submit(
        file_id=uploaded.file_id,
        calculation_method="return_period",
        flood_plus=True,
    )
    result = client.lite_batch.wait_for(submitted.job_id)
    print(result)
```

`calculation_method` accepts `return_period` (the default) or
`globally_relative`. The CLI exposes the same workflow under
`bev-cera lite-batch upload|submit|status|cancel|run`.

### Error Handling

```python
from bev_cera import AuthenticationError, Client, ValidationError

try:
    with Client() as client:
        client.perils.list()
except AuthenticationError:
    print("Check your API key")
except ValidationError as exc:
    print(exc.message)
```

## CLI

Configure the CLI once:

```bash
bev-cera configure
```

Examples:

```bash
bev-cera perils
bev-cera lite --lat 51.5 --lon -0.1
bev-cera in-depth calculate --events events.json --perils Rain,Hail
bev-cera in-depth calculate --events events.json --perils CumulativeRain --window-days 3
bev-cera in-depth daily --events events.json --perils Rain,MaxWindSpeed
bev-cera batch upload events.csv
bev-cera batch run events.csv --perils Rain --no-wait
```

## Local testing from code

To test the SDK without it being on PyPi you can follow these steps:

Get the repo locally using a git clone. Then create a new folder and uv environment for the testing of the SDK

```bash
mkdir bev-sdk-test
cd bev-sdk-test
uv init
```

(You may need to install uv <https://docs.astral.sh/uv/getting-started/installation/>)

Then setup the bev SDK in the UV environment:

```bash
uv add --editable <path_to_local_sdk>/external-weather-api/sdk
```

Next create a .env file to get environment variables. Use this .env schema to help you

```.env
# @type=string(startsWith=test-,uat-,prod-) @required @sensitive
BEV_CERA_API_KEY=

# @type=url
#BEV_CERA_BASE_URL=
```

Source the environment variables

```bash
source .env
```

Then edit the main.py file, created by uv, to this to test lite scores.

```python
def main():
    from bev_cera import Client

    with Client() as client:
        score = client.lite.score(latitude=51.5, longitude=-0.1)
        print(score.scores.root)


if __name__ == "__main__":
    main()
```

To run the application use

```bash
uv run main.py
```

## License and service terms

The `bev-cera` Python SDK source in this directory and its distribution
artifacts are licensed under the [MIT License](LICENSE).

The MIT License applies only to the client SDK. It does not license the hosted
External Weather API, server-side software, weather models, datasets, API
credentials, service operation, or trademarks. Access to the hosted API
requires separately issued credentials and is governed by the applicable
service terms.

For SDK support, contact `albert.dow@birdseyeview.ai`.
