spec

Asset Notation Specification - Version 0.1.0

Status: DRAFT. The data model is exercised against real data before any v1.0. Nothing here is frozen until v1.0.

1. Purpose and scope

Asset Notation is an open, portable data format for a person’s or household’s assets and liabilities over time: the accounts, positions, properties, debts and their values, across institutions and asset classes, in a single self-describing document that any application can read and write. The consolidated net worth is one thing it makes derivable, but the format itself is the broader notation: it records what you own and owe, not a dashboard.

It exists to fill a concrete gap: today wealth data is locked inside each aggregator and institution, with no neutral interchange format. Asset Notation is the neutral payload. It does not replace bank-messaging standards (ISO 20022) or brokerage feeds; it consolidates their outputs into one portable picture the owner controls.

In scope (v0.1): subjects/owners, institutions, holdings (the single generic asset-or-liability entity), optional instruments for market-priced positions, valuations over time, optional transactions, ownership shares.

Out of scope (v0.1): market-data/FX rate distribution, tax computation, budgeting categories, performance analytics, real-time messaging. These belong in tools or in namespaced extensions, not in the core.

2. Design principles

  1. One generic entity. Anything you own or owe is a Holding - a bank account, a savings book, a brokerage position, a house, a car, a mortgage. An open kind says what flavour it is; a nature (asset or liability) says which side of the balance sheet it sits on. There is no separate account / holding / liability hierarchy to learn or to migrate.
  2. Reuse existing identifiers; never invent. Currencies, dates, securities, institutions and accounts are referenced through established ISO standards.
  3. Model facts, not dashboards. The document stores what is true (a holding, a value as of a date). “Net worth at time T” is derived, never stored.
  4. Valuation is first-class, time-stamped and sourced. A value always carries its as-of date and where it came from, because wealth includes illiquid, subjectively-valued assets, and because the value of everything moves.
  5. Money is never a float. Amounts are decimal strings with an explicit currency.
  6. Forward-compatible and extensible. Unknown fields and unknown kind / source values are preserved, not rejected. App-specific data lives in namespaced extensions, keeping the core small. New kinds and new fields never force a migration.
  7. Privacy by construction. The document is plaintext; confidentiality is the container’s job (section 11). Any subset of a document is still valid, so partial disclosure is natural.
  8. Human-inspectable. Plain JSON: diffable, greppable, hand-editable.

3. Conventions

4. Document structure

A document is a single JSON object:

{
  "assetnotation": "0.1.0",
  "generatedAt": "2026-06-24T20:00:00Z",
  "generator": { "name": "example", "version": "1.0.0" },
  "baseCurrency": "EUR",
  "subjects": [],
  "institutions": [],
  "holdings": [],
  "instruments": [],
  "valuations": [],
  "transactions": [],
  "ownership": [],
  "extensions": {}
}
Field Req Type Notes
assetnotation MUST string Spec version major.minor.patch of this document.
generatedAt MUST timestamp When the document was produced.
generator MAY object { name, version } of the producing app.
baseCurrency SHOULD ISO 4217 Reporting currency for derived totals.
subjects SHOULD Subject[] Owners. If omitted, a single implicit owner is assumed.
institutions MAY Institution[] Banks, brokers, lenders.
holdings MUST Holding[] The assets and liabilities. The heart of the document.
instruments MAY Instrument[] Market-priced securities referenced by holdings.
valuations SHOULD Valuation[] Time-stamped values of holdings.
transactions MAY Transaction[] Optional movement history.
ownership MAY Ownership[] Shares. Defaults to 100% to the primary subject.
extensions MAY object Namespaced app-specific data (section 10).

Collections are unordered sets keyed by id. This maps directly onto a schema-agnostic store of named collections (section 12).

5. Core entities

5.1 Subject (owner)

A person or legal entity that can own assets and owe liabilities.

Field Req Type Notes
id MUST string  
type MUST enum person, entity.
name SHOULD string Display name.
kind MAY enum e.g. self, spouse, child, company, trust, sci, joint. Open.
country MAY ISO 3166 Tax residence or registration.
ids MAY object e.g. { "lei": "..." } for legal entities.

5.2 Institution

A bank, broker, insurer, exchange, custodian or lender.

Field Req Type Notes
id MUST string  
name SHOULD string  
kind MAY enum bank, broker, insurer, exchange, custodian, other.
country MAY ISO 3166  
ids MAY object { "bic"?: ISO 9362, "lei"?: ISO 17442 }.

5.3 Holding (the generic entity)

Anything of value, owned or owed. A bank account, a savings book, a brokerage position, a directly-held house or car, a mortgage or a consumer loan are all Holdings. Its values over time are Valuations (5.5); its movements, if any, are Transactions (5.6).

Field Req Type Notes
id MUST string  
kind MUST string Open: checking, savings, brokerage, retirement, life_insurance, crypto_wallet, cash, real_estate, vehicle, valuable, mortgage, loan, credit_line… A consumer MUST accept an unknown kind and render it generically.
nature MUST enum asset or liability. Drives the sign in net worth.
label SHOULD string Display name.
currency SHOULD ISO 4217 The holding’s native currency.
parentId MAY ref The containing holding (a stock in a fund, a fund in a securities account). A holding with no parent is a root.
institutionId MAY ref -> Institution.
ids MAY object { "iban"?: ISO 13616, "bic"?, "number"? }. number SHOULD be masked.
instrumentId MAY ref -> Instrument, for a market-priced position.
quantity MAY decimal string Units held, when instrumentId is set.
links MAY Link[] Relations to other holdings (below).
attributes MAY object Type-specific scalars the core does not model (a loan’s rate, a property’s address…). Forward-compatible: producers put extra kind-specific data here, not in core fields.
openedAt / closedAt MAY date  

A Link is { "rel": string, "holdingId": ref }. rel is an open vocabulary: funded_by (a card -> its account), financed_by (a property -> its mortgage), held_in (a position -> its account). Links express the relationships a 360 view needs without nesting.

Sign convention: a holding’s values are its native signed amounts. An account-style holding carries a signed balance (a negative balance is an overdraft or a card debt, and lowers net worth on its own). A loan-style holding carries a positive outstanding and is marked nature: "liability", so net worth subtracts it. This keeps both representations consistent (section 6).

5.4 Instrument (optional)

A market-priced thing referenced by a holding, so the shared price lives once. Only needed for securities and similar; a house is just a holding with a value.

Field Req Type Notes
id MUST string  
name SHOULD string  
kind MUST enum security, cash, crypto, commodity, other.
ids MAY object { "isin"?: ISO 6166, "figi"?, "ticker"?, "mic"?: ISO 10383 }.
currency MAY ISO 4217 Pricing currency.

5.5 Valuation

The value of a holding, as of a date, from a stated source. Valuations form a time series; multiple per holding are expected (a statement each month, an appraisal each year, the amortized balance of a loan over its life).

Field Req Type Notes
id MUST string  
holdingId MUST ref -> Holding.
asOf MUST date/timestamp When the value held true.
value MUST Money The total value of the holding (signed per 5.3).
unitPrice MAY Money For an instrument-priced holding: price per unit.
source SHOULD string Open: purchase, statement, market, estimate, appraisal, repayment, manual, derived…
confidence MAY number 0..1. An estimate is softer than a statement.

5.6 Transaction (optional)

A movement on a holding. Optional: a document MAY carry valuations only. Semantics align loosely with ISO 20022 / OFX.

Field Req Type Notes
id MUST string  
holdingId MUST ref -> Holding.
date MUST date  
amount MUST Money Signed: negative = outflow, positive = inflow.
type MAY enum transfer, trade, fee, dividend, interest, income, expense, other.
description MAY string  
category MAY string Open budgeting category.
counterpartHoldingId MAY ref The other side of the flow: a transfer target, the loan repaid, the asset funded.
instrumentId / quantity MAY ref / decimal string For trades.

5.7 Ownership (shares)

Who owns how much of what. Enables joint accounts, family consolidation and holding structures. If ownership is omitted, every holding is owned 100% by the primary subject.

Field Req Type Notes
subjectId MUST ref -> Subject.
holdingId MUST ref -> Holding.
share MUST number 0..1. Shares of one holding SHOULD sum to <= 1.

6. Deriving net worth (non-normative)

A standard models facts; tools compute. Net worth for a set of subjects S as of date T:

netWorth(S, T) =
    sum over ROOT holdings h (no parentId) of
        sign(h.nature) * treeValue(h, T) * ownedShare(h, S)
  where treeValue(h, T) = the sum of treeValue over h's children, or h's own
  latestValue(h, T) when it has none; sign(asset) = +1, sign(liability) = -1; all
  converted to baseCurrency using an FX rate as of T.

A container (a fund, a securities account) is therefore counted through its children, never twice.

latestValue(h, T) is the value of the valuation of h with the greatest asOf <= T. A richer tool MAY refine an account’s value between statements using its transactions; this reference derivation uses valuations only. FX rates are not distributed by Asset Notation (out of scope); a tool supplies them. This is non-normative: implementations MAY derive differently, but SHOULD document how.

7. Identifiers and code lists

