Get Grid Endpoint
const url = 'https://example.com/api/v1/snapshots/grid?offset=0&sort_by=date&sort_dir=asc';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://example.com/api/v1/snapshots/grid?offset=0&sort_by=date&sort_dir=asc'Pivoted grid data: dates as rows, accounts as columns.
date_from/date_to are optional query params bounding the snapshot date range; omitting either (or both) is unbounded, matching prior behavior.
limit/offset paginate by distinct date, not by snapshot row – a page always contains every account’s cell for each date it includes, never a partial one. Always returns X-Total-Count (total distinct dates matching date_from/date_to, ignoring limit/offset). Omitting limit returns every matching date, unbounded, matching prior behavior exactly – unaffected by which column is sorted on, still reporting the row count as its total, never gaining a slice.
sort_by/sort_dir/sort_column_id mirror the institutions grid’s contract exactly: date (unchanged, SQL-paginated), row total, or one account’s own raw balance, ordered across the whole matching date range (not just the loaded page) for total/column sorts. This endpoint has no pre-existing router-layer column list, so it resolves one via get_grid_account_ids() before validating and before fetching, and passes that same list down to the grid builder as its column order – the validated set and the rendered columns can never disagree. sort_column_id, when the column mode is requested, must name one of those resolved account ids; anything else (foreign, or matching no account at all) is rejected with a 422 that names the constraint only, indistinguishably. Supplying sort_column_id with any other mode is ignored rather than rejected. Omitting all three sort params reproduces the pre-existing row order and total-count header exactly, in both the paginated and the unbounded case.
Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Responses
Section titled “Responses”Successful Response
One date row in the pivoted grid.
cells has one GridCell per active account, in account order. total is the base-currency-converted sum of non-null cell balances (Decimal serialized as string) – NOT a naive raw sum of native balances, which would be wrong whenever cells span multiple currencies. A cell whose currency has no resolvable conversion rate contributes 0 to this total, matching the existing aggregate-total fallback convention used elsewhere (e.g. SnapshotDateGroup’s total).
object
One account’s data within a grid row.
null snapshot_id/balance means no snapshot for this account on this date. currency/converted_balance are null only when balance is null. converted_balance is the base-currency-converted amount when the snapshot’s own currency differs from the user’s base_currency; it is null when currency == base_currency (nothing to convert) OR when no conversion rate could be resolved at all for that currency (genuinely absent from history, not “still loading” – the frontend renders a warning icon in that case rather than a misleading converted figure).
Example generated
[ { "date": "example", "cells": [ { "account_id": 1, "snapshot_id": 1, "balance": "example", "currency": "example", "converted_balance": "example" } ], "total": "example" }]Validation Error
object
object
object
Example generated
{ "detail": [ { "loc": [ "example" ], "msg": "example", "type": "example", "input": "example", "ctx": {} } ]}