YNAB File Format - popebp/neat-sheets GitHub Wiki

Summary

Jack Turnbull has done a bunch of RE work on the YNAB file format already, but I am not using it. The RE methodology used is very different from my own. The file formats are basically all JSON, but I want to be able to allow a user to point to their existing YNAB directory and import all of their content magically into Neat Sheets.

The Various Files

  • .ynabSettings.yroot
    • // Probably defines base details for YNAB to understand where to find everything.
  • <BudgetName>~<??>.ynab4
    • Budget Directory
  • Budget.ymeta
    • JSON File
  • Backup_<Year>-<Month>-<Day>T<Hour>-<Min>-<Sec>_<DeviceShort>_<DeviceGUID>.y4backup
    • Zip container that contains .ydiff and .ybsettings files. Additional details provided below. I'm guessing the time is in Zulu/GMT, otherwise it isn't the backup time.
  • data<Id>~<??>
    • Directory containing Device GUID directories and a device metadata directory.
  • Device GUID Directories
    • Contains .ydiff, .ybsettings, and .yfull (optional)
  • device directory
    • Contains .ydevice files
  • <shortDeviceId>.ydevice
    • JSON file defining the device GUID, friendly name, short name, version details, etc.
  • Budget.yfull
    • This is the complete budget database in JSON
  • <CSV>.ydiff
    • Diff output of the JSON files. The name of the file describes what is included in the diff.
  • budgetSettings.ybsettings
    • XML file that defines the settings for the UX.

Items of importance

  • .yroot
  • .ymeta
  • .yfull
  • .ydevice

Formats

yroot

  • TED
    • Number
    • Purpose Unknown
  • relativeDefaultBudgetsFolder
    • String
    • Name of directory containing Budgets
  • formatVersion
    • String
    • YRoot (??) file format version
  • relativeKnownBudgets
    • Array of Strings
    • Relative paths to Budget Directories (.ynab4 folders)

ymeta

  • formatVersion
    • String
    • YMeta (??) file format version
  • relativeDataFolderName
    • String
    • Active Data Folder
  • TED
    • Number
    • ??

