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, created as completed) and indirect (accountant pays later, created as unseen). Documents are optional for both.
The payment amount is not sent: the server computes it as the sum of quantity * unit_price over lines. At least one line is required, and every line needs description, quantity, unit_price.
from cashio_client import PurchaseKind, PurchasePaymentMethod, PurchasePaymentStatus
result = client.purchases.create_direct(
lines=[
{"description": "A4 paper", "quantity": 2, "unit": "box", "unit_price": 750000},
{"description": "pen", "quantity": 10, "unit_price": 5000},
],
documents=["/path/to/invoice.jpg"], # optional
description="stationery",
payment_date="1405-06-22", # optional Jalali date, defaults to today
request_id="INV-1", # optional, unique per client
)
print(result.id, result.status) # 11 completed
result = client.purchases.create_indirect(
lines=[{"description": "ride", "quantity": 1, "unit_price": 300000}],
description="taxi",
request_id="INV-2",
)
# payment methods: cash (default), installment, transfer_order
client.purchases.create_indirect(
lines=[{"description": "laptop", "quantity": 1, "unit_price": 30000000}],
payment_method=PurchasePaymentMethod.INSTALLMENT,
installment_count=3, # required, >= 2
installment_amount=10000000, # required
)
client.purchases.create_indirect(
lines=[{"description": "laptop", "quantity": 1, "unit_price": 30000000}],
payment_method=PurchasePaymentMethod.TRANSFER_ORDER,
transfer_due_date="1405-09-01", # required, Jalali date
guarantee_check=7, # optional, fund check id with purpose "guarantee"
)
# 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
payment.payment_method, payment.installment_count, payment.installment_amount
payment.transfer_due_date, payment.guarantee_check_id
# lines, documents, history (adding lines recalculates the payment amount)
client.purchases.lines(payment.id)
client.purchases.add_lines(payment.id, {"description": "stapler", "quantity": 1, "unit_price": 90000}) # one
client.purchases.add_lines(payment.id, [{"description": "a", "quantity": 1, "unit_price": 10}, ...]) # 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). - Payment methods:
cash,installment,transfer_order(PurchasePaymentMethod). Fields of other methods are ignored by the server. - 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.3.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.3.0.tar.gz | 25.7 kB | Without provenance | Details for cashio_client-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cashio_client-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for cashio_client-0.3.0-py3-none-any.whl |
Total release size: 41.5 kB
Release files / cashio_client-0.3.0.tar.gz
| Download URL | cashio_client-0.3.0.tar.gz |
|---|---|
| Size | 25.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d767cdbd6da4a4bba6df3d3abe5479879d9068136e086784dd7f074d346ef295
|
|
BLAKE2b-256 checksum How to use checksums |
f3be3abca5709836b1234f26357b0c40a4752e847128fd28e48f717b1ad01cdf
|
| 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.3.0-py3-none-any.whl
| Download URL | cashio_client-0.3.0-py3-none-any.whl |
|---|---|
| Size | 15.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
211df2b8e55e7e63f7f35ba0d3cccca1fda63f2ea1cdf3ef2b37d75162433e57
|
|
BLAKE2b-256 checksum How to use checksums |
2a177323dece504c5bf4c0c9db2d7e26a94dc46d089973db2f6106415bfef28d
|
| 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.3.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.