diff --git a/bin/simplefinjson b/bin/simplefinjson new file mode 100755 index 000000000..7cdc9fdf5 --- /dev/null +++ b/bin/simplefinjson @@ -0,0 +1,28 @@ +#!/bin/bash +# simplefinjson 1.0 - (c) Simon Michael 2025 +# Download accounts and recent transactions history from SimpleFIN, as JSON. +# +# Requirements: +# a SimpleFIN account with financial institution(s) and app connection configured +# GNU date +# jq to prettify + +# Insert an access token here, acquired with simplefinsetup. +# (Or use a secrets manager, like https://bitwarden.com/help/secrets-manager-quick-start.) +SIMPLEFIN_ACCESS_URL='' + +# Run GNU date, which is gdate on mac. +date() { if hash gdate 2>/dev/null; then gdate "$@"; else date "$@"; fi } + +START=`date +%s -d '-30 days'` + +curl -sL "$SIMPLEFIN_ACCESS_URL/accounts?start-date=$START" | jq + +# https://www.simplefin.org/protocol.html#http-endpoints +# https://www.simplefin.org/protocol.html#get-accounts +# Parameter Required Description +# start-date optional If given, transactions will be restricted to those on or after this Unix epoch timestamp. +# end-date optional If given, transactions will be restricted to those before (but not on) this Unix epoch timestamp. +# pending optional If pending=1 is provided, pending transactions will be included (if supported). By default, pending transaction are NOT included. +# account optional If given, only return information related to the given account id. May be specified multiple times. +# balances-only optional If balances-only=1 is provided, no transaction data is returned. diff --git a/bin/simplefinjson2csv b/bin/simplefinjson2csv new file mode 100755 index 000000000..c3fe143f5 --- /dev/null +++ b/bin/simplefinjson2csv @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# simplefinjson2csv 1.0 - (c) Simon Michael 2025 + +__version__ = "1.0" +__author__ = "Simon Michael" +versionmsg = f"%prog {__version__}, by {__author__} 2025; part of the hledger project." +usagemsg = """%prog [options] [JSONFILE|-] [-] + +Read SimpleFIN /accounts JSON from a JSONFILE or stdin; +write each account's transactions as date-ordered CSV, +to separate CSV files or to stdout. + +Requirements: + python 3 + a SimpleFIN account with financial institution(s) and app connection configured. + +Examples: +$ simplefinjson | simplefinjson2csv +$ simplefinjson >sf.json; simplefinjson2csv sf.json - +""" + +from pprint import pprint as pp +import csv +import datetime +import decimal +import json +import optparse +import re +import sys + +def parse_options(): + parser = optparse.OptionParser(usage=usagemsg, version=versionmsg) + opts, args = parser.parse_args() + if len(args) > 2: + parser.print_help() + sys.exit() + return opts, args + +def main(): + opts, args = parse_options() + with open(args[0],'r') if len(args) > 0 and not args[0]=='-' else sys.stdin as inp: + + i = json.load(inp) + for a in i['accounts']: #[0:1]: + aid = a['id'] + aname = a['name'] + oname = a['org']['name'] + ts = a['transactions'] + if len(args) < 2: + fname = f'sf-{aid}.csv' + out = open(fname,'w') + print(f"writing {len(ts)} transactions to {fname}") + else: + out = sys.stdout + w = csv.writer(out, quoting=csv.QUOTE_ALL) + w.writerow([ + "date", + "id", + "amount", + "description", + "payee", + "memo" + ]) + + for t in reversed(a['transactions']): + dt = datetime.datetime.fromtimestamp(t['posted']) + # dtl = dt.astimezone() + w.writerow([ + dt.strftime('%Y-%m-%d'), # %H:%M:%S %Z'), + t['id'], + t['amount'], + t['description'], + t['payee'], + t['memo'] + ]) + +if __name__ == "__main__": main() diff --git a/bin/simplefinsetup b/bin/simplefinsetup new file mode 100755 index 000000000..d59340fec --- /dev/null +++ b/bin/simplefinsetup @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +# Acquire an access url for SimpleFIN. + +# Insert a setup token here, acquired from the website, then run this script once. +SETUP_TOKEN='' # demo: aHR0cHM6Ly9iZXRhLWJyaWRnZS5zaW1wbGVmaW4ub3JnL3NpbXBsZWZpbi9jbGFpbS9ERU1PLXYyLTM5RTFGQThFM0Y5NjUxNTQ3REZB + +CLAIM_URL="$(echo "$SETUP_TOKEN" | base64 --decode)" +export SIMPLEFIN_ACCESS_URL=$(curl -s -H "Content-Length: 0" -X POST "$CLAIM_URL") +echo $SIMPLEFIN_ACCESS_URL