Get reconciliation data for an account
GET/api/v1/reconciliation/:accountId
Returns full reconciliation data for the account grouped by symbol.
Includes broker positions, UTM trades, unlinked executions,
discrepancy summaries, and reconciliation status per symbol. The
top-level ignoredInWindow field counts orphan ignored executions
at or after the account's utmStartDate so the UI can prompt the
user to bulk-restore them after moving the date earlier (#422); it
is always 0 when no UTM start date is set. Access is denied if the
account does not belong to the authenticated user.
The unlinked / pending-review buckets are capped to a rolling
14-day window by default. Pass showAll=true to drop the window
and fall back to the account's utmStartDate (or no lower bound
if unset). The response includes windowDays,
executionsBeyondWindow, and showingAll so the UI can render
the windowing pill.
Every execution row carries signalStrategyId and
signalStrategyName: the strategy of the signal that produced the
execution's order (via Execution -> Order -> Signal), or null when
the fill has no UTM order or the order has no signal. The match UI
compares these against a candidate trade's strategyId /
strategyName so a cross-strategy link is flagged before the
operator confirms it.
Each orphan execution (pending_review, no linked trade) carries a
suggestions array of Tier 2 auto-match candidates (#418), each
\{ tradeId, score, matchedOn: \{ symbol, side, qtyDeltaPct, timeDeltaMinutes \}, candidateSummary \}, highest score first and
capped at three. A trade whose strategy differs from the orphan's
signal strategy is never suggested; the strategy gate applies only
when both strategies are known. The array is empty when auto-match
is disabled or no candidate clears the configured minimum score.
Nothing is ever linked without an explicit user action; the array is
a suggestion only. Linked, unlinked, and ignored executions omit the
field.
Each symbol also carries a linkedExecutions array (#1107): the real
broker fills (source broker_fill) already attached to one of the
symbol's trades, each with its tradeId. The UI surfaces these behind
a "Show linked fills" disclosure so a fill linked to the wrong trade
can be pulled back out and unlinked or re-matched, rather than only
being visible nested under its trade. Synthetic position-import and
manual fills are excluded - they are managed from the trade itself.
Each symbol with no discrepancy and one or more pending-review fills
also carries a remnants array (#1197): historical unlinked-fill
groups that no longer back the current position. Each remnant has a
kind (closed_round_trip), realisedPnl (sell proceeds minus buy
cost), the grouped fills, the latest executedAt,
and a preStartDate flag (true when the latest fill predates the
account's utmStartDate). summary.remnantCount totals them across
symbols. The top-level utmStartDate is the account's start date (or
null), surfaced so the reconcile banner can render the cutoff and offer
the bulk "ignore everything before" action without a second call.
Each symbol also carries a residueTrades array (#1360, findings 1
and 6): "expired_no_order" lifecycle-residue trades for the symbol -
stranded pre-allocations auto-hidden from trades above and from
summary.unreconciledTrades (see #1106, GET /reconciliation/set-aside)
because they carry no reconciliation work of their own. A residue
shell is nonetheless very often the rightful owner of an unmatched
order or fill surfacing elsewhere on the same symbol, so it is still
listed here as a link-to-trade candidate, separately from the routine
queue. Never includes "zero_quantity_superseded" residue (a
superseded trade was genuinely replaced and is not a valid link
target). Excludes residue the user has already restored from Set
aside - that trade is back in trades instead.
Request
Responses
- 200
- 400
- 401
- 404
- 500
Full reconciliation data grouped by symbol
Invalid account ID format
Authentication required
Account not found or access denied
Server error