Metadata-Version: 2.4
Name: fakturownia-client
Version: 0.1.2
Summary: Unofficial Python client for the Fakturownia (InvoiceOcean) REST API
Author-email: Krzysztof Marmol <krzysztof.marmol@gmail.com>
License-Expression: MIT
Project-URL: Repository, https://github.com/KrzysztofMarmol/fakturownia-client
Project-URL: Issues, https://github.com/KrzysztofMarmol/fakturownia-client/issues
Project-URL: Changelog, https://github.com/KrzysztofMarmol/fakturownia-client/blob/main/CHANGELOG.md
Keywords: fakturownia,invoiceocean,invoices,api,client
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Financial :: Accounting
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.7
Provides-Extra: dev
Requires-Dist: ruff>=0.5.0; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: pytest>=8.2; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"
Dynamic: license-file

# fakturownia-client

[![PyPI](https://img.shields.io/pypi/v/fakturownia-client)](https://pypi.org/project/fakturownia-client/)
[![CI](https://github.com/KrzysztofMarmol/fakturownia-client/actions/workflows/ci.yml/badge.svg)](https://github.com/KrzysztofMarmol/fakturownia-client/actions/workflows/ci.yml)
[![Python](https://img.shields.io/pypi/pyversions/fakturownia-client)](https://pypi.org/project/fakturownia-client/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

**Unofficial** Python client for the [Fakturownia](https://fakturownia.pl)
(InvoiceOcean) REST API. Covers invoices (list/search, create/update, status
changes, PDF download), clients (CRUD) and products.

> This is a community-maintained project. It is not affiliated with, endorsed
> by, or sponsored by Fakturownia sp. z o.o. or InvoiceOcean. "Fakturownia"
> and "InvoiceOcean" are trademarks of their respective owner, used here only
> to indicate compatibility.

## Security note: token in header, never in URL

The official Fakturownia docs mostly show `?api_token=...` in URLs, which leaks
tokens into server and proxy logs. This client sends the token **only** in the
`Authorization: Bearer` header. Header auth was verified against the live API
for every endpoint used here (see `scripts/verify_auth.py` — a no-side-effects
check you can run against your own account).

## Install

```bash
uv add fakturownia-client   # or: pip install fakturownia-client
```

## Usage

```python
from fakturownia_client import FakturowniaClient, InvoiceCreate, InvoicePositionCreate

with FakturowniaClient("mycompany", api_token="...") as fk:
    # list & search
    invoices = fk.list_invoices(period="this_month", include_positions=True)
    for inv in fk.iter_invoices(period="this_year"):  # auto-pagination
        print(inv.number, inv.price_gross)

    # create
    created = fk.create_invoice(
        InvoiceCreate(
            buyer_name="ACME Sp. z o.o.",
            buyer_tax_no="1234567890",
            positions=[InvoicePositionCreate(name="Usługa", total_price_gross=123.00, tax=23)],
        )
    )

    # status & PDF
    fk.change_invoice_status(created.id, "paid")
    pdf = fk.download_invoice_pdf(created.id)

    # clients / products
    clients = fk.list_clients(tax_no="1234567890")
    products = fk.list_products()
```

### Async

`AsyncFakturowniaClient` mirrors the sync API 1:1 on `httpx.AsyncClient`:

```python
from fakturownia_client import AsyncFakturowniaClient

async with AsyncFakturowniaClient("mycompany", api_token="...") as fk:
    invoices = await fk.list_invoices(period="this_month")
    async for inv in fk.iter_invoices(period="this_year"):
        print(inv.number)
```

`domain` accepts `"mycompany"`, `"mycompany.fakturownia.pl"` or a full URL.

### InvoiceOcean

InvoiceOcean is the international brand of Fakturownia — same API. Pass your
full domain: `FakturowniaClient("mycompany.invoiceocean.com", api_token=...)`.
This repository also publishes a companion alias package,
[`invoiceocean-client`](https://pypi.org/project/invoiceocean-client/), which
re-exports this API as `InvoiceOceanClient` / `AsyncInvoiceOceanClient`
(equally unofficial).
Errors raise typed exceptions: `AuthenticationError`, `NotFoundError`,
`ValidationError`, `RateLimitError`, `ServerError` (all subclass `FakturowniaError`).

Caveat: `delete_product()` calls an endpoint absent from the official API docs —
it may not work on all accounts.

## Development

```bash
uv sync --extra dev
uv run ruff check . && uv run mypy && uv run pytest -m "not live"

# optional read-only smoke test against the real API:
FAKTUROWNIA_DOMAIN=mycompany FAKTUROWNIA_API_TOKEN=... uv run pytest -m live
```

## License

MIT
