Zero-based envelope budgeting (YNAB-style) via REST API. Track accounts, transactions, categories, budget assignments. Use when user asks about budgeting, expense tracking, "сколько осталось", "куда ушли деньги", account balances, financial planning, debt tracking, Kaspi, transfers, loans, кредиты, рассрочка, личные долги, "кому должен", "кто должен", вклады, депозиты, проценты, КГСС, капитализация.
Zero-based (envelope) budgeting via REST API. Every tenge of income is assigned to a category. Budget balanced when Ready to Assign = 0.
API Base: $PFM_API_URL (e.g. http://localhost:3000)
Auth Header (required when PFM_API_KEY is set):
AUTH="Authorization: Bearer $PFM_API_KEY"
curl -s "$PFM_API_URL/health" | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/accounts" | jq
Returns: { accounts: [{ id, name, type, balanceCents, balanceFormatted, ... }] }
curl -s -X POST "$PFM_API_URL/api/v1/accounts" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"name": "Kaspi Gold",
"type": "checking",
"currency": "KZT"
}' | jq
Types: checking, savings, credit_card, cash, line_of_credit, tracking
Optional metadata: bankName, last4Digits (4 digits), cardType (visa, mastercard, amex, unionpay, mir, other)
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/accounts/{id}" | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/categories" | jq
Returns nested structure: { categoryGroups: [{ id, name, categories: [...] }] }
curl -s -X POST "$PFM_API_URL/api/v1/categories/groups" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"name": "Постоянные расходы"}' | jq
curl -s -X POST "$PFM_API_URL/api/v1/categories" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"groupId": "GROUP_ID",
"name": "Продукты",
"targetType": "monthly_funding",
"targetAmountCents": 8000000
}' | jq
Target types:
none — no goalmonthly_funding — assign X every month (rent, utilities)target_balance — save up to X total (emergency fund)target_by_date — save X by YYYY-MM (vacation)# All transactions
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/transactions" | jq
# Filter by account
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/transactions?accountId={id}" | jq
# Filter by date range
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/transactions?since=2026-02-01&until=2026-02-28" | jq
# Filter by category
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/transactions?categoryId={id}" | jq
curl -s -X POST "$PFM_API_URL/api/v1/transactions" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"accountId": "ACCOUNT_ID",
"date": "2026-02-24",
"amountCents": -850000,
"payeeName": "Magnum",
"categoryId": "CATEGORY_ID",
"memo": "Продукты на неделю"
}' | jq
Income goes to "Ready to Assign" category:
curl -s -X POST "$PFM_API_URL/api/v1/transactions" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"accountId": "ACCOUNT_ID",
"date": "2026-02-01",
"amountCents": 50000000,
"payeeName": "ТОО Работодатель",
"categoryId": "ready-to-assign",
"memo": "Зарплата февраль"
}' | jq
curl -s -X POST "$PFM_API_URL/api/v1/transactions" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"accountId": "SOURCE_ACCOUNT_ID",
"date": "2026-02-15",
"amountCents": -15000000,
"transferAccountId": "TARGET_ACCOUNT_ID",
"memo": "Погашение Kaspi Red"
}' | jq
Note: transfers automatically create TWO paired transactions. No category needed.
curl -s -X DELETE -H "$AUTH" "$PFM_API_URL/api/v1/transactions/{id}" | jq
Soft-deletes. If part of a transfer, deletes both sides.
RTA varies by month. A single month's RTA does NOT account for future assignments. Always use
/rta-overviewto see the true available amount across all assigned months.
Use this INSTEAD of checking a single month's RTA. Shows the real available money considering future assignments.
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/budget/rta-overview" | jq
minReadyToAssignCents is the TRUE available amount — the lowest RTA across
all months with assignments.
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/budget/2026-02" | jq
Returns:
{
"month": "2026-02",
"readyToAssignCents": -8500000,
"readyToAssignFormatted": "-85 000 ₸",
"isOverAssigned": true,
"categoryGroups": [
{
"groupName": "Постоянные расходы",
"categories": [
{
"categoryName": "Аренда",
"assignedCents": 15000000,
"assignedFormatted": "150 000 ₸",
"activityCents": -15000000,
"activityFormatted": "-150 000 ₸",
"availableCents": 0,
"availableFormatted": "0 ₸",
"isOverspent": false
}
]
}
]
}
curl -s -X POST "$PFM_API_URL/api/v1/budget/2026-02/assign" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"categoryId": "CATEGORY_ID",
"amountCents": 8000000
}' | jq
curl -s -X POST "$PFM_API_URL/api/v1/budget/2026-02/move" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"fromCategoryId": "FROM_ID",
"toCategoryId": "TO_ID",
"amountCents": 1000000
}' | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/budget/2026-02/ready-to-assign" | jq
All amounts are in integer cents (tiyns for KZT):
15000000 cents850000 cents1050 centsResponse fields include both raw cents and formatted strings:
balanceCents: 15000000 + balanceFormatted: "150 000 ₸"{
"error": {
"code": "NOT_FOUND",
"message": "Account 'abc123' not found",
"suggestion": "Use GET /api/v1/accounts to list available IDs"
}
}
curl -s -X POST "$PFM_API_URL/api/v1/simulate/payoff" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"debts": [
{"name":"Kaspi Red","type":"installment","balanceCents":45000000,"aprBps":0,"minPaymentCents":15000000,"remainingInstallments":3,"latePenaltyCents":200000},
{"name":"Халық кредит","type":"loan","balanceCents":120000000,"aprBps":1850,"minPaymentCents":8500000}
],
"strategy": "avalanche",
"extraMonthlyCents": 5000000
}' | jq
Strategies: snowball, avalanche, highest_monthly_interest, cash_flow_index
curl -s -X POST "$PFM_API_URL/api/v1/simulate/compare" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"debts": [
{"name":"Kaspi Red","type":"installment","balanceCents":45000000,"aprBps":0,"minPaymentCents":15000000,"remainingInstallments":3,"latePenaltyCents":200000},
{"name":"Халық кредит","type":"loan","balanceCents":120000000,"aprBps":1850,"minPaymentCents":8500000}
],
"extraMonthlyCents": 5000000
}' | jq '.recommended, .savingsVsWorstFormatted'
curl -s -X POST "$PFM_API_URL/api/v1/simulate/debt-vs-invest" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"extraMonthlyCents":5000000,
"debt":{"name":"Халық","type":"loan","balanceCents":120000000,"aprBps":1850,"minPaymentCents":8500000},
"expectedReturnBps":1200,
"horizonMonths":24
}' | jq '.recommendation, .explanation'
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/scheduled?upcoming=7" | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/scheduled" | jq
curl -s -X POST "$PFM_API_URL/api/v1/scheduled" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"accountId": "ACCOUNT_ID",
"frequency": "monthly",
"nextDate": "2026-03-01",
"amountCents": -15000000,
"payeeName": "Арендодатель",
"categoryId": "CATEGORY_ID",
"memo": "Аренда квартиры"
}' | jq
curl -s -X POST -H "$AUTH" "$PFM_API_URL/api/v1/scheduled/process" | jq
curl -s -X POST "$PFM_API_URL/api/v1/scheduled/process" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"asOfDate": "2026-03-01"}' | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/loans" | jq
Returns loans with computed currentDebtCents (principal minus payments).
curl -s -X POST "$PFM_API_URL/api/v1/loans" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"name": "Халық кредит",
"type": "loan",
"accountId": "ACCOUNT_ID",
"categoryId": "CATEGORY_ID",
"principalCents": 200000000,
"aprBps": 1850,
"termMonths": 24,
"startDate": "2025-06-01",
"monthlyPaymentCents": 8500000,
"paymentDay": 25
}' | jq
Types: loan, installment (0% APR like Kaspi Red), credit_line
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/loans/{id}/schedule" | jq
Returns month-by-month breakdown: principal, interest, payment, remaining balance.
curl -s -X PATCH "$PFM_API_URL/api/v1/loans/{id}" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"note": "Досрочное погашение планируется"}' | jq
curl -s -X DELETE -H "$AUTH" "$PFM_API_URL/api/v1/loans/{id}" | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/debts" | jq
# Include settled debts
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/debts?includeSettled=true" | jq
Returns { debts: [...], summary: { totalOweCents, totalOwedCents, netCents, ... } }
# I owe someone
curl -s -X POST "$PFM_API_URL/api/v1/debts" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"personName": "Ансар С.",
"direction": "owe",
"amountCents": 5000000,
"dueDate": "2026-03-15",
"note": "За обед"
}' | jq
# Someone owes me
curl -s -X POST "$PFM_API_URL/api/v1/debts" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"personName": "Марат К.",
"direction": "owed",
"amountCents": 3000000
}' | jq
Directions: owe (я должен), owed (мне должны)
curl -s -X POST -H "$AUTH" "$PFM_API_URL/api/v1/debts/{id}/settle" | jq
curl -s -X PATCH "$PFM_API_URL/api/v1/debts/{id}" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"amountCents": 3000000}' | jq
curl -s -X DELETE -H "$AUTH" "$PFM_API_URL/api/v1/debts/{id}" | jq
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/deposits" | jq
Returns deposits with currentBalanceCents, projectedInterestCents, and formatted versions.
curl -s -X POST "$PFM_API_URL/api/v1/deposits" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"name": "Halyk Срочный 14.5%",
"bankName": "Halyk Bank",
"type": "term",
"initialAmountCents": 100000000,
"annualRateBps": 1450,
"termMonths": 12,
"startDate": "2025-06-01",
"endDate": "2026-06-01",
"capitalization": "monthly"
}' | jq
Types: term (срочный), savings (накопительный), demand (до востребования)
Capitalization: monthly, quarterly, at_end, none (simple interest)
Optional fields: accountId, categoryId, isWithdrawable, isReplenishable, minBalanceCents, topUpCents, earlyWithdrawalRateBps, note
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/deposits/{id}/schedule" | jq
For perpetual deposits (termMonths=0), pass ?months=N (default 12):
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/deposits/{id}/schedule?months=24" | jq
Returns month-by-month: startBalance, interest, capitalized, endBalance, cumulativeInterest.
curl -s -H "$AUTH" "$PFM_API_URL/api/v1/deposits/kdif" | jq
Groups deposits by bank, shows total vs 15M₸ guarantee limit, flags isOverInsured.
curl -s -X POST "$PFM_API_URL/api/v1/simulate/deposit-compare" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"deposits": [
{"name":"Halyk 14.5%","initialAmountCents":100000000,"annualRateBps":1450,"termMonths":12,"capitalization":"monthly"},
{"name":"Kaspi 12%","initialAmountCents":100000000,"annualRateBps":1200,"termMonths":12,"capitalization":"quarterly"}
]
}' | jq '.recommended, .explanation'
curl -s -X PATCH "$PFM_API_URL/api/v1/deposits/{id}" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"topUpCents": 50000000}' | jq
curl -s -X DELETE -H "$AUTH" "$PFM_API_URL/api/v1/deposits/{id}" | jq
GET /api/v1/budget/rta-overview → use minReadyToAssignFormatted as the answer
minMonth != current month, warn: "в текущем месяце RTA = X, но в {minMonth} уже только Y"GET /api/v1/accounts → show balancesGET /api/v1/budget/2026-02 → find "Продукты" → show availableFormattedGET /api/v1/accounts → find the right accountGET /api/v1/categories → find "Кафе" categoryPOST /api/v1/transactions → create expenseTwo options:
a) Transfer between accounts: POST /transactions with transferAccountId
b) Move budget: POST /budget/2026-02/move between categories
GET /api/v1/loans → show currentDebtFormatted for each loanGET /api/v1/loans → find loan IDGET /api/v1/loans/{id}/schedule → amortization tableGET /api/v1/debts → show debts with direction=oweGET /api/v1/debts → find Марат's debt IDPOST /api/v1/debts/{id}/settle → mark as settledGET /api/v1/deposits → show deposits with projected interestGET /api/v1/deposits → find deposit IDGET /api/v1/deposits/{id}/schedule → interest scheduleGET /api/v1/deposits/kdif → check isOverInsured per bankPOST /api/v1/simulate/deposit-compare → compare with schedules