Bill splitter and tracker.
Project description
Owe
Owe is a simple web application for splitting bills and tracking who owes whom how much.
Overview
Owe lets a group of users record debts and payments between each other. The Summary tab shows the minimum set of transactions needed to settle all outstanding balances, and provides a one-click Settle button for each.
Core concepts:
- Users - participants identified by email address.
- Records - individual transactions of type
DEBT(someone owes money) orPAYMENT(money has been physically transferred). Records can be cancelled (invalidated) if entered by mistake. - Summary - the net balances across all active records, reduced to the minimum number of settlement transactions using a simple greedy algorithm.
Requirements
- Python 3.10 or later
- uv (recommended) or pip
- (Optional) A Telegram bot token and chat ID for record notifications.
Setup
You can get started with uv:
# Sync dependencies
uv sync
# Run the development server
uv run flask --app owe run
# Or run the production server with gunicorn
uv run gunicorn "owe:create_app()"
Or if you prefer pip:
# Create a virtual environment
python3 -m venv .venv
# Activate the virtual environment
source .venv/bin/activate
# Install dependencies
pip install .
# Run the development server
flask --app owe run
# Or run the production server with gunicorn
gunicorn "owe:create_app()"
App factory customization
The application exposes an app factory, create_app, with two optional
keyword arguments:
url_prefix: Prefix all registered routes (e.g."/owe").api_only: Register only the API blueprint (skip the bundled UI).
For example, to run API-only routes under /owe:
# With Flask
uv run flask --app "owe:create_app(api_only=True, url_prefix='/owe')" run
# With gunicorn
uv run gunicorn "owe:create_app(api_only=True, url_prefix='/owe')"
With this configuration, API endpoints are served under /owe/....
Environment variables
The application can be configured with the following environment variables:
OWE_LOG_LEVEL: Python logging level (DEBUG,INFO,WARNING,ERROR,CRITICAL). Default:INFO.OWE_DATABASE: Path to the SQLite database file. Default:owe.db.OWE_CURRENCY: ISO 4217 currency code displayed in the UI. Default:USD.OWE_REQUEST_EMAIL_HEADER: HTTP header to trust for the authenticated user's email, to be used as the creator of records. When run behind Cloudflare Access, this can be set tocf-access-authenticated-user-emailso that the application can identify the user by their email address. When unset, the remote IP address will be used to identify the user instead. Default: unset.OWE_TELEGRAM_BOT_TOKEN: Telegram bot token for notifications. Default: unset.OWE_TELEGRAM_CHAT_ID: Telegram chat ID for notifications. Default: unset.
Docker
Docker images are available on Docker Hub as
zhongruoyu/owe,
and on GitHub Container Registry as
ghcr.io/zhongruoyu/owe.
The main tag tracks the latest commit on the main branch.
You may run the application with Docker as follows:
docker run -p 8000:8000 \
-v /path/to/data:/data \
-e OWE_DATABASE=/data/owe.db \
-e OWE_CURRENCY=USD \
zhongruoyu/owe:main --bind "0.0.0.0:8000"
The container image runs gunicorn and accepts its command-line arguments, so you
can customize the server configuration (e.g. --bind for socket binding) using
standard gunicorn options; run with --help for details.
API Endpoints
The server exposes the following API endpoints:
GET /api/config: Get application configuration (e.g. currency).GET /api/users: List all users.GET /api/records: List all active and inactive records.POST /api/records: Create a new record. Request body should be JSON with the following fields:type: "DEBT" or "PAYMENT"lender: email of the lenderborrowers: list of emails of the borrowersamount: total amount (will be split evenly among borrowers)remarks: optional remarks for the record
PATCH /api/records/status: Update the status of records. Request body should be JSON with the following fields:ids: list of record IDs to updateactive: boolean indicating whether the records should be active or inactive
GET /api/summary: Get the minimum set of settlement transactions.
Utilities
The package also comes with two command-line utilities:
owe-dump: Dump all records in the database as CSV. Use--outputto set the output file path (default:records.csv); use--databaseto choose the SQLite database file (default:owe.db).owe-users: Manage users from the command line. Use--databaseto choose the SQLite database file (default:owe.db). Usage:owe-users [--database <path>] create <email> <name>: Add a user with the given email and name.owe-users [--database <path>] list: List all users.owe-users [--database <path>] activate <email>: Activate the user with the given email.owe-users [--database <path>] deactivate <email>: Deactivate the user with the given email.
To run these utilities:
# With uv
uv run owe-dump --output records.csv
uv run owe-users --database owe.db list
# With pip, after `pip install .`
owe-dump --output records.csv
owe-users --database owe.db list
License
This project is licensed under the MIT License. See the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file owe-0.1.0.tar.gz.
File metadata
- Download URL: owe-0.1.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f4362edc3e76a2a7e653c67c69658d79415a7493bdf4c682d438cac743e64f9
|
|
| MD5 |
c2c26c0dcdf64c3fdc309e6da21b99c8
|
|
| BLAKE2b-256 |
2754a2ef86a26c1ff5f3f40c0de8668a9270ecef420833ce3a0beaa14257c4b0
|
Provenance
The following attestation bundles were made for owe-0.1.0.tar.gz:
Publisher:
release.yml on ZhongRuoyu/owe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
owe-0.1.0.tar.gz -
Subject digest:
4f4362edc3e76a2a7e653c67c69658d79415a7493bdf4c682d438cac743e64f9 - Sigstore transparency entry: 1704333472
- Sigstore integration time:
-
Permalink:
ZhongRuoyu/owe@355722a806d8994b28f0ab7f04241593d4cb0b08 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ZhongRuoyu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@355722a806d8994b28f0ab7f04241593d4cb0b08 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file owe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: owe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f6f183d073aaf7053405fe51cd60a96e64783d38571dc5da5b983abb18a2709
|
|
| MD5 |
714ab63ae0326b076fdba382e0d924c9
|
|
| BLAKE2b-256 |
f3eddf0e681f88b9b5fff5343f458444fcb89ba09fb62b7b0b593e4b50a3c99b
|
Provenance
The following attestation bundles were made for owe-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ZhongRuoyu/owe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
owe-0.1.0-py3-none-any.whl -
Subject digest:
5f6f183d073aaf7053405fe51cd60a96e64783d38571dc5da5b983abb18a2709 - Sigstore transparency entry: 1704333509
- Sigstore integration time:
-
Permalink:
ZhongRuoyu/owe@355722a806d8994b28f0ab7f04241593d4cb0b08 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ZhongRuoyu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@355722a806d8994b28f0ab7f04241593d4cb0b08 -
Trigger Event:
workflow_dispatch
-
Statement type: