Metadata-Version: 2.4
Name: billos
Version: 0.1.0
Summary: BillOS for Python: Israeli tax documents, expenses, webhooks and the regulatory outputs, over one small client.
Author: BillOS
License: MIT
Project-URL: Documentation, https://docs.billos.co.il
Project-URL: Homepage, https://billos.co.il
Project-URL: Source, https://github.com/baraviz/pest-os/tree/main/packages/billos-python
Keywords: billos,invoice,bookkeeping,israel,tax,api
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: Financial :: Accounting
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# billos (Python)

BillOS from Python: legally valid Israeli tax documents (חשבונית מס, קבלה, זיכוי), the expense ledger, webhooks and the regulatory outputs, over one small client with no dependencies beyond the standard library (Python 3.9+).

```bash
pip install billos
```

```python
from billos import BillOS, BillOSError

billos = BillOS(api_key=os.environ["BILLOS_API_KEY"])
bid = billos.businesses.list()["businesses"][0]["id"]

created = billos.documents.create(bid, {
    "docType": 320,
    "priceMode": "gross",
    "party": {"name": "דנה לוי", "phone": "0521111111"},
    "lines": [{"description": "איפור כלה", "quantity": 1, "unitPriceExVat": 120000}],
    "payments": [{"method": "card", "amount": 120000}],
}, idempotency_key="order-8812")

issued = billos.documents.issue(bid, created["document"]["id"])
print(issued["document"]["docNumber"])

pdf = billos.documents.print(bid, created["document"]["id"])   # Binary: .bytes, .content_type, .variant
link = billos.documents.share(bid, created["document"]["id"])   # a public URL for the customer
```

Money is **integer agorot** everywhere, exactly like the API (₪354.00 is `35400`); a foreign-currency document (`"currency": "USD"`) is in that currency's cents. Nothing in the client converts.

## What you get

- Every operation in the spec as `namespace.method` (snake_case): `businesses`, `parties`, `documents`, `recurring`, `expenses`, `exports`, `files`, `webhooks`, `events`, `keys`, `usage`, `sandbox`. `OPERATIONS` (method and path per operation) is generated from the OpenAPI spec, and a test checks every operation has a method, so the client cannot lag behind the API.
- The conventions handled: `X-Api-Key`, the `{ok, ...}` envelope returned as a dict (plus `request_id`), `Idempotency-Key` from `idempotency_key=`, `Retry-After` honoured.
- Retries on 429 / 502 / 503 / 504 and network errors, up to `max_retries` (default 2), for GET/DELETE and for POSTs carrying an idempotency key; never for a POST without one.
- `BillOSError` with `status`, `reason`, `request_id`, `body`, `retryable`. Branch on `reason`.
- Binary answers (`documents.preview`, `documents.print`, `files.get`, a PDF report) come back as `Binary(bytes, content_type, variant, request_id)`.
- `verify_webhook_signature(secret, header, raw_body)` for the `X-BillOS-Signature` header.
- A `bk_test_` key answers from the sandbox with no change on your side (`billos.sandbox.seed()` fills it with demo data).

Documentation and the OpenAPI spec: https://docs.billos.co.il. MIT.
