Skip to main content
Budget plans hold budgets, one per category or category group. Every request reads and writes the default plan unless you pass plan, which takes a plan’s name or id. See the OpenAPI reference for each endpoint’s fields. During the rollout, these endpoints return 404 with NOT_FOUND for accounts that don’t have budgets yet.

Periods

Budgets run monthly. A period is either current or a month written as YYYY-MM. current resolves in the user’s timezone, so the same request can return a different month around midnight on the first. A budget has a startPeriod, the first month it applies to. Editing a month before it returns PERIOD_BEFORE_START. In those months, the category’s spending reports as unbudgeted. Finta computes every status number when you ask for it, so a transaction that arrives late changes that month’s spent and every later month’s rollover. Read status again rather than storing the numbers.

Template and period edits

POST /budgets and PATCH /budgets/{id} require a scope.
  • scope: "template" changes the amount from the current month forward. Past months keep the amount they had, and the response’s snapshot reports how many months Finta wrote down. A month with its own amount keeps it until you set that month again.
  • scope: "period" changes one month and nothing else, and needs period. It can’t create a budget, so set a template first.
budget.amount in a response is always the template amount. A one-month amount is in periodOverride.
POST /budgets returns 201 when it created the budget and 200 when it edited one. created in the body says the same. POST /budgets/reallocate changes only the two budgets’ amounts for that month. It isn’t safe to repeat, so send an Idempotency-Key header if you retry.

Envelope plans

Set method: "envelope" with PATCH /budget-plans/{id}. Changing method changes every past month’s numbers too. In an envelope plan, a month’s planned is only what you assigned with scope: "period", and amount is that month’s total assignment, not an addition. scope: "template" assigns nothing. It sets suggestedAmount in status. Status returns readyToAssign for the current month: the plan’s depository balances minus totals.available minus every payment envelope’s available. It is null for other months and standard plans. It goes negative when you assign more than you have, and that isn’t an error. balancesAsOf is the time of the oldest balance behind it. An overspent envelope shows a negative available this month and resets to 0 next month. The shortfall comes out of readyToAssign.

Credit card payments

Every credit card in an envelope plan’s accounts has one entry in paymentEnvelopes, with or without an assignment. To set money aside, send POST /budgets with the card’s accountId:
A card target takes scope: "period" only. A non-credit account returns ACCOUNT_NOT_CREDIT, a card outside the plan’s accounts returns ACCOUNT_NOT_IN_PLAN, and a standard plan returns METHOD_NOT_ENVELOPE. Finta sorts inflows on a card by category type. An expense category is a refund, and a transfer category is a payment. An income category or no category counts in unrecognizedCardInflows, which is neither. A rule that puts those inflows in a transfer category makes them payments.

Account scope

A plan covers every account (accountScope: "All") or the ones you select ("Selected"). Every number in its status counts only those accounts. Changing a plan’s accounts recomputes every past month too. An API key or OAuth client limited to certain accounts can still read every plan and its totals. Transactions stay limited to the accounts it was granted. When a plan’s totals include other accounts, status returns includesAccountsOutsideConsent: true and names them in accountsOutsideConsent:
A limited key can only build a plan from accounts it may use. Selecting any other account, or asking for every account, returns NOT_FOUND. Account limits apply to which accounts a key can put in a plan, not to the budgets inside it. A limited key can change or delete any budget and any plan, and can assign to any credit card in a plan. These calls change planning numbers only. They move no money and don’t return transactions.

Errors

Errors use the usual { "error": { "code", "message", "requestId" } } body.
  • A bad plan returns 404 with NOT_FOUND, and message lists the user’s plan names.
  • A user without Storage Mode gets 403 with STORAGE_MODE_REQUIRED.
  • A request the budget rules refuse returns 400 with a specific code, such as INSUFFICIENT_PLANNED, DIFFERENT_PLANS or PLAN_NAME_TAKEN. message says what to change.