@get-asset/sdk

Accounts List

Headless compound that fetches a business's connected external accounts and groups them by institution. Each group sorts its accounts by name; groups are sorted alphabetically. Each group is a collapsible summary row (GroupToggle, GroupStatus); per-account parts expose the name, masked number, type, sync status, and the balance with the currency it is held in, plus a Disconnected gate wrapping a Reconnect action. A group states no total: accounts under one institution can be held in different currencies, so the balances that mean something are the rows'.

It also carries reconciliation: each account gains a derived statement state (Statements) built from the statements the backend has asked for, and the list is a three-screen flow — the accounts table, one account’s statements, and a review of everything posted since it last balanced. See Reconciliation.

Anatomy

Import the primitive and compose the parts you need.

<AccountsList.Root onReconnect={reconnect}>
<AccountsList.Success>
<AccountsList.Groups>
{/* Group summary row */}
<AccountsList.GroupToggle></AccountsList.GroupToggle>
<AccountsList.GroupName />
<AccountsList.GroupStatus />
<AccountsList.Accounts>
<AccountsList.Account>
<AccountsList.AccountName />
<AccountsList.AccountMask />
<AccountsList.AccountStatus />
<AccountsList.Balance />
<AccountsList.Currency />
<AccountsList.Disconnected>
<AccountsList.Reconnect>Reconnect</AccountsList.Reconnect>
</AccountsList.Disconnected>
</AccountsList.Account>
</AccountsList.Accounts>
</AccountsList.Groups>
</AccountsList.Success>
<AccountsList.Loading></AccountsList.Loading>
<AccountsList.Empty>No accounts connected.</AccountsList.Empty>
</AccountsList.Root>

Required scopes

The access token used by AssetProvider must include these scopes for this primitive to fetch data successfully:

  • external_account:read
  • external_account:update
  • transaction:delete
  • ledger:read
  • request:read
  • transaction:read
  • document:read
  • document:create
  • document:delete
  • report:read
  • ledger:update

API reference

Root props

PropTypeDefaultDescription
institutionName(account) => string | nullOverride how an account maps to its institution group. Defaults to the account's institution_name, falling back to metadata_ then "Other accounts". Return null to use the fallback.
sourceExternalAccountSourceFilter by account source (manual / plaid / statements / gusto). Passed to the API.
typeExternalAccountTypeFilter by account type (business / personal). Passed to the API.
statusExternalAccountStatusFilter by account status (connected / disconnected / untracked). Passed to the API.
onReconnect(account) => voidInvoked when a disconnected account's <Reconnect> part is clicked. Receives the raw account.
accountsExternalAccountPublic[]Override fetched data — pass the API list as-is. Skips the API call.
state"loading" | "error" | "empty"Force a specific state for testing.
showCurrencybooleanForce the ISO code beside each amount on or off, skipping the business fetch (storybook/tests). By default it shows only for a business that holds money in more than one currency.
defaultScreen"accounts" | "statements" | "review"Screen to open on. Defaults to "accounts". Pass defaultAccountId alongside anything deeper.
defaultAccountIdstringAccount opened on mount — required when defaultScreen is past accounts.
onScreenChange(screen: "accounts" | "statements" | "review") => voidNotified on every screen change, so a host can mirror it in its own chrome (this is how the styled card hides Add Account inside the flow).
tasksTaskRequestStatementPublic[]Override the fetched statement requests. Skips that API call.
transactionsTransactionPublic[]Override the review's fetched transactions. Skips that API call.
reviewState"loading" | "error" | "empty"Force the review's state for testing. Separate from state, which forces the accounts list's.
onTransactionRemove(id: string) => voidCalled after a transaction is successfully deleted.
childrenrequiredReactNodeCompound parts.

Parts

Container

Always rendered. Fetches accounts and provides context.

PartDescription
AccountsList.RootFetches external accounts, groups them by institution and provides context.

