Fiskil’s API does not return historical balances directly—but you can reconstruct them by starting with the current balance and working backward through transaction history.
This guide shows how to generate a running balance after each transaction, using:
/v1/banking/balances
– to retrieve the current balance/v1/banking/transactions
– to retrieve all posted transactionsThis method is accurate to each individual transaction, not just by day.
To reconstruct a running balance timeline:
posting_date_time
descending.This produces an audit-accurate sequence of balance changes.
Example output:
[ { "transaction_id": "txn-1234", "posting_date_time": "2024-09-15T14:30:00Z", "amount": "-50.00", "balance_after": "950.00" }, { "transaction_id": "txn-1233", "posting_date_time": "2024-09-15T10:00:00Z", "amount": "-100.00", "balance_after": "1000.00" } ]
Use the /v1/banking/balances
endpoint:
GET /v1/banking/balances?end_user_id={end_user_id}&account_id={account_id}
This returns the most recent known balance for the account.
Example response:
{ "balances": [ { "account_id": "123456789", "current_balance": "-250.00", "currency": "AUD" } ] }
Use the /v1/banking/transactions
endpoint with a from
date:
GET /v1/banking/transactions?end_user_id={end_user_id}&account_id={account_id}&from=2024-09-02&status=POSTED
Retrieve all POSTED transactions and sort them in descending order by posting_date_time.
const fetch = require('node-fetch'); const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN'; const END_USER_ID = 'your_end_user_id'; const ACCOUNT_ID = 'your_account_id'; const BASE_URL = 'https://api.fiskil.com/v1'; const HEADERS = { 'Authorization': `Bearer ${ACCESS_TOKEN}`, 'Accept': 'application/json; charset=UTF-8', 'Content-Type': 'application/json; charset=UTF-8' }; // Fetch JSON helper async function fetchJSON(url) { const response = await fetch(url, { headers: HEADERS }); if (!response.ok) throw new Error(`HTTP ${response.status} - ${response.statusText}`); return response.json(); } // Step 1: Get current balance async function getCurrentBalance() { const url = `${BASE_URL}/banking/balances?end_user_id=${END_USER_ID}&account_id=${ACCOUNT_ID}`; const data = await fetchJSON(url); return parseFloat(data.balances?.[0]?.current_balance || '0'); } // Step 2: Get all posted transactions async function getAllPostedTransactions() { let transactions = []; let nextPage = null; do { const params = new URLSearchParams({ end_user_id: END_USER_ID, account_id: ACCOUNT_ID, status: 'POSTED', 'page[size]': 100 }); if (nextPage) params.set('page[after]', nextPage); const url = `${BASE_URL}/banking/transactions?${params.toString()}`; const data = await fetchJSON(url); transactions.push(...(data.transactions || [])); const match = data.links?.next?.match(/page\[after\]=([^&]+)/); nextPage = match?.[1] || null; } while (nextPage); // Sort transactions descending by posting_date_time return transactions.sort((a, b) => new Date(b.posting_date_time) - new Date(a.posting_date_time) ); } // Step 3: Build per-transaction balance timeline async function getTransactionBalanceTimeline() { const transactions = await getAllPostedTransactions(); let balance = await getCurrentBalance(); const timeline = transactions.map(tx => { const txAmount = parseFloat(tx.amount); const entry = { transaction_id: tx.transaction_id, posting_date_time: tx.posting_date_time, amount: tx.amount, balance_after: balance.toFixed(2) }; balance -= txAmount; return entry; }); return timeline; } // Run and display the timeline getTransactionBalanceTimeline() .then(timeline => { console.log("Transaction-level balance timeline:"); console.table(timeline); }) .catch(console.error);
Per-transaction precision
Each balance entry corresponds directly to a specific posted transaction, providing an accurate ledger-style timeline.
Extendable structure
You can enrich each timeline entry with additional transaction fields such as:
description
merchant_name
category.primary_category
reference
This can make the balance timeline more informative for audit trails or UIs.
Derive daily or monthly snapshots
If needed, you can group transactions and extract the balance_after
of the last transaction per day or per month to generate high-level trends.
Timezone handling
All posting_date_time
values from the Fiskil API are in UTC. If you're displaying balances in a user-facing product, make sure to adjust for the user's local timezone where appropriate.
Currency consideration
This implementation assumes a single currency per account. If the account includes multi-currency purses
, you'll need to run this logic per currency.
Performance
For high-volume accounts, consider caching results or running this logic as a background job if the full ledger is long. You can also limit by date using the from
/to
parameters on /transactions
to reduce API load.
Was this page helpful?