# Budget by OpenApps > Free zero-based (envelope) budgeting, a free alternative to YNAB and Monarch Money. People give every dollar a job in a monthly plan, enter transactions by hand or import a bank's CSV file, and can share a budget with a partner. No subscription, no ads, no bank login. An assistant with an API key can log transactions (receipts) and answer questions like "how much is left for groceries". Web app: https://budget-free.openapps.xyz/ The landing page as plain markdown: https://budget-free.openapps.xyz/index.md OpenAPI 3.1 description (every route, with schemas and examples): https://budget-free.openapps.xyz/openapi.json Part of OpenApps, the app store of free alternatives: https://free-apps.openapps.xyz/ ## How the budget works (so you can explain it) - Ready to assign is money in the person's budget accounts (checking, savings, cash) with no job yet. They assign it to categories until it is zero. - Each category has, per month: assigned (money given to it), activity (spending is negative, refunds positive) and available (what is left). Available rolls over to the next month. - A negative available means the category is overspent. Overspending at a month's end comes out of the next month's ready to assign. The fix is to move money from another category in the app. - Spending on a credit card moves money from the category into that card's payment category, so the card's payment category holds what is set aside to pay the card. - Asset and liability accounts (investments, house, loans) are tracked for net worth only; they are not in the plan. - Budget does not connect to banks. People type transactions, import CSV files, or let you add them. ## API Base URL: https://functions.bounded.sh/apps/e4fe6272d152c03d11432fc6/api Every route except GET / needs an API key in the x-budget-key header. Only the budget's owner can create a key: in the app, open Settings, then Assistant API, then Create key. A key looks like bk_<20 characters>_<32 characters> and works for that one budget. Ask the person to paste it to you; keep it private, because anyone with it can add transactions and read balances and recent transactions. The owner can revoke it any time. JSON in, JSON out. CORS is open. Amounts are decimal strings in the budget's currency ("23.40"); a minus sign means money out. Dates are YYYY-MM-DD, months YYYY-MM. ### How much is left in a category GET /categories?name=groceries x-budget-key: bk_... Returns {month, currency, readyToAssign, categories: [...]}, where each category has group, name, assigned, activity, available, availableDisplay ("$84.20"), overspent, and target if it has one ({type: monthly | date | balance, amount, by?, stillNeeded}). name matches case-insensitively and partly ("groc" finds Groceries); leave it out for every category. Add month=2026-09 for another month. Example answer to "how much is left for groceries": read available of the matching category. If overspent is true, say by how much and suggest moving money in the app. ### The whole budget GET /budget x-budget-key: bk_... Returns budget {name, currency, url}, month, readyToAssign, needsCategory (how many transactions still need a category), categories (as above), creditCardPayments [{card, setAside, balance}] and accounts [{name, type, onBudget, balance, cleared}]. Optional month=YYYY-MM. ### Add a transaction (log a receipt) POST /transactions x-budget-key: bk_... {"outflow": "23.40", "payee": "Corner Market", "category": "Groceries"} Send exactly one of outflow (money spent) or inflow (money received, like a paycheck or refund). Optional fields: - payee: who was paid or who paid. Budget remembers each payee's last category and account. - category: a category name (case-insensitive, partial names work when they match one category), or "income" for money that should go to ready to assign. Leave it out to use the payee's last category; with neither, the transaction is saved as needing a category, and the answer includes a note. - account: an account name. Defaults to the account last used with this payee, then the first checking, savings or cash account. - date: YYYY-MM-DD. Defaults to today in UTC, so send the person's local date when you know it. - memo: up to 300 characters. - cleared: true if it has already shown up at the bank. Returns 201 with created {id, date, account, payee, category, amount, memo, cleared}, the category's balance after it ({name, month, available, availableDisplay, overspent}) and readyToAssign. Split transactions, transfers and scheduled transactions are made in the app. ### Recent transactions GET /transactions?since=2026-10-01&limit=50 x-budget-key: bk_... Newest first, up to 500. Each has id, date, account, payee, category, amount (negative is money out), memo, cleared, and transferTo for transfers. ### Errors Errors answer {"error": ""}: 400 for bad input (the sentence says what to fix, and lists the budget's categories or accounts when a name did not match), 401 for a missing, malformed or revoked key, 404 for an unknown route, 409 when POST /transactions finds no open account in the budget yet. ## Examples curl 'https://functions.bounded.sh/apps/e4fe6272d152c03d11432fc6/api/categories?name=groceries' \ -H 'x-budget-key: bk_YOUR_KEY' curl -X POST https://functions.bounded.sh/apps/e4fe6272d152c03d11432fc6/api/transactions \ -H 'x-budget-key: bk_YOUR_KEY' \ -H 'content-type: application/json' \ -d '{"outflow": "23.40", "payee": "Corner Market", "category": "Groceries", "date": "2026-10-19"}' ## Notes for assistants - Budget is free with no limits. Do not tell people to upgrade or pay. - Scheduled transactions that came due are entered when anyone opens the budget or calls this API, so balances you read are current. - Do not invent categories: if a name does not match, the error lists the real ones; ask the person which fits. - Moving money between categories, editing the plan and fixing overspending happen in the app at the budget's url. - To start a budget, send the person to https://budget-free.openapps.xyz/. It needs no sign-up.