Success

Renders when at least one account is available.

PartDescription
AccountsList.SuccessState wrapper. Compose the grouped table inside.
AccountsList.GroupsIterates each institution group, providing a group context and tracking per-group collapse state.
AccountsList.GroupName
asChild?
Renders the current group's institution name.
AccountsList.GroupToggle
asChild?
Button that collapses/expands the group. Sets aria-expanded and data-collapsed (for styling a chevron). While collapsed, <Accounts> renders nothing.
AccountsList.GroupStatus
asChild?, format?
Renders the group's rolled-up status (connected if any account is, else disconnected, else paused) and sets data-status. Connected groups show the most recent sync time.
AccountsList.AccountsIterates the current group's accounts (nothing while collapsed). Must be used inside <Groups> (throws otherwise). Provides an account context to each iteration.
AccountsList.Account
asChild?
Per-account row wrapper. Sets data-type, data-status and data-disconnected attributes from the account.
AccountsList.AccountName
asChild?
Renders the account name (falls back to "Unnamed account").
AccountsList.AccountMask
asChild?, format?
Renders the account mask (e.g. last four digits). Pass format(mask) to decorate it; mask may be null.
AccountsList.AccountStatus
asChild?, format?
Renders the account's status and sets data-status. Connected accounts show a relative sync time ("2h ago"); others show "Disconnected"/"Paused". Pass format(status, lastSyncedAt) to override.
AccountsList.AccountType
asChild?, format?
Renders the account type. Defaults to "Business"/"Personal" and sets data-type on the element.
AccountsList.LastSynced
asChild?, format?
Renders the last-synced timestamp as an absolute date ("Mon DD, YYYY", or "Never synced"). Pass format(date | null) to override.
AccountsList.Balance
asChild?, format?
Renders the account's external balance. format receives (amount, currency) — the account's own ISO 4217 code, or null — so it can print the symbol that goes with this account's money. Renders nothing when the balance is unknown (null).
AccountsList.Currency
asChild?
The ISO 4217 code the account's balance is denominated in — meant to sit beside Balance. Renders nothing when the account reports no currency, or no balance for it to label. Adds data-currency. Renders nothing at all unless the business holds money in more than one currency.
AccountsList.DisconnectedPer-account state gate. Renders its children only when the account is disconnected.
AccountsList.ConnectedInverse of Disconnected — renders only for connected accounts.
AccountsList.Reconnect
asChild?
Button that calls Root's onReconnect with the current account. Renders nothing unless the account is disconnected and came from Plaid — the only source with a link to repair (Plaid update mode).
AccountsList.BusinessPer-account gate. Renders only for business accounts.
AccountsList.PersonalPer-account gate. Renders only for personal accounts.
AccountsList.PausedPer-account gate. Renders only for a paused synced account (status untracked). Never renders for manual accounts, which have nothing to sync.
AccountsList.SyncingPer-account gate. Renders only for an actively-syncing account. Like Paused, it is sync-specific and never renders for manual accounts.
AccountsList.Editing
editor
Per-account gate. Renders only while this account's inline editor of the given kind is open — editor="switch-personal" for the ledger editor, editor="delete" for the delete confirmation. Open via edit(account, editor); compose the editor UI and the actions (cancelEdit / switchToPersonal / deleteAccount) inside.
AccountsList.SyncedPer-account source gate. Renders only for externally-synced accounts (anything but manual) — compose sync-specific UI here (last-synced time, pause/resume). For a specific source use Source instead.
AccountsList.Source
value
Per-account source gate — renders only when the account's source matches value. Pass a single source (value="plaid" / value="manual") or an array to match any of several (value={["plaid", "gusto"]}). This is the per-source gate; new sources need no new component.

Loading

Renders while the fetch is in flight.

PartDescription
AccountsList.LoadingState wrapper. Render any skeleton or placeholder UI inside.

Empty

