Metadata-Version: 2.4
Name: noonlight-dispatch
Version: 0.1.1
Summary: Async client for the Noonlight Dispatch API
Project-URL: Homepage, https://github.com/brentb2529/noonlight-dispatch
Project-URL: Issues, https://github.com/brentb2529/noonlight-dispatch/issues
Author: Brent Bensten
License-Expression: MIT
License-File: LICENSE
Keywords: alarm,dispatch,emergency,home-assistant,noonlight
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx>=0.24
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
Requires-Dist: pytest>=8; extra == 'test'
Requires-Dist: respx>=0.20; extra == 'test'
Description-Content-Type: text/markdown

# noonlight-dispatch

A small, typed, async Python client for the [Noonlight](https://www.noonlight.com)
**Dispatch API** (`/dispatch/v1`). Built on [`httpx`](https://www.python-httpx.org/),
it accepts a shared client/session so it slots cleanly into apps like Home
Assistant.

It handles the Noonlight wire-format quirks for you: phone numbers are sent as
digits with a country code but no leading `+`, and US states as the uppercase
2-letter code.

## Install

```bash
pip install noonlight-dispatch
```

## Usage

```python
import httpx
from noonlight_dispatch import NoonlightClient, SANDBOX_BASE_URL

async def main():
    async with httpx.AsyncClient() as session:
        client = NoonlightClient(session, "YOUR_TOKEN", base_url=SANDBOX_BASE_URL)

        alarm = await client.create_alarm(
            services=["police"],
            name="Jane Doe",
            phone="+1 (202) 555-0142",   # stored/sent as 12025550142
            address="123 Main St",
            city="Springfield",
            state="va",                  # sent as VA
            zip_code="62704",
            instructions="Triggered by Front Door motion",  # -> instructions.entry
            owner_id="Site A",           # caller-defined site identifier
        )
        alarm_id = alarm["id"]

        status = await client.get_alarm_status(alarm_id)
        await client.cancel_alarm(alarm_id)
```

`SANDBOX_BASE_URL` never alerts real responders — use it for testing.
`PRODUCTION_BASE_URL` is the default.

## Errors

All failures raise a subclass of `NoonlightError`:

- `NoonlightAuthError` — token rejected (401/403)
- `NoonlightConnectionError` — unreachable / timeout
- `NoonlightResponseError` — unexpected status or body (carries `.status_code`)

## Development

```bash
pip install -e ".[test]"
pytest
```

## License

MIT
