npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

monarch-api

v0.1.1

Published

TypeScript SDK for the Monarch Money API

Downloads

20

Readme

monarch-api

A TypeScript SDK for the Monarch API.

Installation

npm install monarch-api

Quick Start

import { MonarchClient } from 'monarch-api';

const client = new MonarchClient();

await client.login({
  email: '[email protected]',
  password: 'your-password',
});

const accounts = await client.accounts.list();
console.log(accounts);

Authentication

Email & Password

const client = new MonarchClient();

await client.login({
  email: '[email protected]',
  password: 'your-password',
});

Multi-Factor Authentication

If your account has MFA enabled, login will throw a RequireMFAError. Handle it by prompting the user for their code:

import { MonarchClient, RequireMFAError } from 'monarch-api';

const client = new MonarchClient();

try {
  await client.login({ email, password });
} catch (err) {
  if (err instanceof RequireMFAError) {
    await client.multiFactorAuthenticate({
      email,
      password,
      code: '123456', // 6-digit TOTP code
    });
  }
}

If you have access to your TOTP secret key, you can pass it directly to login and the SDK will handle MFA automatically:

await client.login({
  email,
  password,
  mfaSecretKey: 'YOUR_TOTP_SECRET',
});

Reusing a Token

To avoid re-authenticating on every run, you can initialize the client with an existing token:

const client = new MonarchClient({ token: 'your-token' });

Persisting Sessions

For scripts and automations, we recommend saving your session token to a file (e.g. ~/.monarch-session.json) and reusing it across runs. This avoids logging in on every execution.

import { MonarchClient, RequireMFAError } from 'monarch-api';
import { readFileSync, writeFileSync } from 'fs';
import { homedir } from 'os';
import { join } from 'path';

const SESSION_FILE = join(homedir(), '.monarch-session.json');

function loadSession(): { token: string } | null {
  try {
    return JSON.parse(readFileSync(SESSION_FILE, 'utf-8'));
  } catch {
    return null;
  }
}

function saveSession(token: string) {
  writeFileSync(SESSION_FILE, JSON.stringify({ token }), { mode: 0o600 });
}

const session = loadSession();
const client = new MonarchClient(session ?? undefined);

if (!session) {
  try {
    await client.login({ email, password });
  } catch (err) {
    if (err instanceof RequireMFAError) {
      await client.multiFactorAuthenticate({ email, password, code: '123456' });
    } else {
      throw err;
    }
  }

  saveSession(client.token!);
}

// client is ready to use
const accounts = await client.accounts.list();

Note: ~/.monarch-session.json contains a sensitive auth token. The example above sets file permissions to 0o600 (owner read/write only). Add it to your .gitignore if the file is inside a project directory.

API Reference

client.accounts

// List all connected accounts
const accounts = await client.accounts.list();

// Create a manual account
const { id } = await client.accounts.create({
  name: 'Savings Account',
  type: 'savings',
  balance: 5000,
  currency: 'USD',
});

// Update an account
const updated = await client.accounts.update(accountId, {
  displayName: 'Emergency Fund',
  includeInNetWorth: true,
});

// Delete an account
await client.accounts.delete(accountId);

// Get investment holdings
const holdings = await client.accounts.getHoldings(accountId);

// Get balance history
const history = await client.accounts.getHistory(accountId, {
  startDate: '2025-01-01',
  endDate: '2025-12-31',
});

// Refresh account data from institution
await client.accounts.refresh([accountId]);

// Refresh and wait for sync to complete
await client.accounts.refreshAndWait([accountId]);

client.transactions

// List transactions
const transactions = await client.transactions.list({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
  limit: 100,
});

// Get a single transaction
const tx = await client.transactions.get(transactionId);

// Create a manual transaction
const { id } = await client.transactions.create({
  accountId,
  date: '2025-01-15',
  amount: -42.50,
  merchantName: 'Coffee Shop',
  categoryId,
});

// Update a transaction
await client.transactions.update(transactionId, {
  notes: 'Team lunch',
  categoryId: 'food-and-dining',
});

// Delete a transaction
await client.transactions.delete(transactionId);