Renders when no accounts are connected.

PartDescription
AccountsList.EmptyState wrapper. Render an empty-state message inside.

Error

Renders on fetch error.

PartDescription
AccountsList.ErrorState wrapper. Compose the error UI inside.
AccountsList.ErrorMessage
asChild?
Renders the error message string.
AccountsList.Retry
asChild?
Button that re-runs the fetch.

Reconciliation — screens

Screen gates are mutually exclusive — exactly one is open at a time. Wrap the accounts table in AccountsScreen so it gives way to the drill-down.

PartDescription
AccountsList.AccountsScreenRenders children while the accounts table is showing (the root screen).
AccountsList.StatementsScreenRenders children while one account's statements are showing.
AccountsList.ReviewScreenRenders children while the account's transactions are being reviewed. Entering it is what triggers the transactions fetch.
AccountsList.Statements
asChild?, format?
The reconciliation state of the account row being rendered — the Statements column. Defaults to the derived label ("2 statements needed", "Up to date", "Not checked") and sets data-status to the matching value. Must be used inside <Accounts>. format receives the whole AccountReconciliation ({ accountId, status, count, requestedAt, lastBalancedAt, label }).
AccountsList.OpenAccount
asChild?
Opens the account row being rendered into its statements. Accounts that aren't tracked (disconnected or paused) are inert and carry data-disabled. Adds tabIndex and Enter/Space handling so the row answers to the keyboard; role is left to you, since inside a table the row is a row. Must be used inside <Accounts>.
AccountsList.Back
asChild?
The one back affordance — steps to the parent screen. Renders nothing on the accounts screen.
AccountsList.GoTo
asChild?, screen
Navigates straight to a screen — the "Accounts" crumb, typically.
AccountsList.RequestedCount
asChild?, format?
How many statements have been asked for across every account.
AccountsList.OpenAccountName
asChild?, format?
Names the account you're inside. Renders nothing until one is open. format receives the raw account.
AccountsList.OpenCount
asChild?, format?
How many statements are still being asked for on the open account.
AccountsList.StatementRequested / NoStatementRequestedGates on whether the open account still owes a statement. The styled layer uses these for the screen's banner: the months wanted inside the first, and when the account last balanced inside the second. Note that nothing outstanding is not the same as the books agreeing — the banner states the date and draws no conclusion from it.
AccountsList.RequestsIterates the open statement requests for the account, oldest month first, providing a request context to each. The API keeps a request open until its upload has been read, so a row stays put through uploading and processing and only clears once the statement has landed — at which point StatementList carries it.
AccountsList.RequestMonth
asChild?, format?
The month a statement has been asked for, as YYYY-MM (null when the task carries none). Must be used inside <Requests>.
AccountsList.RequestedAt
asChild?, format?
When the statement was asked for — how long the row has been waiting.
AccountsList.RequestStatus
asChild?, format?
How far along the request is: needed, uploading, processing, ready or failed. Sets data-status, and defaults to a plain label ("Reading statement…"). format receives the whole StatementRequest.
AccountsList.RequestIs
status
Renders children only while the request is in the given state; pass an array to match several (status={["needed", "failed"]}).
AccountsList.RequestFileName
asChild?
The name of the statement uploaded against the request. Renders nothing until there is one.
AccountsList.RequestError
asChild?
Why the upload or processing failed, from the upload error or the document's status_reason. Renders nothing unless the request failed.
AccountsList.StatementDropzone
asChild?
Drag-and-drop surface for statements — wires the drag events and hands files to addStatements. Sets data-dragging while a file is over it. Pair with a file input for the click path, as the Documents dropzone does.
AccountsList.UploadItems / UploadItem / UploadItemName / UploadItemMeta / UploadItemErrorMessage / UploadItemUploading / UploadItemSuccess / UploadItemError / UploadItemDismissThe upload queue, part for part the same as Documents' own — one chip per file with its own status. Files over maxFileSize (25 MB by default) and names the account already holds are rejected before any request is made, with the same wording. A success clears its chip after a moment; an error stays until dismissed.
AccountsList.StatementsProcessing / StatementsFailed / NoStatementsFailedGates on the state of the statements the account holds: one still being read, one that couldn't be read, and neither. The styled layer uses them to say why the review is inert and to keep the banner honest.
AccountsList.StatementsUploading / UploadErrorGate for an upload in flight, and the last upload failure. Uploads tag task_id only when exactly one request is open. Note the create endpoint reports per-file outcomes in a 201 body, so a rejected file is read from `unsuccessful` rather than from the HTTP status.
AccountsList.UploadStatement
input props
Renders a real <input type="file"> that uploads a statement against the request it sits in, tagged with task_id. Pair it with a <label> to style it. The row then polls the document every 3s until it leaves processing.
AccountsList.StatementsReadyRenders children once every requested statement has been read (or nothing was asked for).
AccountsList.Review
asChild?
Opens the review of the account's transactions. Disabled while a statement is still being asked for or still being read — a statement mid-read hasn't put its transactions in the books yet. A statement that couldn't be read does not block: it will never finish and its request has already cleared. Present rather than hidden, so the screen shows what it leads to.
AccountsList.CanReview / NotReadyToReviewGates mirroring Review's own condition, for saying what is still being waited on where the button would be.
AccountsList.StatementListIterates the statements to list for the open account, newest first. Separate from Requests: that is what we still want, this is what we have. A statement already shown on a request row is left out, so one being read appears once rather than twice — it moves here when that row is released. Polls while any is still being read.
AccountsList.HasStatements / NoStatementsGates on whether the account holds any statement at all.
AccountsList.StatementName / StatementUploadedAt / StatementDocumentStatus
asChild?, format?
The statement's file name, when it was uploaded, and how far it has got ("Reading…", "Processed", "Partly processed", "Couldn't be read"). The status sets data-status. Must be used inside <StatementList>.
AccountsList.StatementError
asChild?
The document's status_reason. Renders nothing unless the statement failed.
AccountsList.StatementIs
status
Renders children only while the statement is in the given DocumentPublicStatus; pass an array to match several (status={["processed", "partially_processed"]}).

