Skip to main content

novitus-noviapi

PyPI version CI Python versions License PEP 561

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

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, strips a trailing slash from /api/v1/, and rejects ambiguous subpaths.

from noviapi import NoviApiClient

with NoviApiClient('http://127.0.0.1:8888') as client:
    client.comm_test()

Quick start

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

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.
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)

Sharing a token across clients

By default each client keeps its own token in memory for its own lifetime. Most NoviAPI devices tolerate only one active token and rate-limit token requests per hour, so if multiple client instances or processes talk to the same device, each minting its own token can exhaust that budget and start failing every one of them with TooManyTokenRequestsError.

Pass a token_store to share one token instead. FileTokenStore ships with the library and needs no external service -- it persists the token to a file (in the OS temp dir by default) guarded by a lockfile, so every process on the machine reuses the same token:

from noviapi import FileTokenStore, NoviApiClient

store = FileTokenStore('http://127.0.0.1:8888/api/v1')
with NoviApiClient('http://127.0.0.1:8888/api/v1', token_store=store) as client:
    client.queue_check()

Implement the TokenStore protocol (load/save/clear/try_lock/unlock) to back this with anything else -- Redis, a database row, etc.

Pass token_refresh_margin_seconds to refresh proactively before a token actually expires, instead of waiting for it to lapse (or for a request to come back 401):

NoviApiClient(
    'http://127.0.0.1:8888/api/v1',
    token_store=store,
    token_refresh_margin_seconds=60,
)

A stored token the device has stopped honouring -- 401 on use and 401 on the PATCH /token refresh, whatever its expiration_date says -- is dropped from the store and replaced by a freshly minted one, and the request is retried once. Only a 401 from the refresh does that: a 403 or 429 still raises, because minting cannot help there.

NoviApiAsyncClient accepts the same token_store (implementing AsyncTokenStore) and token_refresh_margin_seconds parameters.

Error handling

Transport problems and API errors are separated.

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 suite only covers comm_test() and queue_check() so it does not print fiscal documents by accident.

Optional stateful coverage includes a read-only status_send() / status_confirm() / status_check() device-status flow and a non-fiscal document test in tests/hardware/test_nf_printout.py that prints Greetings from the test suite!. Those tests require the extra --run-hardware-stateful flag.

The non-fiscal document test still consumes paper, so run it only when that output is acceptable.

These hardware checks are manual and are not part of GitHub Actions. CI only covers contract, unit, integration, and packaging validation.

Long-poll timeout parameters are forwarded in milliseconds, matching the NoviAPI contract.

The current supported printer matrix below reflects the minimum firmware versions declared by the printer manufacturer for NoviAPI support:

  • POINT firmware 1.00
  • HD II Online firmware 3.50
  • Deon Online firmware 310
  • Bono Online firmware 300
  • INFIS firmware 1.30

This library has been personally verified on POINT firmware 1.00. Treat the other entries as manufacturer-declared minimum supported versions until they are individually exercised by this project's hardware validation.

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

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.

See RC_CHECKLIST.md for the current release-candidate gate.

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, artifact install smoke checks, and a small hardware test suite. Hardware support remains intentionally narrow and manual hardware validation still sits outside GitHub Actions; the supported printer matrix lives in docs/hardware-testing.md.

The extraction and open-source work was sponsored by Diablaq, and Novitus provided a development kit for the project. Thank you!

Metadata

Release files for novitus-noviapi 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for novitus-noviapi 0.3.2
File Size Uploaded
novitus_noviapi-0.3.2.tar.gz 19.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for novitus-noviapi 0.3.2
File Interpreter ABI Platform
novitus_noviapi-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 41.5 kB

Release files / novitus_noviapi-0.3.2.tar.gz

Download URL novitus_noviapi-0.3.2.tar.gz
Size 19.7 kB
Tags Source
SHA-256 checksum
How to use checksums
2ac8b9db0653f32edad7c9dea5a0da463bd8d1454cf529cb1f7d5f3a26d48e0c
BLAKE2b-256 checksum
How to use checksums
3d1e5c099146d02167f517413c5ef48dcb44ee79a0b3eace17d617990b52833e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release files / novitus_noviapi-0.3.2-py3-none-any.whl

Download URL novitus_noviapi-0.3.2-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8214c76ab3ab431555e20fb756f26fd30f21901902e6d3440bfb21bc9475368a
BLAKE2b-256 checksum
How to use checksums
635476045b0c473b713a11087c74424dc17e4c9d5f1ffafd197e313ac16a5e16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page