Skip to main content

Library to interact with PrusaLink v2

Project description

pyprusalink

PyPI Python License

Async Python client for the PrusaLink HTTP API. Covers both the current /api/v1/... endpoints and a few legacy paths (/api/version, /api/printer).

The primary consumer is the Home Assistant prusalink integration, and API shape decisions are weighted toward serving that integration. Today the library does not perform runtime validation, retry, or caching at the boundary — consumers handle those — but the shape may evolve as the integration's needs do.

Requirements

  • Python 3.11+
  • A PrusaLink-enabled Prusa printer (bundled with Prusa-Firmware-Buddy on Core One, MK4, MK3.9, MK3.5, MINI, XL; or standalone PrusaLink on an RPi)

The library is async-only and is built on httpx. Digest authentication is handled by httpx.DigestAuth under the hood.

Installation

pip install pyprusalink

Quickstart

import asyncio

import httpx
from pyprusalink import PrusaLink


async def main() -> None:
    async with httpx.AsyncClient() as client:
        api = PrusaLink(client, "http://prusa.local", "maker", "<password>")

        info = await api.get_info()
        print(info.get("name"), info.get("serial"))

        status = await api.get_status()
        print(status["printer"]["state"])

        job = await api.get_job()
        if job is not None:
            print(f"{job['progress']:.0f}% — {job['file']['display_name']}")


asyncio.run(main())

The username on bundled-firmware printers is maker. The password is the API key shown under Settings → PrusaLink on the printer.

Public API

Method Returns Notes
get_version() VersionInfo /api/version — firmware, hostname, API version
get_info() PrinterInfo /api/v1/info — serial, model, location, capabilities
get_status() PrinterStatus /api/v1/status — printer state plus embedded job/storage/transfer/camera
get_job() JobInfo | None /api/v1/jobNone when no job is running
get_storage() list[Storage] /api/v1/storage — available storage devices
get_transfer() Transfer | None /api/v1/transferNone when no transfer is in progress
cancel_transfer(transfer_id) None Cancel an active upload
cancel_job(job_id) None Cancel a print
pause_job(job_id) None Pause a running print
resume_job(job_id) None Resume a paused print
continue_job(job_id) None Continue after the printer enters the ATTENTION state (e.g. timelapse capture)
get_legacy_printer() LegacyPrinterStatus /api/printer — legacy endpoint, used for material
get_file(path) bytes Fetch raw resources such as thumbnails referenced from JobFilePrint.refs

Errors

All HTTP errors map to subclasses of PrusaLinkError:

Exception When
InvalidAuth 401 — wrong credentials
NotFound 404 — resource missing
Conflict 409 — action conflicts with current printer state (e.g. cancel while idle)
from pyprusalink.types import Conflict

try:
    await api.cancel_job(42)
except Conflict:
    ...  # printer wasn't in a cancellable state

Type contract

Return types are TypedDicts declared in pyprusalink/types.py. Two conventions worth knowing:

  1. NotRequired[T] for optional fields. The PrusaLink API omits absent fields rather than returning null, so optional fields are NotRequired[T] and consumers must use .get(...) or membership checks. Indexing a missing key raises KeyError.

  2. T | None for return types when the resource may be absent. get_job() and get_transfer() return None (not an empty dict) when there's no active job/transfer.

The library does not perform runtime validation. response.json() results are wrapped in typing.cast(...) against the declared TypedDict. This is a deliberate choice — for a thin wrapper, the runtime overhead and dependency footprint of pydantic/msgspec is not worth it. If you need runtime validation, layer it on top.

Versioning

Semantic versioning. Changes to TypedDict shapes that affect strict-typed consumers are counted as breaking and require a major version bump.

Development

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[test,lint]"

# unit tests (default — integration tests are excluded)
pytest tests/

# lint
black --check pyprusalink/ tests/
flake8 pyprusalink/ tests/
isort --check pyprusalink/ tests/
mypy

Integration tests

Integration tests live in tests/test_integration.py and run against a real printer. They are opt-in via the integration pytest marker:

PRUSALINK_HOST=http://prusa.local \
PRUSALINK_USERNAME=maker \
PRUSALINK_PASSWORD=<api-key> \
pytest tests/test_integration.py -m integration

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyprusalink-3.0.0.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyprusalink-3.0.0-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page