Reconciliation — review

The review fetches everything posted to the open account since last_balanced_at. It has its own loading / error / empty gates, separate from the list's, because the accounts table is already on screen behind it.

PartDescription
AccountsList.ReviewedSince
asChild?, format?
When the account last balanced. The review starts there, and the statements banner says it outright once nothing is outstanding. Renders nothing when the account has never balanced — the review then covers everything, and there is no date to state.
AccountsList.OpeningBalanceField
input props
The opening balance as an editable field — the one figure on the summary the user can change, since a wrong opening balance is a common cause of a gap no transaction explains. Commits on blur or Enter, reverts on Escape, and writes via PUT /ledger/{id}/opening-balance, which needs ledger:update. Closing and Difference move with it.
AccountsList.OpeningBalance / TransactionsBalance / ClosingBalance / BankBalance / Difference
asChild?, format?
The balance summary: what the books opened at, everything booked since, the two together (the bank ledger's all_time_balance), what the bank says (the account's external_balance), and the difference between the last two — which is what the user is there to drive to zero, and which sets data-balanced when it gets there. Each renders nothing when its figure is unknown, and each format receives (amount, currency). The API exposes no direct read of the opening balance, so it is derived as all_time_balance minus the balance over the business's entries_start → now range. Every figure is stated in the account's own currency: a foreign account reads the ledger's original_currency_balances entry for that currency, rather than the top-level balances, which are in the business home currency.
AccountsList.HasBalances / BalancesLoadingGates on the summary. HasBalances renders only once both sides are known — an account with no bank balance or no bank ledger has no comparison to make, and a summary of blanks is worse than none. It also stays off when the ledger reports nothing in the account's currency, since the figures would otherwise mix two currencies.
AccountsList.Balanced / NotBalancedGates on whether the books match the bank.
AccountsList.ReviewLoading / ReviewError / NoTransactions / HasTransactionsThe review's own four states. NoTransactions means nothing has posted since the account last balanced.
AccountsList.ReviewErrorMessage
asChild?, format?
Renders the review's error message string.
AccountsList.ReviewRetry
asChild?
Refetches the review's transactions.
AccountsList.TransactionsIterates the transactions under review, providing a row context to each.
AccountsList.Transaction
asChild?
The row element. Sets data-confirming while its delete is armed.
AccountsList.OpenAccountCurrency
asChild?
The ISO 4217 code the open account's figures are denominated in. The reconciliation screens are one account's, so every amount on them shares it — pair it with the balance summary figures and each review row's amount. Renders nothing when the account reports no currency. Adds data-currency. Renders nothing at all unless the business holds money in more than one currency.
AccountsList.TransactionDate / TransactionDescription / TransactionAmount
asChild?, format?
The row's values. TransactionDate gives the raw ISO instant; TransactionAmount takes format(amount, currency) — every row is in the reviewed account's currency — and sets data-direction to in or out. Descriptions take no format.
AccountsList.TransactionSource
asChild?
The statement that produced the row, as its file name. Empty when nothing accounts for it — pair with the FromDocument gate.
AccountsList.FromDocument / NoDocumentGates on whether a statement accounts for the row. Matched from the statements already fetched for the account (their transaction_id / transaction_ids), so it costs no extra request — but it only sees statements, not receipts or bills. A row nothing accounts for draws attention; it does not assert the row is wrong, since a bank-feed entry can legitimately have no statement behind it.
AccountsList.RemoveTransaction
asChild?
Asks to delete the row. Deleting a posted transaction is irreversible, so this only arms a confirmation — it does not call the API. Renders nothing on the row already awaiting confirmation.
AccountsList.ConfirmingRenders children only on the row awaiting confirmation. Compose the confirm band inside.
AccountsList.ConfirmRemove / CancelRemove
asChild?
Deletes the armed transaction, or closes the confirmation. Both disable while the delete is in flight. A successful delete invalidates the transactions and accounts queries, since the balance may now agree.
AccountsList.HasMore / LoadMoreCursor pagination over the review, the same shape the Transactions component uses: HasMore gates the banner, LoadMore fetches the next page and appends it, setting data-loading and aria-busy while it is in flight.
AccountsList.TransactionCount
asChild?, format?
How many transactions the review is showing.

