Metadata-Version: 2.4
Name: novitus-noviapi
Version: 0.1.1
Summary: Python client library for the Novitus NoviAPI fiscal printer REST API.
Project-URL: Homepage, https://noviapi.novitus.pl/
Project-URL: Documentation, https://noviapi.novitus.pl/
Project-URL: Repository, https://github.com/dekoza/novitus-noviapi
Project-URL: Issues, https://github.com/dekoza/novitus-noviapi/issues
License: Apache-2.0
License-File: LICENSE
Keywords: fiscal-printer,noviapi,novitus,pos,printer
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: anyio<5.0,>=4.9
Requires-Dist: httpx<1.0,>=0.28
Requires-Dist: pydantic<3.0,>=2.11
Description-Content-Type: text/markdown

# novitus-noviapi

[![PyPI version](https://img.shields.io/pypi/v/novitus-noviapi.svg)](https://pypi.org/project/novitus-noviapi/) [![CI](https://github.com/dekoza/novitus-noviapi/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/dekoza/novitus-noviapi/actions/workflows/ci.yml) [![Python versions](https://img.shields.io/pypi/pyversions/novitus-noviapi.svg)](https://pypi.org/project/novitus-noviapi/) [![License](https://img.shields.io/pypi/l/novitus-noviapi.svg)](https://pypi.org/project/novitus-noviapi/) [![PEP 561](https://img.shields.io/badge/PEP%20561-typed-blue.svg)](https://peps.python.org/pep-0561/)

Python client library for the Novitus NoviAPI fiscal printer REST API.

`novitus-noviapi` is the package name on PyPI. Import it as `noviapi`.

## Features

- Sync and async clients with explicit endpoint methods
- Strict Pydantic request and response models
- Token lifecycle handling with retry on expired tokens
- Async client built on `httpx` and `anyio`
- Offline contract tests against a frozen NoviAPI OpenAPI snapshot

## Installation

```bash
uv add novitus-noviapi
```

Pass an `http://` or `https://` base URL that points either at the printer root
or directly at a path ending with `/api/v1`. The client normalizes root URLs to
`/api/v1` and rejects ambiguous subpaths.

## Quick start

```python
from decimal import Decimal

from noviapi import NoviApiClient
from noviapi.models import Article, Item, Receipt, Summary

client = NoviApiClient('http://127.0.0.1:8888/api/v1/')

receipt = Receipt(
    items=[
        Item(
            article=Article(
                name='Coffee',
                ptu='A',
                quantity=Decimal('1'),
                price=Decimal('10.00'),
                value=Decimal('10.00'),
            )
        )
    ],
    summary=Summary(total=Decimal('10.00'), pay_in=Decimal('10.00')),
)

created = client.receipt_send(receipt)
client.receipt_confirm(created.request.id)
```

## Async quick start

```python
from noviapi import NoviApiAsyncClient
from noviapi.exceptions import NoviApiTransportError


async def main() -> None:
    async with NoviApiAsyncClient('http://127.0.0.1:8888/api/v1/') as client:
        try:
            if not await client.comm_test():
                raise RuntimeError('Printer returned an unexpected non-200 response')
        except NoviApiTransportError:
            raise RuntimeError('Printer is not reachable') from None
```

## Authentication

- Most endpoint methods fetch and refresh tokens automatically.
- `comm_test()` is the exception: it is intentionally auth-free.
- `comm_test()` returns `True` for `200 OK`, returns `False` for unusual non-error
  responses such as redirects, and raises on transport errors or HTTP responses
  `>= 400`.
- Use `token_get()` when you need to inspect or bootstrap a token explicitly.
- Use `token_refresh()` when you need to force a refresh cycle yourself.

```python
from noviapi import NoviApiClient

with NoviApiClient('http://127.0.0.1:8888/api/v1/') as client:
    token = client.token_get()
    client.token_refresh(token.token)
```

## Error handling

Transport problems and API errors are separated.

```python
from noviapi import NoviApiClient
from noviapi.exceptions import (
    AuthenticationError,
    NoviApiTransportError,
    TooManyTokenRequestsError,
)

with NoviApiClient('http://127.0.0.1:8888/api/v1/') as client:
    try:
        queue = client.queue_check()
    except TooManyTokenRequestsError as exc:
        allowed_refresh_date = (
            exc.detail.exception.allowed_refresh_date
            if exc.detail is not None
            else None
        )
        print(allowed_refresh_date)
    except AuthenticationError:
        print('Token rejected by printer')
    except NoviApiTransportError:
        print('Network error or invalid JSON response')
    else:
        print(queue.requests_in_queue)
```

## Hardware testing

Hardware tests are opt-in and intended only for development against a real
device. The default hardware smoke test only checks `comm_test()` so the suite
does not print fiscal documents by accident.

The current hardware suite also covers `queue_check()` and a read-only
`status_send()` / `status_confirm()` / `status_check()` device-status flow.
That status flow is treated as stateful and requires an extra explicit flag.
Long-poll `timeout` parameters are forwarded in milliseconds, matching the
NoviAPI contract.

Set the printer base URL and enable the hardware test marker explicitly:

```bash
export NOVIAPI_BASE_URL="http://192.168.1.50:8888/api/v1/"
uv run pytest tests/hardware --run-hardware -m hardware
```

If `--run-hardware` is omitted, hardware tests are skipped. If
`NOVIAPI_BASE_URL` is missing, pytest fails fast with a usage error. Stateful
hardware tests also require `--run-hardware-stateful`.

See `docs/hardware-testing.md` for the full checklist, requirements, safety
notes, and recommended execution procedure.

## Status

This library started as one part of a larger project and was later extracted
into a standalone open-source package. It currently ships strict models,
explicit endpoint coverage, contract tests, lean release artifacts, and a small
hardware test suite, while broader hardware coverage and additional release
automation are still planned.

The extraction and open-source work was sponsored by
[Diablaq](https://diablaq.com/), and Novitus provided a development kit for
the project.
