Metadata-Version: 2.4
Name: vertical-weather
Version: 0.1.0
Summary: Client for the Vertical Weather API: wind, temperature, pressure, humidity and air density at chosen heights, from NOAA GFS.
Author-email: Stephen Filios <support@verticalweather.com>
License-Expression: MIT
Project-URL: Homepage, https://verticalweather.com
Project-URL: Documentation, https://verticalweather.com/guide/requests/
Keywords: weather,wind,altitude,gfs,atmosphere,forecast,vertical-profile
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pydantic<3,>=2.10
Dynamic: license-file

# vertical-weather

Python client for the [Vertical Weather](https://verticalweather.com) API. Ask
for wind, temperature, pressure, humidity and air density at the heights you
choose above a point, from NOAA's GFS model.

```sh
pip install vertical-weather
```

Needs Python 3.11 or later. Get an API key from the
[dashboard](https://api.verticalweather.com/dashboard); the API is in free beta.

## Example

```python
import os
from vertical_weather import get_profile

profile = get_profile(os.environ["VERTICAL_WEATHER_API_KEY"], {
    "latitude": 35.052,
    "longitude": -117.985,
    "time": "2026-10-03T18:00:00Z",
    "altitudes_m": [1000, 2000, 5000],
    "altitude_reference": "agl",
})
for level in profile.levels:
    print(level.altitude_agl_m, level.wind_speed_ms, level.wind_direction_deg)
```

In async code, use `await async_get_profile(...)` with the same arguments.
The result is a typed Pydantic model; `profile.model_dump(mode="json")` gives
plain data. `PROFILE_UNITS` names the unit of every level field.

Keep the key on a server. Don't ship it in a mobile app, browser code or a
public repository.

## Reading the results

- Heights are metres above ground (`agl`) or above mean sea level (`msl`).
  Ground is the model's terrain unless you pass `ground_elevation_m_msl`.
- Wind `u` points east and `v` north, in m/s. `wind_direction_deg` is where the
  wind comes from, clockwise from true north; 0 at zero speed means calm.
- `valid_time` is the model time actually used and can differ from the time
  you asked for. `provenance` names the model run and grid point.
- Relative humidity can be above 100%.

## Options

Keyword arguments to both functions:

| Option | Default | Meaning |
| --- | --- | --- |
| `base_url` | `https://api.verticalweather.com` | API address |
| `timeout_ms` | 30000 | Time limit per attempt (1 to 300000) |
| `max_elapsed_ms` | 30000 | Time limit for the whole call, including waits |
| `max_attempts` | 1 | Up to 5; retries only `429 rate_limited` and `503 source_busy` |

Retries wait for `Retry-After` when the server sends it. Timeouts and network
errors are never retried, since the server may already have done the work.

## Errors

Every failure raises `AtmosphereError` with `code`, `status`, `request_id`,
`retry_after_ms` and `coverage`.

| Code | What to do |
| --- | --- |
| `unauthorized` (401) | Check the key. |
| `profile_out_of_range` (409) | A height is outside the model column; `coverage` has the available range. |
| `rate_limited` (429) | Wait `retry_after_ms`, or allow retries. |
| `source_busy` (503) | Try again shortly. |
| `timeout`, `network_error` | The request may or may not have completed. |
| `invalid_response`, `unexpected_status` | The response didn't match the contract. |
| `invalid_request`, `missing_key`, `invalid_url`, `invalid_options` | Fix the input. |

The client checks every response against the request (heights, time, ground,
coverage, derived wind) and never fills in missing values. It follows no
redirects, ignores proxy environment variables and never logs your key.

## Links

- Guides: https://verticalweather.com
- Support: support@verticalweather.com

MIT license.