Hooks

PartDescription
useAccountsList()Hook returning groups, accounts, hasData, loading, error, retry, onReconnect, plus per-account actions: pauseSync, resumeSync, deleteAccount, switchToBusiness, switchToPersonal(account, { contributionLedgerId, distributionLedgerId }), actionPending, and the inline row editors — editing ({ account, editor } | null), edit(account, editor) and cancelEdit open/close the switch-to-personal ("switch-personal") or delete ("delete") editor, with ledgers / ledgersLoading for the switch form. Each action mutates via the API and refetches the list.
useAccountsListGroup()Hook used inside a Groups iteration; returns the current group ({ institution, accounts }).
useAccountsListAccount()Hook used inside an Accounts iteration; returns the current account node ({ account, institution, currency, status, isDisconnected, canReconnect, isBusiness, isPersonal, isPaused, source, isManual, isPlaid, isSynced }). currency is the ISO 4217 code the account's balances are denominated in, or null when it reports none.
useAccountsListRow()Hook used inside a Transactions iteration; returns the current review row ({ id, date, description, amount, confirming }).
useAccountsListRequest()Hook used inside a Requests iteration; returns the current TaskRequestStatementPublic, so you can read its month or attach an upload to its id.

Reconciliation

The compound has a second job beyond listing accounts: getting a business’s bank statements checked against its books. It stays one compound because it is the same data — the accounts the user already sees, annotated with what each one needs — and it is always on, so every account row carries its statement state.

