Skip to content

Investment History v1 ​

Investment History v1 appends source records to one active position-tracked account. The signed-in session and account URL supply the owner, account, institution, account currency, and tracking mode. A file cannot override them.

Use the downloadable examples:

Files are limited to 5 MB and 10,000 combined source records. Dates are non-future YYYY-MM-DD values. Quantities, prices, rates, and money are decimal strings, not JSON numbers.

The position import page also offers optional Convert document with AI. Extraction happens within your self-hosted instance; selected source sections are sent to the configured provider only after approval. The resulting JSON draft must pass the normal import preview. See AI-assisted import.

Stable external IDs ​

Supply stable, case-sensitive external IDs no longer than 200 characters. Instruments, position events, and prices require them. A cash row with no ID receives a derived date/type/minor-amount ID; supply your own to distinguish otherwise identical source events. Instrument references use the instrument's external ID rather than a Wealthboard database ID.

  • An identical stored ID is skipped as a duplicate.
  • An existing ID with different authoritative fields is a conflict.
  • Every occurrence of an ID repeated inside its identity scope is invalid.
  • Instrument IDs are user-scoped; position-event and cash IDs are scoped to the user/account and their respective collections; price IDs are scoped to the user/instrument.
  • Deleting an imported position event, cash transaction, or price releases its external ID for an intentional reimport. Archived instruments retain their identity and external ID.

Do not use spreadsheet row numbers that change when rows are inserted or sorted. Prefer provider IDs or deterministic IDs built from stable source fields outside Wealthboard.

JSON envelope ​

The JSON root is strict:

json
{
  "format": "wealthboard-investment-history",
  "version": 1,
  "instruments": [],
  "position_events": [],
  "cash_transactions": [],
  "prices": []
}

Unknown root or record fields reject the file.

Instruments ​

FieldRequiredRule
external_idYesStable instrument reference
nameYes1 to 100 characters
symbolNoUp to 30 characters
identifier_typeYesisin, ticker_exchange, or custom
identifierNoISIN, exchange ticker, or custom source value
exchange_micNoExchange or MIC used with ticker identity
asset_typeYesstock, etf, or fund
quote_currencyYesEnabled three-letter currency code

An existing instrument with the same external ID must match the imported identity. Ticker alone is not assumed globally unique.

Position events ​

FieldRequiredRule
external_idYesStable event reference
instrument_external_idYesResolves an imported or existing instrument
typeYesopening_position, buy, sell, or quantity_adjustment
quantityYesPositive except a signed, non-zero quantity adjustment
unit_priceBuy/sellPositive execution price
trade_currencyNoEnabled three-letter code; defaults to the instrument quote currency
fee_amountNoNon-negative fee in fee_currency or trade currency
fee_currencyNoEnabled fee currency
cash_effectCross-currency alternativePositive net cash movement including fees, in account currency; direction comes from buy/sell
applied_exchange_rateCross-currency alternativePositive settlement rate; invalid for same-currency trades
opening_cost_basisOpening onlyOptional non-negative reference in account currency
event_group_idNoJSON-only dividend-reinvestment group reference
trade_dateYesEffective financial date
settlement_dateNoSettlement date for a trade
description, notesNoOptional source context

A cross-currency buy or sell requires cash_effect or applied_exchange_rate. An explicit cash_effect is used as the complete cash debit or credit; the fee is not applied again. The complete existing plus imported sequence must stay long-only at every date and explicit same-date order.

Cash transactions ​

FieldRequiredRule
external_idNoStable source reference; strongly recommended to avoid derived-ID collisions
typeYesdeposit, withdrawal, interest, dividend, fee, or manual_adjustment
amountYesPositive except a signed, non-zero manual adjustment
dateYesFinancial date
event_group_idNoJSON-only dividend-reinvestment group reference
description, notesNoOptional source context

One reinvestment group contains one dividend cash row and one or more same-date buy events. The group is remapped to one internal UUID and commits, restores, or deletes atomically. Separate CSV uploads cannot form a grouped reinvestment; use JSON or the Reinvest workflow.

Prices ​

FieldRequiredRule
external_idYesStable observation reference
instrument_external_idYesResolves an imported or existing instrument
priceYesPositive decimal unit price
effective_dateYesDate from which this observation applies
sourceYesShort source label such as statement
provenanceNoStatement, file, or provider reference

Price currency is always the instrument quote currency. A later file cannot silently overwrite a conflicting observation on the same effective date.

CSV contracts ​

Each CSV uses one exact set of header names; column order may vary. Missing, extra, duplicate, or renamed columns reject the file. CSV does not wrap records in a JSON envelope.

Opening holdings ​

csv
instrument_external_id,event_external_id,price_external_id,instrument_name,symbol,identifier_type,identifier,exchange_mic,asset_type,quote_currency,quantity,unit_price,price_date,opening_cost_basis,notes

Each row creates or resolves an instrument, writes one opening position, and writes its effective price. It counts as three records against the combined 10,000-record limit.

Trades ​

csv
external_id,instrument_external_id,type,quantity,unit_price,trade_currency,fee_amount,fee_currency,cash_effect,applied_exchange_rate,trade_date,settlement_date,description,notes

Trade rows support buy, sell, and quantity_adjustment. Instruments must already exist or be included through a JSON envelope/opening-holdings import.

Cash ​

csv
external_id,type,amount,date,description,notes

Prices ​

csv
external_id,instrument_external_id,price,effective_date,source,provenance

Preview and commit ​

Preview writes nothing. The downloadable Report contains:

  • existing or new instrument resolution;
  • per-instrument and per-event before/after quantities;
  • deterministic date/order placement;
  • current and projected cash, position value, total, and net change;
  • price values, currencies, sources, and affected-from dates;
  • missing prices and currencies;
  • duplicates, conflicts, invalid relationships, and oversells.

Investment import preview showing exact quantity and value effects

The current page shows summary counts and the first 50 row outcomes. Use the report for complete quantities and projected values; stale-price diagnostics remain in the account's Positions table rather than this import result.

Confirmation requires the same file bytes and SHA-256 hash. Wealthboard reparses the file, rechecks ownership and duplicates, inserts every accepted source record, validates grouped relationships and long-only replay, and rebuilds the account value inside one serializable PostgreSQL transaction. Any unexpected error rolls back the entire investment import.

Common rejection reasons ​

Message or stateResolution
Position would become negativeAdd the missing earlier holding/buy, correct the quantity/date, or remove the oversell
External ID conflictsUse the original authoritative fields or a genuinely different stable source ID
Referenced instrument was not foundImport/create the instrument first or correct instrument_external_id
Cross-currency settlement requiredSupply actual account-currency settlement or the applied settlement rate
Missing price or rateThe import may be structurally valid but projected value remains incomplete; add the effective observation before relying on totals
File changed after previewPreview the final file again before confirming

For ordinary balance-account transactions, use Account History Import v1 instead.

Private wealth tracking, on infrastructure you control.