Skip to main content

Bulk currency conversion for Splitwise expenses

Project description

splitwise-fx

Bulk currency conversion for Splitwise expenses.

Pulls a Splitwise group's expenses, converts every foreign-currency line to a target currency at the UnionPay transaction-date rate (the rate Chinese banks actually used to settle), and writes the converted values back via the Splitwise API.

Install

uv tool install splitwise-fx

(Or pipx install splitwise-fx, or any other tool that installs Python CLIs into isolated venvs.)

After install, splitwise-fx is on your PATH.

Setup

Get a Splitwise API key from https://secure.splitwise.com/apps and export it:

export SPLITWISE_API_KEY=your-key-here

(Add to ~/.zshrc / ~/.bashrc to persist. You can also pass --api-key per-invocation, or drop a .env file in the directory you run from.)

Usage

# preview, then prompt y/N to apply
splitwise-fx --group "东京旅行" --to CNY

# preview only — exit without prompting
splitwise-fx --group "东京旅行" --to CNY --dry-run

# skip the prompt (automation)
splitwise-fx --group "东京旅行" --to CNY --yes

# date window
splitwise-fx --group "东京旅行" --to CNY --after 2026-04-01 --before 2026-05-01

# bypass the on-disk rate cache
splitwise-fx --group "东京旅行" --to CNY --no-cache

--group accepts either the group's name (case-insensitive) or its numeric ID. If the name is ambiguous or missing, the CLI lists matches and exits.

How it works

  1. Pulls expenses from the chosen group, paginating Splitwise's API.
  2. For each foreign-currency expense, looks up that day's rate.
  3. Skips settle-up payments and same-currency lines.
  4. Converts cost + each user's paid_share and owed_share using Decimal. Distributes ±0.01 rounding residuals to the largest non-zero shares so sum(paid) == sum(owed) == cost holds (Splitwise rejects updates that violate this).
  5. Renders a Rich preview with rate source per line (UPI or FRA).
  6. On confirm, posts each update via POST /update_expense/{id}, sleeping 1 s between writes.

Rate sources

Source When used Notes
UnionPay (unionpayintl.com/upload/jfimg/{YYYYMMDD}.json) Target currency is one of: AUD CAD CNY EUR GBP HKD HUF JPY MNT MOP NZD SGD THB USD VND Files exist for every day including weekends/CN holidays (Friday rate carries through).
Frankfurter (api.frankfurter.dev/v2/rate/{src}/{dst}) Target outside UnionPay's 15 base currencies, or pair missing from UnionPay file Free, ECB-backed.

Rates are cached on disk under ${XDG_CACHE_HOME:-~/.cache}/splitwise-fx/. Past dates never expire (historical rates are immutable); today's date refreshes every hour.

Caveats

  • Idempotency: re-running with a different --to after a first conversion will re-convert already-converted expenses. The filter only skips lines whose currency_code already matches the target.
  • Settle-up payments are skipped — converting them would corrupt the ledger.
  • Splitwise rate limits are undocumented; the CLI sleeps 1 s between writes and backs off on 429s.

Development

git clone https://github.com/whtsky/splitwise-fx
cd splitwise-fx
uv sync

# linters / type-checker / tests
uv run ruff check
uv run ruff format --check
uv run mypy src tests
uv run pytest

Releasing (maintainer notes)

Releases publish to PyPI via GitHub Actions Trusted Publishing on tag push:

# bump version in pyproject.toml and src/splitwise_fx/__init__.py
git commit -am "release: vX.Y.Z"
git tag vX.Y.Z
git push origin main vX.Y.Z

The release.yml workflow builds with uv build and publishes via pypa/gh-action-pypi-publish. Trusted publishing is configured one-time at https://pypi.org/manage/account/publishing/.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

splitwise_fx-0.0.1.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

splitwise_fx-0.0.1-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file splitwise_fx-0.0.1.tar.gz.

File metadata

  • Download URL: splitwise_fx-0.0.1.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for splitwise_fx-0.0.1.tar.gz
Algorithm Hash digest
SHA256 5060e2c631732ea3cfc5cc4e4f2d84e36b338c356d40e4009e408e0b1ffc6657
MD5 d24e31b88a89587f2b82afd973f809bd
BLAKE2b-256 e85de9f59d719940dbb818b9b30c62c8dbe8557a9a6e817e9a4bc78ed5e50cf8

See more details on using hashes here.

Provenance

The following attestation bundles were made for splitwise_fx-0.0.1.tar.gz:

Publisher: release.yml on whtsky/splitwise-fx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file splitwise_fx-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: splitwise_fx-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 18.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for splitwise_fx-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4e94eadbdcdefcbdc2a831cc17ac0a05694a99e8baad353ce8efe594995f4d8b
MD5 a727433b624e5582ff26433a6eed7c61
BLAKE2b-256 a2ef5145020539e27d814996c37467d5fe1391103c14088945e87e13c2983f31

See more details on using hashes here.

Provenance

The following attestation bundles were made for splitwise_fx-0.0.1-py3-none-any.whl:

Publisher: release.yml on whtsky/splitwise-fx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page