How the flow is driven

A background job compares each account’s balance against the books. When they disagree for long enough it raises a request_statement task, and that task is the only signal this component reads — there is no reconciliation resource.

1. A background job compares the account balance against the books.
2. They disagree for long enough → it raises a `request_statement` task
carrying `external_account_id` and `month`.
3. The account row reads "N statements needed".
4. Opening the row names the months wanted and offers one dropzone. A file is
tagged with `task_id` only when a single request is open — with several
there is no telling which file answers which, so the backend reads the
period off the statement.
5. The task stays open until the statement has been read, so the row keeps its
place and shows the progress. The document is polled every 3s. The task
clears a beat after the document settles, so the tasks are polled too while
a row reads `ready` — that is what finally clears it.
6. Once nothing is being asked for and nothing is still being read, Review opens: the bank balance against
the book balance with the gap between them, over everything posted since
`last_balanced_at`. Deleting a row refetches both the transactions and the
ledger, so the summary moves with it.

The Statements column is derived from those open requests:

  • disconnected or paused → not_checked— the balance isn’t being compared to anything, so a statement is never asked for. The label is “Not checked”, but the styled column renders nothing for it: the Status column beside it already says Disconnected or Paused.
  • one or more open requests → Not reconciled since <date>, taken from the oldest request’s created_at. How long it has been out is what tells the user whether this is urgent — a file count doesn’t. The raw value is on requestedAt so the styled layer formats it.
  • otherwise → nothing outstanding. lastBalancedAtcarries the account’s last_balanced_at so the styled column can say Last balanced on Jun 30th— a date is what makes the reassurance worth anything, and an account that has never balanced shows nothing at all rather than claiming to be up to date. The default label stays date-free, since formatting isn’t the headless layer’s job.

The row states the action needed rather than a reconciliation status, because the user is not expected to know the word. Nothing keys off last_statement_end_date: a statement having arrived once says nothing about whether one is wanted now.

The review fetches; it does not take a period

Review covers everything posted to the account since last_balanced_at — the window the background job found the discrepancy in. That comes off the account itself, so no statement period has to be inferred. When the account has never balanced, the start bound is omitted and the review covers everything.

Deleting is irreversible, so RemoveTransaction only arms a per-row confirmation — ConfirmRemove is what calls the API. A successful delete invalidates the transactions and accounts queries, since the balance may now agree.

Editing is partly unbacked. TransactionUpdateItem carries only type, reviewed, status, tags and line_items— nothing that changes a posted transaction’s amount, date or description. TransactionField therefore holds those corrections locally and reports them through onTransactionUpdate, so a host can persist them its own way (typically delete + re-create via POST /transactions, which does accept all three). Until an endpoint takes them, a reload loses them.

Anatomy

