Skip to main content
Build a dashboard that shows a user’s linked accounts, recent transactions, financial health scores, and recurring bills — all from a single API key.

Fetch the overview

Start with GET /me/summary to get accounts, scores, and goals in one call:
import Yoshi from "@yoshi-ai/sdk";

const yoshi = new Yoshi();

const summary = await yoshi.me.summary();

console.log("Accounts:", summary.accounts.total);
console.log("Yoshi Score:", summary.scores?.yoshi);
console.log("Active Goals:", summary.goals.length);
This single call replaces three separate requests to /accounts, /scores, and /goals.

List recent transactions

Fetch the latest transactions across all accounts:
const page = await yoshi.transactions.list({ limit: 20 });

for (const tx of page.data) {
  const direction = tx.cash_flow_direction === "outflow" ? "-" : "+";
  console.log(`${direction}$${tx.amount_absolute} ${tx.counterparty_name}`);
}
Filter by account to show transactions for a specific card or bank account:
curl "https://api.yoshi.ai/transactions?account_id=acc_abc123&limit=10" \
  -H "Authorization: Bearer yoshi_YOUR_KEY"

Show balance history

Plot account balances over time with the balance series endpoint:
const balances = await yoshi.accounts.balanceSeries.list("acc_abc123", {
  days: 30,
});

for (const point of balances.points) {
  console.log(`${point.date}: $${point.balance}`);
}

Add recurring streams

Show subscriptions, bills, and income streams:
const recurring = await yoshi.recurring.list();

const bills = recurring.streams.filter(
  (s) => s.direction === "outflow" && s.is_active
);
const income = recurring.streams.filter(
  (s) => s.direction === "inflow" && s.is_active
);

console.log(`${bills.length} active bills, ${income.length} income streams`);

Caching strategy

Not all data changes at the same rate:
ResourceCache durationWhy
Accounts metadata5–15 minutesNames and types rarely change
BalancesDo not cacheChanges with every sync
Transactions1–5 minutesNew transactions arrive periodically
Scores1 hourRecalculated daily
Recurring streams1 hourUpdated infrequently
Use webhooks instead of polling. Subscribe to transaction.created and balance.updated events to refresh your dashboard in real time.

Polling vs webhooks

For a simple dashboard, poll on a timer:
setInterval(async () => {
  const summary = await yoshi.me.summary();
  updateUI(summary);
}, 60_000); // every 60 seconds
For real-time updates, register a webhook endpoint and listen for events:
app.post("/webhooks/yoshi", async (req, res) => {
  const event = req.body;

  if (event.type === "transaction.created") {
    await refreshTransactions(event.data.account_id);
  } else if (event.type === "balance.updated") {
    await refreshBalances(event.data.account_id);
  }

  res.sendStatus(200);
});

Handle pending transactions

Transactions can arrive in a pending state before they post:
const page = await yoshi.transactions.list({ limit: 50 });

const posted = page.data.filter((tx) => !tx.pending);
const pending = page.data.filter((tx) => tx.pending);
Pending transactions may change amount, date, or even disappear before posting. Always use the transaction id for deduplication — don’t rely on amount or description matching.

What’s next

Webhooks

Set up real-time updates instead of polling.

Data freshness

Understand when and how data syncs.
Last modified on April 30, 2026