xippios-cashctrl
Typed Python client, MCP server and FastAPI routes for CashCtrl, part of the xippios SDK family. Names and semantics follow the upstream documentation; every response carries release metadata (source, endpoint, retrieved_at, published_at, vintage).
Install
uv add xippios-cashctrl # client only
uv add "xippios-cashctrl[mcp]" # + MCP server
uv add "xippios-cashctrl[http]" # + FastAPI router
Configuration
CashCtrl serves every organisation from its own subdomain
(https://<subdomain>.cashctrl.com/api/v1) and gives every organisation its own API
user. The package therefore works with named organisations, declared in the environment;
nothing is read from files.
| Variable | Meaning |
|---|---|
CASHCTRL_ORGS |
the organisations, comma-separated, lower-case letters, digits and _: acme,acme_test |
CASHCTRL_<NAME>_SUBDOMAIN |
per organisation, the subdomain: CASHCTRL_ACME_SUBDOMAIN=acme |
CASHCTRL_<NAME>_API_KEY |
per organisation, the API user's key (Settings → Users & Roles) |
CASHCTRL_DEMO_SUBDOMAIN, CASHCTRL_DEMO_API_KEY |
the reserved organisation demo, used by this repository's tests; never listed in CASHCTRL_ORGS |
Every task and tool takes org, the name of one declared organisation, as its first
parameter, and every result names it as meta.tenant. list_organisations() (the tool
cashctrl_list_organisations) returns the declared names, nothing else. Each
organisation gets its own client, key and rate limit (60 requests per minute,
self-imposed); nothing spans organisations. A deployment reaches exactly the
organisations its environment declares. An unknown name is refused with the declared
ones; a malformed CASHCTRL_ORGS or a missing or malformed subdomain is a configuration
error naming the variable, never its value.
30-second example
from xippios.cashctrl import tasks
from xippios.cashctrl.models import Filter
print(tasks.list_organisations().data) # the declared organisations, e.g. ["acme", "demo"]
# "demo" stands for any declared organisation; the first argument is always org.
periods = tasks.list_fiscal_periods("demo")
current = next(period for period in periods.data if period.is_current)
accounts = tasks.list_accounts("demo", fiscal_period_id=current.id, only_active=True)
for account in accounts.data:
print(account.number, account.name, account.end_amount) # a Decimal, or None
bank = tasks.list_accounts("demo", filter=[Filter(comparison="eq", field="number", value="1020")])
record = tasks.get_account("demo", bank.data[0].id)
print(record.meta.endpoint, record.meta.request, record.meta.retrieved_at)
# The journal, persons and orders page by offset: limit gives one page, and meta.total
# says how many match; without limit every page is collected.
page = tasks.list_journal_entries("demo", fiscal_period_id=current.id, limit=20)
print(len(page.data), "of", page.meta.total)
entry = tasks.get_journal_entry("demo", page.data[0].id) # with lines and bookings
invoices = tasks.list_orders("demo", type="SALES", fiscal_period_id=current.id)
Every task returns Result[T]: data holds models that mirror CashCtrl's payloads
under upstream's names in snake_case (is_current, end_amount), in Python and in
every tool and route result alike (the report rows of get_report_data excepted, which
come as upstream sends them, and the file tasks' Downloaded, which describes a file;
Files below), meta the upstream operation, the parameters as sent under upstream's
names (onlyActive), the organisation as tenant, when they were fetched and, for a
list, total, upstream's count of the matching records. Async twins are named
<task>_async (list_organisations has none). The tasks are listed in the status table
below. Persons come back without the personal identifiers ssn and iban
(list_persons, get_person, the persons get_journal_entry names; ADR-0017),
locations and an order's document without their bank account numbers (iban and
qr_iban, list_locations; orgIban, orgQrIban and recipientIban,
get_order_document), and report rows without any key named ssn or ending in iban
(get_report_data, which refuses payroll and people reports outright). An API user that
wrote or changed a record shows as API:REDACTED in created_by and last_updated_by,
as in the fixtures; CashCtrl writes API: and the first four characters of its key
there.
MCP
{
"mcpServers": {
"cashctrl": {
"command": "uvx",
"args": ["--from", "xippios-cashctrl[mcp]", "xippios-cashctrl-mcp", "--org", "acme"],
"env": {
"CASHCTRL_ORGS": "acme",
"CASHCTRL_ACME_SUBDOMAIN": "acme",
"CASHCTRL_ACME_API_KEY": "..."
}
}
}
}
--org acme binds the server to one organisation: it stops at startup unless acme is
declared with a well-formed subdomain, its instructions name the organisation, and every
tool acts on acme and takes no org, so no call reaches another organisation;
cashctrl_list_organisations then lists acme only. Without
--org, a server serves every declared organisation and the agent picks one per call,
after cashctrl_list_organisations has named them. Its tools are read-only and named
cashctrl_<verb>_<noun>. Results are capped at 200 rows or 64 KB with a note on how to
narrow the query (cashctrl_list_cost_centers and cashctrl_list_history name their
filters, and a paged list says where to resume); cashctrl_list_custom_fields at 500
rows or 128 KB and cashctrl_get_report_data at 128 KB, since an agent needs them
whole. --http serves
streamable HTTP instead of stdio.
Write tools run in a separate server, xippios-cashctrl-mcp-write (see Write tools
below); every write tool previews its change unless called with confirm=true. It
takes --org too. It carries no authentication, so --http serves it on a loopback
--host (127.0.0.1, localhost, ::1) only; --allow-remote serves it beyond,
behind a gateway that authenticates.
{
"mcpServers": {
"cashctrl-write": {
"command": "uvx",
"args": ["--from", "xippios-cashctrl[mcp]", "xippios-cashctrl-mcp-write", "--org", "acme"],
"env": {
"CASHCTRL_ORGS": "acme",
"CASHCTRL_ACME_SUBDOMAIN": "acme",
"CASHCTRL_ACME_API_KEY": "..."
}
}
}
}
Write tools
Eleven tools create, change and delete journal entries, persons and orders, set the
status of orders and create the payment of orders. They are tasks in
xippios.cashctrl.tasks_write (re-exported from xippios.cashctrl), served by the
write server only: never by the read server, never as an HTTP route.
| Upstream operation | Task function | MCP tool |
|---|---|---|
POST journal/create.json (Create journal entry) |
create_journal_entry |
cashctrl_create_journal_entry |
POST journal/update.json (Update journal entry) |
update_journal_entry |
cashctrl_update_journal_entry |
POST journal/delete.json (Delete journal entries) |
delete_journal_entry |
cashctrl_delete_journal_entry |
POST person/create.json (Create person) |
create_person |
cashctrl_create_person |
POST person/update.json (Update person) |
update_person |
cashctrl_update_person |
POST person/delete.json (Delete people) |
delete_person |
cashctrl_delete_person |
POST order/create.json (Create order) |
create_order |
cashctrl_create_order |
POST order/update.json (Update order) |
update_order |
cashctrl_update_order |
POST order/delete.json (Delete orders) |
delete_order |
cashctrl_delete_order |
POST order/update_status.json (Update status) |
update_order_status |
cashctrl_update_order_status |
POST order/payment/create.json (Create payment) |
create_order_payment |
cashctrl_create_order_payment |
- The confirm gate. Every write tool takes
confirm, last,falseby default. Without it nothing is written: the result is a preview,performed: false, withendpoint,payload(the exact form fields CashCtrl would receive, under upstream's names: booleanstrue/false, datesYYYY-MM-DD, lists as JSON, custom fields as XML;ssnand anibanasREDACTED, as inmeta.requestafter a write),before(for an update or a delete, the record as it is now, as the read tools show it) andchanges(for an update). A create's preview sends no request, nor does a status's or a payment's; an update's or a delete's sends one read and never a write. Withconfirm=truethe write is sent and the result isperformed: truewithinsert_id(the new record's id; an update answers the record's own) and upstream'smessage. Call once withoutconfirm, show the preview, then confirm. Onlyconfirm=Truewrites: from Python anything else ("false",1) previews; over MCP the schema turns"true","yes","1",1into true and"false","no","0",0into false, and refuses anything else. In Python the result isResult[WritePreview[<record>] | WriteResult]; narrow it withisinstanceorif result.data.performed:. - Updates send the whole record. CashCtrl empties every parameter an update leaves
out.
update_journal_entry,update_personandupdate_ordertherefore read the record, apply the parameters given, and send every parameterupdate.jsondocuments, the rest taken from the record. A parameter left out keeps its value: an order's items, too, are sent back as stored, each under the keys the items table documents (account_id,name,unit_price,quantity,tax_id, ...), anditemsgiven replace them whole; upstream stores the items it is sent anew, so their ids change (observed).clearnames parameters to send empty (clear=["tax_id", "notes"]; a flag such asis_vendororis_display_item_grossis sentfalse), and a parameter both given and cleared is refused, as issequence_number_id, which an update sends only when given. Refused withInvalidRequestErrorbefore anything is written, unless the call gives or clears what is missing: a record that gives no value for a mandatory parameter; one holding a list whose shape was never observed (attachments, allocations, bank accounts, children, service periods, insurance contracts, certificate values, an order item's allocations), an address with atitleId, a contact with apurposeor an order item with attachments or marked optional (keys the tables do not document); an insurance whose read shows no insurance numbers or an employee whose read shows nouser_id(the read leaves empty fields out, and these were never seen come back); and a journal entry an order or a salary run booked. A confirmed update reads the record again and recomputes the payload, so it can differ from the preview if the record changed in between. - Deletes take one id; the preview shows the record that would go.
delete_journal_entryreads the entry withconfirm=trueas well and refuses, withInvalidRequestErrorbefore anything is deleted, an entry an order or a salary run booked; an unknown id isNotFoundErrorthere. A person or an order that no longer exists, or an entry deleted between that read and the delete, is refused by upstream (RequestRejected). - Statuses and payments.
update_order_statussets the statusstatus_idon the ordersidsnames;create_order_paymentcreates the payment of the ordersorder_idsnames, dateddate, foramountper order or, without it, every open amount. CashCtrl documents a payment as the payment order for e-banking, a pain.001 file (typePAIN, its default, orSEPA_PAIN) or a PDF (WIRE_PDF,CASH_PDF), which itsorder/payment/downloaddelivers afterwards (not wrapped here). Both send what they are given, nothing read first. A payment creates no book entry, and CashCtrl documents no way to read, list or delete one.PAINneeds the sender's and the recipient's bank accounts and the sender's BIC and refuses a date in the past;CASH_PDFneeded none of them (observed on the demo organisation, 2026-10-29). A status id comes from thestatusof the orders' category incashctrl_list_order_categories. - Custom fields:
custommaps upstream's names (customField1,customField<ID>, the ids fromcashctrl_list_custom_fields) to text, sent as<values><customField1>...</customField1></values>, values escaped. An update keeps every stored value it is not given. - Amounts. A journal
amountwith atax_idis the gross amount, VAT included, and order items'unit_pricewas read as gross too (observed on the demo organisation, although the tax codes' calculation type reads NET;docs/demo-org.md). - Ids come from the read tools: account ids from
cashctrl_list_accounts(theid, not the account number), tax codes fromcashctrl_list_tax_codes, persons fromcashctrl_list_persons, order categories and their statuses fromcashctrl_list_order_categories, currencies fromcashctrl_list_currencies, a person'scategory_idfromcashctrl_list_person_categories, itstitle_idfromcashctrl_list_person_titlesand an employee'slocation_idfromcashctrl_list_locations, an allocation'sto_cost_center_idfromcashctrl_list_cost_centers; the record to update or delete fromcashctrl_list_journal_entries,cashctrl_list_personsorcashctrl_list_orders(theid, not thenr). A journalassociate_idis a person's id; create a new person withcashctrl_create_personfirst (upstream would create one from a name, which the tools do not send). - CashCtrl checks every write and refuses with the fields it objects to, e.g.
error: RequestRejected: CashCtrl rejected the request: debitId: This field cannot be empty.; a refused write changed nothing. A write that meets a server error or a timeout is never repeated (ADR-0011): read back before sending it again.
from datetime import date
from decimal import Decimal
from xippios.cashctrl import tasks_write
from xippios.cashctrl.models import WritePreview, WriteResult
entry = dict(
date_added=date(2026, 10, 24),
amount=Decimal("100.00"), # gross, VAT included, with a tax_id
debit_id=3, # account ids from list_accounts, not account numbers
credit_id=42,
tax_id=9, # from list_tax_codes
title="xippios-live README example", # marked, should it ever run against demo
)
preview = tasks_write.create_journal_entry("demo", **entry)
assert isinstance(preview.data, WritePreview)
print(preview.data.payload) # what CashCtrl would receive; nothing was written
done = tasks_write.create_journal_entry("demo", **entry, confirm=True)
assert isinstance(done.data, WriteResult)
print(done.data.insert_id) # the new entry's id
Files
Five tasks write a file instead of returning records: download_order_document, the
documents of orders as one PDF, and the list exports export_journal_entries,
export_accounts, export_persons and export_orders, each with format (csv,
xlsx or pdf), the filters of the list it mirrors and columns. They are Python
only: no MCP tool and no HTTP route serves them, since no tool hands an agent a file
path (BULK_TASKS, ADR-0019). Each streams the file to dest, the path the caller
gives; nothing is read into the result, kept in memory or cached, and data describes
the file (path, bytes, content_type, filename, retrieved_at). A refusal
raises and writes nothing, and a file already at dest stays as it was:
RequestRejected for one CashCtrl sends as HTTP 200, NotFoundError for an unknown
order id, which CashCtrl answers with HTTP 404.
- Cut at 100. Upstream exports at most
limitrecords, 100 whenlimitis left out (the account export, like its list, takes nolimit): read the list task'smeta.totalfirst and pass alimitof at least that. - Personal identifiers. Without
columns, the person export names the fieldslist_personsreturns as its columns, sossnandibanstay out of the file; a caller that names them incolumnsgets them, deliberately (ADR-0017). An order document is what its recipient gets: an invoice's QR-bill may carry the organisation's IBAN or QR-IBAN and the recipient's name and address. Where a file goes is the caller's choice.
from pathlib import Path
from xippios.cashctrl import tasks
count = tasks.list_journal_entries("demo", fiscal_period_id=2, limit=1).meta.total or 1
journal = tasks.export_journal_entries(
"demo", "csv", Path("journal-2025.csv"), fiscal_period_id=2, limit=count
)
print(journal.data.path, journal.data.bytes, journal.data.content_type)
invoice = tasks.download_order_document("demo", [3], Path("RE-2026-103.pdf"))
HTTP
xippios.cashctrl.http.router is a FastAPI router the consumer mounts. It has no lock:
every route but GET /cashctrl/list_organisations takes org, and the consumer passes
it explicitly on each request. A deployment that must reach one organisation only
declares only that one. A task whose
parameters are all scalars is a GET /cashctrl/<task> with query parameters; the list
tasks that take a filter, a list (list_accounts, list_cost_centers,
list_journal_entries, list_persons, list_orders, list_history), are a POST
with a JSON body
keyed by parameter name.
The MCP entry points quiet httpx's request log; the router does not, so a consumer that
logs at INFO logs httpx's request lines, whose URLs carry the organisation's host (its
subdomain): set the httpx logger to WARNING.
Status
| Upstream operation | Task function | MCP tool | Status |
|---|---|---|---|
| none: the declared organisations | list_organisations |
cashctrl_list_organisations |
available; names only, no request |
GET fiscalperiod/list.json (List fiscal periods) |
list_fiscal_periods |
cashctrl_list_fiscal_periods |
available |
GET currency/list.json (List currencies) |
list_currencies |
cashctrl_list_currencies |
available |
GET tax/list.json (List tax codes) |
list_tax_codes |
cashctrl_list_tax_codes |
available |
GET account/list.json (List accounts) |
list_accounts |
cashctrl_list_accounts |
available; HTTP route is POST |
GET account/read.json (Read account) |
get_account |
cashctrl_get_account |
available |
GET journal/list.json (List journal entries) |
list_journal_entries |
cashctrl_list_journal_entries |
available; paged; HTTP route is POST |
GET journal/read.json (Read journal entry) |
get_journal_entry |
cashctrl_get_journal_entry |
available |
GET person/list.json (List people) |
list_persons |
cashctrl_list_persons |
available; paged; HTTP route is POST |
GET person/read.json (Read person) |
get_person |
cashctrl_get_person |
available |
GET order/list.json (List orders) |
list_orders |
cashctrl_list_orders |
available; paged; HTTP route is POST |
GET order/read.json (Read order) |
get_order |
cashctrl_get_order |
available |
GET order/document/read.json (Read document) |
get_order_document |
cashctrl_get_order_document |
available; layout, sender, recipient, payment references; without orgIban, orgQrIban and recipientIban; the PDF from download_order_document |
GET order/bookentry/list.json (List book entries) |
list_order_book_entries |
cashctrl_list_order_book_entries |
available; one order's (order_id, sent as id) |
GET order/category/list.json (List categories) |
list_order_categories |
cashctrl_list_order_categories |
available |
GET customfield/list.json (List custom fields) |
list_custom_fields |
cashctrl_list_custom_fields |
available; one module (type) a call |
GET person/category/list.json (List categories) |
list_person_categories |
cashctrl_list_person_categories |
available |
GET person/title/list.json (List titles) |
list_person_titles |
cashctrl_list_person_titles |
available |
GET account/category/list.json (List categories) |
list_account_categories |
cashctrl_list_account_categories |
available; flat, linked by parent_id |
GET account/costcenter/list.json (List cost centers) |
list_cost_centers |
cashctrl_list_cost_centers |
available; HTTP route is POST; balances assumed of the current fiscal period |
GET location/list.json (List locations) |
list_locations |
cashctrl_list_locations |
available; without iban and qr_iban |
GET report/tree.json (Get tree of reports) |
get_report_tree |
cashctrl_get_report_tree |
available |
GET report/element/data.json (Read JSON data) |
get_report_data |
cashctrl_get_report_data |
available; rows as upstream sends them; payroll and people reports refused |
GET history/list.json (List history) |
list_history |
cashctrl_list_history |
available; paged; HTTP route is POST |
GET order/document/read.pdf (Download PDF) |
download_order_document |
none, Python only | available; one PDF to dest; an invoice's QR-bill may carry the organisation's IBAN or QR-IBAN and the recipient's address |
GET journal/list.csv, list.xlsx, list.pdf (Export to CSV, Excel, PDF) |
export_journal_entries |
none, Python only | available; a file to dest; at most limit, upstream's default 100 |
GET account/list.csv, list.xlsx, list.pdf (Export to CSV, Excel, PDF) |
export_accounts |
none, Python only | available; a file to dest; every matching account |
GET person/list.csv, list.xlsx, list.pdf (Export to CSV, Excel, PDF) |
export_persons |
none, Python only | available; a file to dest; at most limit, upstream's default 100; without ssn and iban unless columns names them |
GET order/list.csv, list.xlsx, list.pdf (Export to CSV, Excel, PDF) |
export_orders |
none, Python only | available; a file to dest; at most limit, upstream's default 100 |
POST journal/create.json, update.json, delete.json |
create_journal_entry, update_journal_entry, delete_journal_entry |
cashctrl_create_journal_entry, ... |
available on the write server only |
POST person/create.json, update.json, delete.json |
create_person, update_person, delete_person |
cashctrl_create_person, ... |
available on the write server only |
POST order/create.json, update.json, delete.json |
create_order, update_order, delete_order |
cashctrl_create_order, ... |
available on the write server only |
POST order/update_status.json (Update status) |
update_order_status |
cashctrl_update_order_status |
available on the write server only |
POST order/payment/create.json (Create payment) |
create_order_payment |
cashctrl_create_order_payment |
available on the write server only; no book entry, no delete documented |
lang (de, fr, it, en), which upstream takes on every request and which matters
mostly for error messages and exports, is not exposed yet. list_accounts checks dir
(ASC, DESC) and each filter's comparison (eq, like, gt, lt) before
anything is sent, since upstream silently ignores values it does not know; both are
typed as these value sets, so the tool schema lists them. A filter is a Filter or,
from Python, a mapping with the same keys.
The paged lists (list_journal_entries, list_persons, list_orders, list_history)
take start (default 0) and limit. With limit they return one page of at most
limit records from start; without it, every record from start on, fetched 100 at a
time (upstream's documented page size, about 1 s per 100 at the self-imposed pace).
meta.total is upstream's count of every record the request matches. The next page
starts at start plus the number of records received: over MCP the result cap (200 rows
or 64 KB) may return fewer than limit, so never advance by limit. MCP agents should
always pass a limit of about 20. Offset pages over a list that changes meanwhile can
repeat or skip records. Every other list returns its whole answer in one request and
reports upstream's total too.
The journal and order lists answer for the API user's current fiscal period unless
fiscal_period_id is given; that period is server-side state that
fiscalperiod/switch.json changes, and meta.request does not show which period
answered, so pass fiscal_period_id (an id from list_fiscal_periods) for a
reproducible answer. Without type (SALES, PURCHASE), list_orders returns both;
list_order_categories lists SALES (upstream's default) unless given PURCHASE.
list_order_book_entries lists one order's book entries (order_id, sent as upstream's
id): the journal entries its items booked (type GENERATED) and those booked to it
by hand, such as payments, each with its rows; an order in a status that books nothing
has none. list_history is the audit log, newest first: who changed what and when
(created_by, change_type, message), narrowed with order_id, person_id or
statement_id; the history of a deleted order is no longer listed (observed).
get_report_tree lists the organisation's reports, collections of report elements;
get_report_data reads one element (element_id, a balance sheet, a profit and loss
statement, a VAT settlement, ...) for fiscal_period or for start_date to
end_date. Giving the fiscal period and a date is refused before anything is sent:
upstream derives the dates from the period and would ignore the ones given. The report
comes back as upstream sends it (data, the rows, nested; properties, the columns
shown; total), under upstream's camelCase names and with amounts as JSON numbers: the
documentation gives no schema, and the rows differ by report type. Payroll and people
reports, which carry personal data under undocumented names, are refused before their
data is requested: every report whose type (as get_report_tree shows it) starts with
SALARY_ or contains PERSON, or is SETTLEMENT, WITHHOLDING_TAX_SETTLEMENT,
PEOPLE or ORG_CHART; WITHHOLDING_TAX_RATES, rates without persons, is read. The
type comes from the organisation's report tree, read once per
organisation and process and kept; a report the tree does not list is asked of
upstream. Every key named ssn or ending in iban (qrIban, orgIban) is dropped from
what comes back, in any letter case and at any depth.
list_account_categories is the flat account/category/list.json, each category with
its parent_id; account/category/tree.json nests the same categories with display
fields only. list_custom_fields takes the module (type: JOURNAL, PERSON,
ORDER, ...) and refuses any other value; list_cost_centers checks dir and the
filters as list_accounts does.
Upstream terms and attribution
Data comes from CashCtrl (https://cashctrl.com) under its own terms of use;
this package adds no rights to it. Documentation snapshot: docs/upstream/.
Licence
Apache-2.0. See LICENSE.
Metadata
Release files for xippios-cashctrl 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 |
|---|---|---|---|---|
| xippios_cashctrl-0.3.0.tar.gz | 222.4 kB | With provenance | Details for xippios_cashctrl-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| xippios_cashctrl-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for xippios_cashctrl-0.3.0-py3-none-any.whl |
Total release size: 387.3 kB
Release files / xippios_cashctrl-0.3.0.tar.gz
| Download URL | xippios_cashctrl-0.3.0.tar.gz |
|---|---|
| Size | 222.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b994cc29c19be9c128724cb37086bd94eea1a9f90b06a09a70af8a537e0ef6c
|
|
BLAKE2b-256 checksum How to use checksums |
afb9e5720dad2df6507f37800871c8ba771a8971c3392b77e7402cb7b342d242
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logRelease files / xippios_cashctrl-0.3.0-py3-none-any.whl
| Download URL | xippios_cashctrl-0.3.0-py3-none-any.whl |
|---|---|
| Size | 164.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c7c8488e522b388b523d76f1a3d09528b2333a1721bcb5d7968cdff092a2091
|
|
BLAKE2b-256 checksum How to use checksums |
40157656e7244e4aea703564cddc18ef7be734aedfb88904271df55624a019ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logSecurity for xippios-cashctrl 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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for xippios_cashctrl-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.
Transparency logA 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.