<AccountsList.Root>
<AccountsList.Success>
{/* 1 — the accounts table, plus a Statements column */}
<AccountsList.AccountsScreen>
<AccountsList.Groups>
<AccountsList.Accounts>
<AccountsList.OpenAccount>
<AccountsList.AccountName />
<AccountsList.Statements /> {/* "2 statements needed" */}
<AccountsList.Balance />
</AccountsList.OpenAccount>
</AccountsList.Accounts>
</AccountsList.Groups>
</AccountsList.AccountsScreen>
{/* 2 — one account's statements, and what has been asked for */}
<AccountsList.StatementsScreen>
<AccountsList.Back></AccountsList.Back>
<AccountsList.OpenAccountName />
{/* the banner: either the months wanted, or that it's balanced */}
<AccountsList.StatementRequested>
<AccountsList.Requests>
<AccountsList.RequestMonth /> {/* "2026-05" */}
<AccountsList.RequestedAt /> {/* when we asked */}
<AccountsList.RequestFileName /> {/* once something is uploaded */}
<AccountsList.RequestIs status={["needed", "failed"]}>
<AccountsList.UploadStatement />
</AccountsList.RequestIs>
<AccountsList.RequestIs status={["uploading", "processing"]}>
<AccountsList.RequestStatus /> {/* polls until read */}
</AccountsList.RequestIs>
<AccountsList.RequestIs status="failed">
<AccountsList.RequestError />
</AccountsList.RequestIs>
</AccountsList.Requests>
</AccountsList.StatementRequested>
<AccountsList.NoStatementRequested>
<AccountsList.ReviewedSince /> {/* "Last balanced on Jun 30th" */}
</AccountsList.NoStatementRequested>
{/* everything held for the account — an upload lands here and polls
itself from Reading to Processed */}
<AccountsList.HasStatements>
<AccountsList.StatementList>
<AccountsList.StatementName />
<AccountsList.StatementUploadedAt />
<AccountsList.StatementDocumentStatus />
<AccountsList.StatementIs status="failed">
<AccountsList.StatementError />
</AccountsList.StatementIs>
</AccountsList.StatementList>
</AccountsList.HasStatements>
{/* hidden until nothing is outstanding and nothing is still being read */}
<AccountsList.NotReadyToReview>Still waiting…</AccountsList.NotReadyToReview>
<AccountsList.Review>Review transactions</AccountsList.Review>
</AccountsList.StatementsScreen>
{/* 3 — everything posted since the account last balanced */}
<AccountsList.ReviewScreen>
<AccountsList.Back></AccountsList.Back>
<AccountsList.ReviewedSince />
{/* what the user is here to fix */}
<AccountsList.HasBalances>
<AccountsList.OpeningBalanceField /> {/* editable */}
<AccountsList.TransactionsBalance />
<AccountsList.ClosingBalance />
<AccountsList.BankBalance />
<AccountsList.Difference /> {/* the target: zero */}
</AccountsList.HasBalances>
<AccountsList.ReviewLoading></AccountsList.ReviewLoading>
<AccountsList.ReviewError>
<AccountsList.ReviewErrorMessage />
<AccountsList.ReviewRetry>Try again</AccountsList.ReviewRetry>
</AccountsList.ReviewError>
<AccountsList.NoTransactions>Nothing has posted.</AccountsList.NoTransactions>
<AccountsList.HasTransactions>
<AccountsList.Transactions>
<AccountsList.Transaction>
<AccountsList.TransactionDate />
<AccountsList.TransactionDescription />
{/* which statement produced the row, if any */}
<AccountsList.FromDocument>
<AccountsList.TransactionSource />
</AccountsList.FromDocument>
<AccountsList.NoDocument>No document</AccountsList.NoDocument>
<AccountsList.TransactionAmount />
<AccountsList.OpenAccountCurrency />
<AccountsList.RemoveTransaction>Delete</AccountsList.RemoveTransaction>
</AccountsList.Transaction>
{/* deleting is irreversible, so it confirms in place */}
<AccountsList.Confirming>
<AccountsList.CancelRemove>Cancel</AccountsList.CancelRemove>
<AccountsList.ConfirmRemove>Delete</AccountsList.ConfirmRemove>
</AccountsList.Confirming>
</AccountsList.Transactions>
<AccountsList.HasMore>
<AccountsList.LoadMore>Show more</AccountsList.LoadMore>
</AccountsList.HasMore>
<AccountsList.TransactionCount />
</AccountsList.HasTransactions>
</AccountsList.ReviewScreen>
</AccountsList.Success>
</AccountsList.Root>

Scopes

Because reconciliation is always on, AccountsList.scopes includes the statement-request, document and transaction reads it needs. A token minted from an older, smaller set will 401 on the task fetch and the list will show its error state — regenerate delegated tokens from this array.