Concept Standard
Currency ISO 4217
Date / time ISO 8601 / RFC 3339
Country ISO 3166-1 alpha-2
Language (in extensions) BCP 47
Security ISIN (ISO 6166); FIGI, ticker as alternates
Exchange MIC (ISO 10383)
Institution BIC (ISO 9362), LEI (ISO 17442)
Bank account IBAN (ISO 13616)

Producers SHOULD populate ids with whichever external identifiers they have. Consumers MUST NOT assume any ids entry is present.

8. Money representation

Money is { "amount": "<decimal string>", "currency": "<ISO 4217>" }. The decimal string is base-10, optional leading -, . as the decimal separator, no thousands separators, no currency symbol. Rationale: binary floats cannot represent most decimal cash values exactly; ISO 20022 likewise uses decimal.

9. Compatibility and versioning

10. Extensibility

App-specific or domain-specific data that is not part of the core MUST NOT be placed in core fields. Three mechanisms, from most to least scoped:

This keeps the core small and stable while letting tools carry their own state (for example an app’s own categorization rules) without polluting the standard.

11. Security and privacy

Asset Notation documents are plaintext and inherently sensitive. Confidentiality, integrity and tamper-evidence are the responsibility of the container that carries the document (for example an encrypted, authenticated container), not of this schema.

12. Containers and transport

Asset Notation is a payload schema, independent of how a document is stored or moved. A document MAY live in a plain file, inside a versioned and optionally encrypted container, in a ZIP, or be served over an API; none of that is the schema’s concern.

Because a document is a set of collections keyed by id (subjects, institutions, holdings, valuations, transactions, ownership), it maps one-to-one onto any document or key-value store. A producer whose internal model is Asset-Notation-shaped can therefore emit a conformant document directly from its own state, reconciling entities by id.

13. Conformance

14. Open questions (for v0.2+)

15. Worked example

A household: one person, a checking account with a cash balance, a brokerage position in an ETF, a directly-owned apartment financed by a mortgage.

{
  "assetnotation": "0.1.0",
  "generatedAt": "2026-06-24T20:00:00Z",
  "generator": { "name": "example", "version": "1.0.0" },
  "baseCurrency": "EUR",
  "subjects": [
    { "id": "s1", "type": "person", "name": "A. Doe", "country": "FR" }
  ],
  "institutions": [
    { "id": "i1", "name": "Example Bank", "kind": "bank", "ids": { "bic": "EXAMPLEXXX" } },
    { "id": "i2", "name": "Example Broker", "kind": "broker" }
  ],
  "holdings": [
    { "id": "h1", "label": "Current account", "kind": "checking", "nature": "asset", "currency": "EUR", "institutionId": "i1", "ids": { "iban": "FR76 XXXX XXXX XX" } },
    { "id": "h2", "label": "World ETF", "kind": "brokerage", "nature": "asset", "currency": "EUR", "institutionId": "i2", "instrumentId": "n1", "quantity": "40" },
    { "id": "h3", "label": "12 Main St", "kind": "real_estate", "nature": "asset", "currency": "EUR", "links": [{ "rel": "financed_by", "holdingId": "h4" }] },
    { "id": "h4", "label": "Mortgage", "kind": "mortgage", "nature": "liability", "currency": "EUR", "institutionId": "i1", "attributes": { "rate": 1.8, "startDate": "2022-01-01", "endDate": "2042-01-01", "payment": "990.00" } }
  ],
  "instruments": [
    { "id": "n1", "name": "World ETF", "kind": "security", "ids": { "isin": "IE00B4L5Y983" }, "currency": "EUR" }
  ],
  "valuations": [
    { "id": "v1", "holdingId": "h1", "asOf": "2026-06-24", "value": { "amount": "4210.55", "currency": "EUR" }, "source": "statement" },
    { "id": "v2", "holdingId": "h2", "asOf": "2026-06-24", "value": { "amount": "4920.00", "currency": "EUR" }, "unitPrice": { "amount": "123.00", "currency": "EUR" }, "source": "market" },
    { "id": "v3", "holdingId": "h3", "asOf": "2026-06-01", "value": { "amount": "300000.00", "currency": "EUR" }, "source": "estimate", "confidence": 0.5 },
    { "id": "v4", "holdingId": "h4", "asOf": "2026-06-24", "value": { "amount": "176400.00", "currency": "EUR" }, "source": "statement" }
  ],
  "ownership": [
    { "subjectId": "s1", "holdingId": "h1", "share": 1 },
    { "subjectId": "s1", "holdingId": "h3", "share": 1 },
    { "subjectId": "s1", "holdingId": "h4", "share": 1 }
  ]
}

Net worth as of 2026-06-24: 4210.55 + 4920.00 + 300000.00 - 176400.00 = 132730.55 EUR.