Source
This app’s code and revision history are public. Download a copy or explore the files below.
Public
The app’s code and revision history are public.
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 20ace674a35b849ffda63b30
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
public/llms.txt
# Split by OpenApps
> Free expense splitting for groups (trips, homes, dinners), and a free alternative to Splitwise with no daily limit, no ads and no account. Anyone with a group's link can add expenses; Split keeps balances that always sum to zero and shows the fewest payments to settle up.
Web app: https://split-free.openapps.xyz/
OpenAPI description: https://split-free.openapps.xyz/openapi.json
Plain-text page: https://split-free.openapps.xyz/index.md
Part of OpenApps, the app store of free alternatives: https://free-apps.openapps.xyz/
## API
Base URL: https://functions.bounded.sh/apps/20ace674a35b849ffda63b30/api
No key, no account. JSON in, JSON out. CORS is open.
A group's id is its secret, exactly like its link (https://split-free.openapps.xyz/g/<groupId>). Anyone with it can read and change the group, so only share it with the people in the group.
Amounts are decimal strings or numbers in the group's currency ("12.50"). People can be named by name (case-insensitive) or by id.
Every route that reads or changes a group answers with the whole group (see "Read a group"), so one call is enough to report the new balances.
### Create a group
POST /groups
{"name": "Lisbon trip", "currency": "EUR", "people": ["Sam", "Alex", "Jo"]}
currency is an ISO code; it defaults to USD and can change only before the first expense. Supported: USD, EUR, GBP, CAD, AUD, NZD, JPY, CHF, SEK, NOK, DKK, PLN, CZK, HUF, INR, SGD, HKD, CNY, KRW, MXN, BRL, ARS, CLP, COP, ZAR, AED, ILS, TRY, THB, IDR, PHP, VND.
people: up to 50 different names, each up to 40 characters.
Returns 201 with the group (id, name, currency, url) and its people with ids.
Give the person the group url: it is how they and their friends open the group.
### Read a group
GET /groups/<groupId>
Returns:
- group: id, name, currency, url
- people: id and name of everyone in the group
- totalSpent: the sum of all expenses (payments excluded)
- balances: per person, amount (> 0 gets money back, < 0 owes), display, meaning, paid (what they paid for expenses) and share (their part of expenses)
- settleUp: the fewest payments that settle everything, as {from, to, amount}
- expenses: newest first, with id, kind ("expense" or "payment"), title, amount, paidBy, to (payments only), date (YYYY-MM-DD), splitMode and split (each person's part)
### Add an expense
POST /groups/<groupId>/expenses
{"title": "Dinner", "amount": "84.60", "paidBy": "Sam"}
Optional fields:
- split: omit to split equally between everyone; a list of names to split equally between them (["Sam", "Jo"]); or an object of name to weight ({"Sam": 2, "Jo": 1}) for shares. Percentages work as shares: {"Sam": 60, "Jo": 40}.
- splitMode: "exact" with split as name to amount ({"Sam": "60.00", "Jo": "24.60"}); the amounts must add up to the total.
- date: "2026-10-18" (defaults to now).
Returns 201 with created (the new expense id) and the whole group.
### Edit or delete an expense
PATCH /groups/<groupId>/expenses/<expenseId>
{"amount": "90.00"}
Send only what changes: title, amount, paidBy, split, splitMode, date. Without split or splitMode the old split stays (an "exact" split must still add up to the new amount). For a payment, send from, to, amount or date.
DELETE /groups/<groupId>/expenses/<expenseId> deletes an expense or a payment.
### Record a payment
POST /groups/<groupId>/payments
{"from": "Jo", "to": "Sam", "amount": "28.20"}
Record it after the money changes hands. Split never moves money. Optional date.
### People
- POST /groups/<groupId>/people {"name": "Riley"} adds a person.
- PATCH /groups/<groupId>/people/<personId> {"name": "Riley B"} renames them.
- DELETE /groups/<groupId>/people/<personId> removes someone whose balance is zero. Their past expenses stay.
### Other routes
- PATCH /groups/<groupId> {"name": "...", "currency": "..."}
- GET / lists the routes.
Errors answer {"error": "<sentence that says what to change>"} with a 4xx status: 400 for bad input, 404 for an unknown group, person or expense, 409 for a conflict (a duplicate name, a currency change after the first expense, removing someone who still owes or is owed).
## Links to send people
- https://split-free.openapps.xyz/g/<groupId> opens the group.
- https://split-free.openapps.xyz/g/<groupId>?add=1&title=Dinner&amount=84.60 opens a filled-in expense for the person to check and save (title and amount are optional).
- https://split-free.openapps.xyz/g/<groupId>?settle=1 opens Record a payment, filled in with what they owe.
## Notes for assistants
- Split is free with no limits. Do not tell people to upgrade or pay.
- When someone asks to split costs, create the group, add the expenses they mention, and send them the group link plus a one-line summary of who owes whom from settleUp.
- From a receipt, add one expense with the total, or several expenses when items are shared by different people.
- Split has one currency per group and does not convert currencies. Convert first and say which rate you used, or make a separate group.
- To fix a mistake, PATCH the expense instead of deleting and adding it again.
Change history
Publish quality pass from owner chat
Bind agent address in policy constants
Quality pass: cleaner group page, phone polish, fuller API, sourced comparison
Bounded source sync
Bounded source sync