cashio-client
Python client for the Cashio Client API (transactions and purchase payments).
Install in other projects with pip install cashio-client (after publishing) or from a local path / git URL.
کلاینت پایتون برای API کلاینت Cashio (تراکنشها و پرداختهای خرید). قابل استفاده در پروژههای دیگر و قابل انتشار روی PyPI.
Install
pip install cashio-client
From this repo (editable):
pip install -e .
Quick start
from cashio_client import CashioClient
client = CashioClient("http://127.0.0.1:8000", token="YOUR_TOKEN")
result = client.transactions.create(
amount=1500000,
type="income",
description="from rahkarmelk",
date="1405-06-22",
)
print(result.ok, result.id)
Token comes from Cashio Settings → Client API Config. There is no session login.
If that config has a default fund (and category), you can omit fund / category.
Authentication
The token is sent with one method (default: Bearer header):
| Method | How |
|---|---|
bearer (default) |
Authorization: Bearer <token> |
token |
Authorization: Token <token> |
x-api-token |
X-Api-Token: <token> |
body |
JSON/form field "token": "<token>" |
from cashio_client import AuthMethod, CashioClient, CashioSettings
settings = CashioSettings(
"http://127.0.0.1:8000",
token="YOUR_TOKEN",
auth_method=AuthMethod.X_API_TOKEN,
)
client = CashioClient(settings)
base_url is the Cashio host (http://127.0.0.1:8000). A trailing /a/api is stripped if present. Requests go to {base_url}/a/api/....
Create a transaction
POST /a/api/transaction/create
result = client.transactions.create(
amount=250000,
transaction_type="expense",
fund=15,
category=3,
description="rent",
payment_type="full_payment",
)
Aliases from the API are accepted: type for transaction_type, fund_id for fund, category_id for category, holder_id for holder.
With files (multipart)
result = client.transactions.create(
amount=1500000,
type="income",
attached_file=["/path/to/receipt.pdf", "/path/to/photo.jpg"],
)
attached_file may be a path, a file object, a (filename, fileobj) tuple, or a list of those.
Fields
| Field | Type | Required |
|---|---|---|
amount |
number / Decimal | yes |
transaction_type / type |
income or expense |
yes |
fund / fund_id |
int | if no default fund |
category / category_id |
int | no (client default) |
description |
str | no |
date |
str Jalali YYYY-MM-DD |
no |
reference_number |
str | no |
payment_type |
full_payment, part_payment, completed_parts |
no (API default full_payment) |
holder / holder_id |
int | no |
transaction_linked |
int | no |
fee |
number | no (creates a linked expense) |
attached_file |
file(s) | no |
Constants: TransactionType.INCOME, TransactionType.EXPENSE, PaymentType.FULL_PAYMENT, …
Purchase payments
Two kinds: direct (already paid, invoice documents required, created as completed) and indirect (accountant pays later, documents optional, created as unseen).
from cashio_client import PurchaseKind, PurchasePaymentStatus
# direct: documents required
result = client.purchases.create_direct(
amount=1500000,
documents=["/path/to/invoice.jpg"],
description="stationery",
payment_date="1405-06-22", # optional Jalali date, defaults to today
request_id="INV-1", # optional, unique per client
lines=[
{"description": "A4 paper", "quantity": 2, "unit": "box", "unit_price": 750000},
{"description": "pen", "quantity": 10},
],
)
print(result.id, result.status) # 11 completed
# indirect: documents optional
result = client.purchases.create_indirect(amount=300000, description="taxi", request_id="INV-2")
# read
payment = client.purchases.get(result.id) # by id
payment = client.purchases.get(request_id="INV-2") # by your own reference
payments = client.purchases.list(status=PurchasePaymentStatus.IN_REVIEW, kind=PurchaseKind.INDIRECT)
payment.status, payment.amount, payment.lines, payment.documents, payment.transaction_id
# lines, documents, history
client.purchases.lines(payment.id)
client.purchases.add_lines(payment.id, {"description": "stapler", "quantity": 1}) # one
client.purchases.add_lines(payment.id, [{"description": "a", "quantity": 1}, ...]) # many
client.purchases.documents(payment.id)
client.purchases.add_documents(payment.id, ["/path/to/receipt.pdf"])
client.purchases.statuses(payment.id)
| Method | Endpoint |
|---|---|
purchases.create_direct(...) |
POST /a/api/purchase/direct/create |
purchases.create_indirect(...) |
POST /a/api/purchase/indirect/create |
purchases.list(status=, kind=) |
GET /a/api/purchase/list |
purchases.get(id) / get(request_id=) |
GET /a/api/purchase/<id>/status / purchase/status?request_id= |
purchases.lines(id) / add_lines(id, ...) |
GET / POST /a/api/purchase/<id>/lines |
purchases.documents(id) / add_documents(id, files) |
GET / POST /a/api/purchase/<id>/documents |
purchases.statuses(id) |
GET /a/api/purchase/<id>/statuses |
- Statuses:
unseen,seen,in_review,completed(PurchasePaymentStatus). - Line units:
piece(default),kilogram,gram,liter,meter,box,pack,set,other(PurchaseLineUnit). - Lines and documents of a
completedpayment cannot be changed (CashioAPIError). - Money values are returned as
Decimal; dates and timestamps stay strings as sent by the API. - Files accept the same inputs as
attached_fileabove.
Errors
from cashio_client import (
CashioAuthError,
CashioNotFoundError,
CashioValidationError,
CashioAPIError,
)
try:
client.transactions.create(amount=10, type="income")
except CashioAuthError as exc:
print(exc.status_code, exc.payload) # 401
except CashioValidationError as exc:
print(exc.errors) # {"fund": ["This field is required."]}
except CashioNotFoundError as exc:
print(exc.status_code) # 404 (e.g. unknown purchase payment); subclass of CashioAPIError
except CashioAPIError as exc:
print(exc.status_code, exc.payload) # 400 detail / 405 / other
Publish to PyPI
pip install -e ".[dev]"
python -m build
twine upload dist/*
Use TestPyPI first: twine upload --repository testpypi dist/*.
License
MIT
Metadata
Release files for cashio-client 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cashio_client-0.2.0.tar.gz | 23.7 kB | Without provenance | Details for cashio_client-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cashio_client-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for cashio_client-0.2.0-py3-none-any.whl |
Total release size: 38.6 kB
Release files / cashio_client-0.2.0.tar.gz
| Download URL | cashio_client-0.2.0.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e46f878927385d9dd0ed21b32022147e8dd80320e741dca55ee91cc11f2a0c88
|
|
BLAKE2b-256 checksum How to use checksums |
92f1dc86755d5d29d421f134e216e65b859062ee9188d16eb1f6ef702d1825d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / cashio_client-0.2.0-py3-none-any.whl
| Download URL | cashio_client-0.2.0-py3-none-any.whl |
|---|---|
| Size | 15.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
76696e69ff3447acf093865ba76518a7d46cebc5d5d74d1ba9c53fbdafb46050
|
|
BLAKE2b-256 checksum How to use checksums |
0ab80f21f2f8f75bfb02e32d45c966e8f37863b17669ab7271d6e03139f67d45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for cashio-client 0.2.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.