Skip to content

Latest commit

 

History

35 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Monarch Go Client

CI codecov Go Report Card GoDoc License

A production-grade Go client library for the Monarch API, providing a clean, idiomatic interface for managing personal finances programmatically.

Features

  • 🔐 Full Authentication Support - Login, MFA, TOTP, and session management
  • 📊 Complete API Coverage - Accounts, transactions, budgets, and more
  • 🚀 High Performance - Concurrent operations, connection pooling, and smart caching
  • 🛡️ Production Ready - Comprehensive error handling, retries, and rate limiting
  • 🧪 Well Tested - Extensive test coverage with mocked responses
  • 📝 Fully Documented - Complete GoDoc documentation and examples

Installation

go get github.com/eshaffer321/monarch-go/v2

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/eshaffer321/monarch-go/v2/pkg/monarch"
)

func main() {
    // Create client
    client, err := monarch.NewClient(&monarch.ClientOptions{
        // Option 1 (recommended): browser session cookie — see Authentication below
        // Cookie: "sessionid=...; csrftoken=...",

        // Option 2: bearer token
        Token: "your-auth-token",
    })
    if err != nil {
        log.Fatal(err)
    }
    
    ctx := context.Background()
    
    // Get all accounts
    accounts, err := client.Accounts.List(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    for _, account := range accounts {
        fmt.Printf("%s: $%.2f\n", account.DisplayName, account.CurrentBalance)
    }
}

Authentication

Cookie Auth (recommended)

Monarch's web app now authenticates with an HttpOnly session cookie, and scripted username/password logins are frequently blocked by bot protection. A browser-copied session cookie is the most reliable way to authenticate a script today, and reportedly lasts much longer than a bearer token (~60 days per community reports — not confirmed against Monarch's own docs).

How to get it:

  1. Log in to https://app.monarch.com in your browser (check "Stay signed in" if offered)
  2. Open DevTools → Network, and find any request to api.monarch.com/graphql
  3. Copy the full Cookie request header (it includes sessionid=...; csrftoken=...)
client, err := monarch.NewClient(&monarch.ClientOptions{
    Cookie: "sessionid=...; csrftoken=...", // paste the full Cookie header here
})

Cookie auth takes precedence over Token when both are set.

Bearer Token

client, err := monarch.NewClient(&monarch.ClientOptions{
    Token: "your-auth-token",
})

Login with Credentials

⚠️ Scripted login is currently unreliable — Monarch's bot protection blocks many automated /auth/login/ requests. Prefer cookie auth above. This is kept for accounts/flows where it still works.

client, _ := monarch.NewClient(&monarch.ClientOptions{})

// Basic login
err := client.Auth.Login(ctx, "email@example.com", "password")

// Login with MFA
err := client.Auth.LoginWithMFA(ctx, "email@example.com", "password", "123456")

// Login with TOTP secret
err := client.Auth.LoginWithTOTP(ctx, "email@example.com", "password", "TOTP_SECRET")

Session Management

// Save session to file
err := client.Auth.SaveSession("~/.monarch_session.json")

// Load session from file
err := client.Auth.LoadSession("~/.monarch_session.json")

// Use session file automatically
client, _ := monarch.NewClient(&monarch.ClientOptions{
    SessionFile: "~/.monarch_session.json",
})

Services

Accounts

// List all accounts
accounts, err := client.Accounts.List(ctx)

// Get account details
account, err := client.Accounts.Get(ctx, "account-id")

// Create manual account
account, err := client.Accounts.Create(ctx, &monarch.CreateAccountParams{
    Type:           monarch.AccountTypeCredit,
    Name:           "My Credit Card",
    CurrentBalance: -1500.00,
})

// Refresh accounts
job, err := client.Accounts.Refresh(ctx, "account-id-1", "account-id-2")
err = job.Wait(ctx, 30*time.Second)

Transactions

// Query transactions with filters
result, err := client.Transactions.Query().
    Between(startDate, endDate).
    WithAccounts("account-id").
    WithCategories("category-id").
    WithMinAmount(100).
    Execute(ctx)

// Get transaction details
transaction, err := client.Transactions.Get(ctx, "transaction-id")

// Update transaction
err := client.Transactions.Update(ctx, "transaction-id", &monarch.UpdateTransactionParams{
    Category: "new-category-id",
    Notes:    "Updated note",
})

// Stream transactions for real-time updates
txnChan, errChan := client.Transactions.Stream(ctx, startDate, endDate)
for {
    select {
    case txn := <-txnChan:
        fmt.Printf("New transaction: %s - $%.2f\n", txn.Merchant, txn.Amount)
    case err := <-errChan:
        log.Printf("Stream error: %v", err)
    }
}

Budgets

// Get all budgets
budgets, err := client.Budgets.List(ctx)

// Update budget amount
err := client.Budgets.SetAmount(ctx, "budget-id", 500.00)

// Get budget details with spending
budget, err := client.Budgets.Get(ctx, "budget-id")
fmt.Printf("Spent $%.2f of $%.2f\n", budget.ActualAmount, budget.PlannedAmount)

Cash Flow

// Get cash flow summary
summary, err := client.Cashflow.GetSummary(ctx, startDate, endDate)
fmt.Printf("Income: $%.2f, Expenses: $%.2f\n", summary.Income, summary.Expenses)

// Get detailed cash flow by category
details, err := client.Cashflow.GetByCategory(ctx, startDate, endDate)

Advanced Features

Rate Limiting

import "golang.org/x/time/rate"

client, _ := monarch.NewClient(&monarch.ClientOptions{
    RateLimiter: rate.NewLimiter(rate.Every(time.Second), 10), // 10 requests/second
})

Retry Configuration

client, _ := monarch.NewClient(&monarch.ClientOptions{
    RetryConfig: &monarch.RetryConfig{
        MaxRetries: 3,
        RetryWait:  1 * time.Second,
        MaxWait:    10 * time.Second,
    },
})

Hooks for Observability

client, _ := monarch.NewClient(&monarch.ClientOptions{
    Hooks: &monarch.Hooks{
        OnRequest: func(ctx context.Context, req *http.Request) {
            log.Printf("Request: %s %s", req.Method, req.URL)
        },
        OnResponse: func(ctx context.Context, resp *http.Response, duration time.Duration) {
            log.Printf("Response: %d in %v", resp.StatusCode, duration)
        },
        OnError: func(ctx context.Context, err error) {
            log.Printf("Error: %v", err)
        },
    },
})

Examples

See the examples directory for complete working examples:

Development

Prerequisites

  • Go 1.20 or higher
  • Make

Building

# Run tests
make test

# Build binary
make build

# Run linter
make lint

# Format code
make fmt

Project Structure

monarch-go/
├── pkg/monarch/       # Public API package
├── internal/          # Internal implementation
│   ├── auth/         # Authentication logic
│   ├── graphql/      # GraphQL queries and loader
│   └── transport/    # HTTP/GraphQL transport
├── cmd/              # Command-line tools
├── examples/         # Usage examples
└── tests/           # Integration tests

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. See our Contributing Guidelines for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Disclaimer

This is an unofficial client library and is not affiliated with Monarch. Use at your own risk.

Acknowledgments

About

Production-grade Go client library for the Monarch API - budgets, transactions, accounts with full authentication support

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Contributors

Languages