Metadata-Version: 2.4
Name: northlight-checker
Version: 0.1.0
Summary: Official Python SDK for the Northlight Checker API — validate Russian electronic medical records against clinical guidelines.
Project-URL: Homepage, https://sciencerocket.tech
Project-URL: Documentation, https://devs.sciencerocket.tech/docs
Project-URL: Issues, https://github.com/northlight-ai/checker-sdk-python/issues
Author-email: ООО «Наука Ракета» <support@sciencerocket.tech>
License: Apache-2.0
License-File: LICENSE
Keywords: checker,clinical-guidelines,healthcare,medical,northlight,oms,russia
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# northlight-checker

Official Python SDK for the [Northlight Checker API](https://devs.sciencerocket.tech/docs) —
validate Russian electronic medical records (ЭМК) against clinical guidelines
(Клинические рекомендации Минздрава РФ), quality criteria, МЭС, and more.

- Sync + async clients (`httpx`)
- Typed pydantic models that mirror the API schemas 1:1
- Automatic retries with exponential backoff + `Retry-After` support
- Typed exceptions for every HTTP failure mode
- Works with `NORTHLIGHT_API_KEY` env var out of the box

---

## Install

```bash
pip install northlight-checker
```

Requires Python 3.10+. Core deps: `httpx>=0.27`, `pydantic>=2.0`.

## 30-second quick start

```python
from northlight_checker import CheckerClient, MedicalRecord

with CheckerClient(api_key="nlt_...") as client:
    result = client.validate(
        medical_record=MedicalRecord(
            diagnosis="E11 Сахарный диабет 2 типа",
            diagnosis_code="E11",
            anamnesis="Болеет 5 лет, компенсация неустойчивая.",
            prescriptions=["Метформин 1000 мг 2 р/сут"],
            examinations=["HbA1c 7.8%", "Глюкоза натощак 8.2"],
        ),
        scope="case",
    )

print(result.overall_score)          # 0.0–1.0
print(result.critical_violations)    # list[Violation]
print(result.summary)                # narrative from the checker
```

Set `NORTHLIGHT_API_KEY` in your environment and you can drop `api_key=...`:

```bash
export NORTHLIGHT_API_KEY=nlt_live_xxx
```

```python
from northlight_checker import CheckerClient

with CheckerClient() as client:
    result = client.validate(medical_record=record, scope="case")
```

## Async

```python
import asyncio
from northlight_checker import AsyncCheckerClient, MedicalRecord

async def main() -> None:
    async with AsyncCheckerClient() as client:
        result = await client.validate(
            medical_record=MedicalRecord(
                diagnosis="I21.0 Острый трансмуральный инфаркт миокарда передней стенки",
                diagnosis_code="I21.0",
                anamnesis="Боли за грудиной 4 часа, ST-элевация.",
                prescriptions=["Аспирин 300 мг", "Клопидогрел 600 мг", "Гепарин"],
                examinations=["ЭКГ", "Тропонин I", "ЭхоКГ"],
            ),
            scope="case",
            application="CARDIO",
        )
        print(result.overall_score)

asyncio.run(main())
```

## Batch

```python
from northlight_checker import CheckerClient, MedicalRecord

records = [
    MedicalRecord(diagnosis="E11 ...", anamnesis="..."),
    MedicalRecord(diagnosis="I21 ...", anamnesis="..."),
]

with CheckerClient() as client:
    results = client.validate_batch(records=records, scope="case")

for item in results:
    if item.is_error:
        print(item.index, "failed:", item.error)
    else:
        print(item.index, item.result.overall_score)
```

## HTML report

```python
from pathlib import Path
from northlight_checker import CheckerClient

with CheckerClient() as client:
    html_bytes = client.validate_report(medical_record=record, scope="case")

Path("report.html").write_bytes(html_bytes)
```

## Error handling

```python
from northlight_checker import (
    CheckerClient,
    AuthError,
    RateLimitError,
    InsufficientBalanceError,
    ValidationError,
    ServerError,
    NorthlightError,
)

try:
    with CheckerClient() as client:
        result = client.validate(medical_record=record, scope="case")
except AuthError:
    # 401 / 403 — check your API key
    raise
except InsufficientBalanceError:
    # 402 — top up your prepaid balance
    raise
except RateLimitError as e:
    # 429 after retries — wait `e.retry_after` seconds or upgrade your plan
    print("rate limited, wait", e.retry_after)
except ValidationError:
    # 422 — request schema mismatch (caller bug)
    raise
except ServerError:
    # 5xx after retries exhausted
    raise
except NorthlightError:
    # base class for everything above + network errors
    raise
```

Transient failures (429, 5xx, timeouts, connection errors) are retried
automatically up to 3 times with exponential backoff (1 s → 2 s → 4 s).
If the server sends a `Retry-After` header on 429, we honour it exactly.
4xx responses other than 429 are **not** retried — they mean your request
has a problem.

## Other endpoints

```python
with CheckerClient() as client:
    scopes = client.list_scopes()     # ['case', 'mes', 'quality_criteria', ...]
    meta   = client.get_meta()        # {'version': ..., 'config': ..., 'scopes': [...]}
```

## Scopes

| Scope                     | What it checks                                                      |
| ------------------------- | ------------------------------------------------------------------- |
| `case`                    | Клинические рекомендации (КР) — general compliance                  |
| `mes`                     | Медико-экономический стандарт (МЭС) — OMS minimum coverage          |
| `regional_standard`       | Территориальная программа ОМС                                       |
| `standard_of_care`        | Федеральный стандарт оказания помощи (Приказ МЗ РФ)                 |
| `relevant_normative_acts` | Порядки оказания помощи (e.g. 3/14/7-day rule in oncology)          |
| `quality_criteria`        | Критерии оценки качества (КОК, Приказ №520н)                        |
| `dispensary_observation`  | План диспансерного наблюдения                                       |

## Configuration

| Arg        | Default                          | Env var                |
| ---------- | -------------------------------- | ---------------------- |
| `api_key`  | `None`                           | `NORTHLIGHT_API_KEY`   |
| `base_url` | `https://api.sciencerocket.tech` | —                      |
| `timeout`  | `300` s                          | —                      |

LLM-backed validation can take minutes, so timeouts default to five.

## Logging

The SDK uses the standard `logging` module. Turn on INFO to see retry decisions:

```python
import logging
logging.getLogger("northlight_checker").setLevel(logging.INFO)
```

## Full API reference

See [devs.sciencerocket.tech/docs](https://devs.sciencerocket.tech/docs) for
the complete API reference including all fields, scopes, and examples.

## License

Apache 2.0. © ООО «Наука Ракета».