yfull

  • masterCategories
    • Array of Objects (referred to as masterCategory)
      • entityType
        • String [masterCategory]
        • Defines the type of entity
      • expanded
        • Boolean
      • name
        • String
        • Category Name
      • type
        • String
        • Type of Category, Looks to be "OUTFLOW" for all of mine
      • deleteable
        • Boolean
        • Whether the category can be deleted or not (False means this is Required for the App to function)
      • subCategories
        • Array of Objects (referred to as category)
          • entityType
            • String [category]
          • note
            • String, Optional
          • name
            • String
            • When the Master Category is __Hidden__, the name has a special format.
          • cachedBalance
            • Number
          • masterCategoryId
            • String
          • isTombstone
            • Boolean
            • Deleted?
          • entityVersion
            • String
          • isResolvedConflict
            • Boolean
          • entityId
            • String
          • sortableIndex
            • Number
        • entityVersion
          • String
        • entityId
          • String
        • sortableIndex
          • Number
  • payees
    • Array of Objects (referred to as payee)
  • monthlyBudgets
    • Array of Objects (referred to as monthlyBudget)
  • fileMetaData
    • Object
      • entityType
        • String [fileMetaData]
        • Defines the type of entity
      • budgetDataVersion
        • String
        • YFull (??) file format version number
      • currentKnowledge
        • String
        • CSV format defining the known data entries for each version.
  • transactions
    • Array of Objects (referred to as transaction)
  • scheduledTransactions
    • Array of Objects (referred to as scheduledTransaction)
  • accountMappings
    • Array of Objects (referred to as accountMapping)
      • entityType
        • String [accountMapping]
      • skipImport
        • Boolean
        • ??
      • hash
        • String
        • Base64 encoded hash result (likely SHA256, given the decoded length is 256-bits)
      • fid
        • String
        • ??
      • dateSequence
        • ?? (mine was null)
        • ??
      • shortenedAccountId
        • String
        • ?? (other than what the name says, it's -S90 in mine...)
      • shouldFlipPayeesMemos
        • Boolean
        • ??
      • salt
        • String
        • Looks like a 256-bit salt for the hash I suspect.
      • targetYNABAccountId
        • String
        • GUID for the account that it updates.
      • shouldImportMemos
        • Boolean
        • ??
      • entityVersion
        • String
        • [DEVICE]-[LASTENTRYID] format. I am guessing this might be the version state on the device when imported. I am going to guess this whole object is related to data import from CSV/QBF/etc for reconciling.
      • entityId
        • String
        • A GUID for referring to this entity
  • budgetMetaData
    • Object
      • entityType
        • String [budgetMetaData]
      • strictBudget
        • String
        • Boolean value of whether this budget is strict or not.
      • currencyISOSymbol
        • ?? (this is null in my file, but I am guessing it defines the Symbol for non-USD currencies)
      • entityVersion
        • String
        • [DEVICE]-[LASTENTRYID] format. Mine is just A-0, so I am not sure of the point of this.
      • currencyLocale
        • String
        • The locale for the currency (mine is en_US). Looks like en_GB for Pound Sterling.
      • budgetType
        • String
        • Setting between "Personal/Family" and "Small Business", which I suspect is Personal and Business respectively.
      • dateLocale
        • String
        • Date format, mine is en_US, others are en_GB
      • entityId
        • String
        • All examples I have seen (a whole 2) this is just A2.
  • accounts
    • Array of Objects
      • entityType
        • String [account]
      • lastReconciledDate
        • String
        • Date of the last time the account was reconciled
      • lastEnteredCheckNumber
        • Number
        • -1 for never entered, otherwise the number
      • lastReconciledBalance
        • Number
        • Balance when last reconciled. This makes it a source of truth (instead of needing to calculate backwards)
      • accountType
        • String
        • "Cash", "Savings", "Checking", etc Defines the account type. I suspect special sauce is added depending on the type. Will need to enumerate the options.
      • hidden
        • Boolean
        • Whether or not the account is hidden in the UI
      • sortableIndex
        • Number
        • ??, maybe a UX thing
      • onBudget
        • Boolean
        • Whether or not this account affects the budget and requires Category when transactions are placed against it.
      • accountName
        • String
        • Displayed name for the account
      • entityVersion
        • String
        • [DEVICE]-[LASTENTRYID] format. Looks like it might be the update state.
      • entityId
        • String
        • Unique GUID for representing the entity.

ydevice

  • deviceGUID
    • String
    • Unique Identifier representing the Device
  • YNABVersion
    • String
    • Version string of the YNAB client
  • shortDeviceId
    • String
    • Character representation of the device (seems to be A, B, C, etc.)
  • formatVersion
    • String
    • YDevice (??) file format version
  • deviceType
    • String
    • Complex String providing details about the device (e.g. iPhone, Desktop, Android). Some more detailed than others
  • highestDataVersionImported
    • String
    • ??
  • friendlyName
    • String
    • Hostname of the device
  • knowledgeInFullBudgetFile
    • String
    • CSV string of data versions for each device in the format of (DEVICE)-(LASTENTRYID)[,(DEVICE)-(LASTENTRYID)]. This is null when hasFullKnowledge is false.
  • hasFullKnowledge
    • Boolean
    • Seems to represent if the device is capable of full knowledge. Desktops are, mobile devices seem to not have full knowledge. This might be a feature thing where if you were to pay for the mobile app maybe you got full features in the app?
  • lastDataVersionFullyKnown
    • String
    • ?? (I'm beginning to suspect this might be the Version of the YFull file format, I guess I will learn more when I get to understanding more of the YFull format).
  • knowledge
    • String
    • Same format as knowledgeInFullBudgetFile, but seems to exist regardless of hasFullKnowledge.
⚠️ **GitHub.com Fallback** ⚠️