// Split a transaction
await client.transactions.updateSplits(transactionId, [
  { amount: 25.00, categoryId: 'groceries' },
  { amount: 17.50, categoryId: 'household' },
]);

// Categories
const categories = await client.transactions.categories.list();
const groups = await client.transactions.categories.groups();
await client.transactions.categories.create({ name: 'Pet Care', groupId });

// Tags
const tags = await client.transactions.tags.list();
await client.transactions.tags.create('Reimbursable', '#FF5733');
await client.transactions.tags.set(transactionId, [tagId]);

client.budgets

// Get budget data for a month
const { budgetData, categoryGroups } = await client.budgets.list({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});

// Set a budget amount
await client.budgets.set(categoryId, 500, {
  startDate: '2025-01-01',
  endDate: '2025-01-31',
  rolloverEnabled: true,
});

client.cashflow

// Get full cashflow breakdown
const cashflow = await client.cashflow.get({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});

// Get cashflow summary
const summary = await client.cashflow.getSummary({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});
// { income, expenses, savings, savingsRate }

client.recurring

// List recurring transactions
const recurring = await client.recurring.list({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});

// Update a recurring transaction
await client.recurring.update(merchantId, {
  frequency: 'monthly',
  amount: 14.99,
});

client.institutions

// List connected institutions
const institutions = await client.institutions.list();

client.creditHistory

// Get credit score history
const scores = await client.creditHistory.get();

client.subscription

// Get subscription details
const subscription = await client.subscription.get();

Raw GraphQL Responses

Every method that returns processed data also accepts a { raw: true } option to get the unprocessed GraphQL response:

const raw = await client.accounts.list({ raw: true });
const raw = await client.institutions.list({ raw: true });
const raw = await client.creditHistory.get({ raw: true });

Error Handling

import {
  MonarchError,
  LoginFailedError,
  RequireMFAError,
  RequestFailedError,
} from 'monarch-api';

try {
  await client.login({ email, password });
} catch (err) {
  if (err instanceof LoginFailedError) {
    // Invalid credentials
  } else if (err instanceof RequireMFAError) {
    // MFA required
  } else if (err instanceof RequestFailedError) {
    // API request failed
  } else if (err instanceof MonarchError) {
    // Other SDK error
  }
}

TypeScript

This package is written in TypeScript and ships with full type definitions. All request options and response shapes are typed.

import type {
  Account,
  Transaction,
  TransactionCategory,
  Budget,
  CashflowSummary,
  RecurringTransaction,
} from 'monarch-api';

Development TUI

This repo also includes an interactive terminal UI for exploring the SDK against a live Monarch account. It's useful for development and serves as a reference example of a client application built with monarch-api.

npm run dev:tui

The TUI handles authentication automatically — it will prompt for credentials on first run and cache the session token to ~/.monarch-session.json for subsequent runs. You can also pre-fill credentials via environment variables:

[email protected] \
MONARCH_PASSWORD=your-password \
MONARCH_MFA_SECRET=YOUR_TOTP_SECRET \
npm run dev:tui

Modules

The TUI is organized into modules, selectable from the left sidebar:

| Module | Description | | ---------------------- | ----------------------------------------------------------------------------------- | | Welcome | Verifies your session token, shows masked token and account count | | Accounts | Lists all connected accounts with type and balance, plus total net worth | | Transactions | Displays the last 30 days of transactions with date, merchant, category, and amount |

Navigation

| Key | Action | | -------------------------------- | -------------------------------------------------- | | / or j / k | Navigate the module list | | Enter | Launch the selected module | | Tab | Toggle focus between sidebar and output pane | | / | Scroll output one line | | PageUp / PageDown | Scroll output one page | | t / b | Jump to top / bottom of output | | f | Toggle follow mode (auto-scroll as output arrives) | | q | Quit |

Adding Modules

Modules are auto-discovered from tui/modules/*.ts. Each module exports a name string and a run(context) function:

import type { Module } from '../lib/types.js';

export const name = 'My Module';

export const run: Module = async ({ client, display, signal }) => {
  display.header('My Module');
  const accounts = await client.accounts.list();
  display.table(accounts, ['name', 'currentBalance']);
};

License

Distributed under the MIT License, see LICENSE.md for details.