Skip to content

Instantly share code, notes, and snippets.

@ConnorGriffin
Last active October 22, 2024 22:38
Show Gist options
  • Save ConnorGriffin/faffa47631f77cde5829718123c859f7 to your computer and use it in GitHub Desktop.
Save ConnorGriffin/faffa47631f77cde5829718123c859f7 to your computer and use it in GitHub Desktop.
Automatically update your YNAB 'Home Value' tracking account with Zillow's Zestimate data
function updateYnabHomeZestimate() {
var accessToken = 'YNAB token goes here' // Your YNAB Personal Access Token
var zwsid = 'zwsid goes here' // Your Zillow ZWSID
var budgetName = 'budget name goes here' // The name of your budget
var accountName = 'home value account name goes here' // The name of your home value tracking account
var address = '1657 Notrealaddress Drive, Redding, CA 96001' // Home address
// YNAB API settings
var url = 'https://api.youneedabudget.com/v1'
var headers = {
"Authorization": "Bearer " + accessToken,
"Content-Type":"application/json; charset=utf-8"
}
// Get all budgets, find our budget by name
var budgets = JSON.parse(UrlFetchApp.fetch(url + '/budgets', {'headers': headers})).data.budgets
var budget = findObjectByKey(budgets, 'name', budgetName)
// Get all accounts in the budget, find our home value tracking account by name
var accountsUrl = url + '/budgets/' + budget.id + '/accounts'
var accounts = JSON.parse(UrlFetchApp.fetch(accountsUrl, {'headers': headers})).data.accounts
var account = findObjectByKey(accounts, 'name', accountName)
var accountValue = account.balance / 1000
// Get the zestimate
var zestimate = parseFloat(getDeepSearchResults(zwsid,address).getChild('zestimate').getChild('amount').getValue())
// If the totals don't match, update the value in YNAB
if (zestimate != accountValue) {
var transactionData = {
'transaction': {
'account_id': account.id,
'date': Utilities.formatDate(new Date(), "UTC", "yyyy-MM-dd"),
'amount': ((zestimate - accountValue) * 1000).toString(),
'payee_name': 'Zestimate Automation',
'memo': 'Entered automatically by Google Apps Script automation',
'cleared': 'cleared',
'approved': true
}
}
var options = {
'method': 'post',
'payload': JSON.stringify(transactionData),
'headers': headers
}
var transactionUrl = url + '/budgets/' + budget.id + '/transactions'
var result = UrlFetchApp.fetch(transactionUrl, options)
}
}
// Function to retrieve detailed
function getDeepSearchResults(zwsid, address) {
var addressArray = splitAddress(address)
var endpoint = 'http://www.zillow.com/webservice/GetDeepSearchResults.htm'
var params = [
'zws-id='+zwsid,
'address='+addressArray['address'],
'citystatezip='+addressArray['cityStateZip']
]
var requestUri = endpoint.concat("?", params.join('&'))
var xmlData = XmlService.parse(UrlFetchApp.fetch(requestUri).getContentText())
var rootElement = xmlData.getRootElement()
var result = rootElement.getChild('response').getChild('results').getChild('result')
return result
}
// Function to convert an address into an array for Zillow API usage
function splitAddress(address) {
var addressArray = address.split(',')
return {
'address': addressArray[0].trim(),
'cityStateZip': ''.concat(addressArray[1].trim(),', ', addressArray[2].trim())
}
}
// Function to find objects in an array of objects by key value
function findObjectByKey(array, key, value) {
for (var i = 0; i < array.length; i++) {
if (array[i][key] === value) {
return array[i];
}
}
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment