@get-asset/sdk
Transactions
Headless compound that fetches the business's transactions and exposes them as table rows — date, description, the external account, the amount, and the category. Each pending row offers a confirm (✓) action that sets its status to confirmed and a provide-context (✕) action that opens an inline form. A business_pendingrow leaves a note on its journal entry and hands it back to the bookkeeper; any other row runs the comment through the agent chat infrastructure (create chat → categorization message). On submit the section collapses and the row reads “Reviewing” until the agent finishes, then it refetches — reviews run concurrently, so several rows can be reviewing at once. The table can be filtered by status and by external account — exposed via useTransactions() and applied to the fetch. Results are paginated: a HasMore banner with aLoadMore link fetches and appends the next page. Payment-only transactions (those without a both-basis journal entry) are always excluded.
Anatomy
Import the primitive and compose the parts you need.
<Transactions.Root><Transactions.Success><Transactions.Rows><Transactions.Row><Transactions.Date /><Transactions.Description /><Transactions.Account /><Transactions.Amount /><Transactions.Status /><Transactions.Category /><Transactions.HasTags>{/* tag UI */}</Transactions.HasTags><Transactions.Pending><Transactions.Confirm /></Transactions.Pending><Transactions.ProvideContext /></Transactions.Row><Transactions.Context>{/* inline "provide context" form */}</Transactions.Context></Transactions.Rows><Transactions.HasMore><Transactions.LoadMore>Show more</Transactions.LoadMore></Transactions.HasMore></Transactions.Success></Transactions.Root>
Required scopes
The access token used by AssetProvider must include these scopes for this primitive to fetch data successfully:
transaction:readtransaction:updateexternal_account:readbusiness:readtag:readjournal_entry:readjournal_entry:create
API reference
Root props
| Prop | Type | Default | Description |
|---|---|---|---|
year | number | — | Override the AssetProvider's year for the date range. |
month | number | null | — | Override the AssetProvider's month (1-12); null forces the whole year. Omit to inherit the provider's month. |
startDatetime | string | — | ISO datetime overriding the start of the provider-derived year/month period. |
endDatetime | string | — | ISO datetime overriding the end of the provider-derived year/month period. |
accountIds | string[] | — | Only include transactions for these external account ids. |
ledgerType | LedgerType | — | Only include transactions whose journal entry has a line in a ledger of this type (e.g. "expense"). Always applied to the fetch. Ignored when ledgerSubtype is also set — the subtype is more granular and already implies its type. |
ledgerSubtype | LedgerSubType | — | Only include transactions whose journal entry has a line in a ledger of this subtype (e.g. "operating_expense"). Always applied to the fetch. Takes precedence over ledgerType — when both are set only the subtype is sent to the API. |
defaultStatusFilter | string | — | Pre-select the status filter ("business_pending" | "bookkeeper_pending" | "confirmed", or "all"). Uncontrolled — the user can still change it. |
defaultAccountFilter | string | — | Pre-select the account filter (an external account id, or "all"). A specific account overrides accountIds. Uncontrolled — the user can still change it. |
pageSize | number | — | Page size passed to the API. |
entries | TransactionOverride[] | — | Override the rows shown (skips the API fetch). Used by storybook/tests. |
tagFields | TransactionTagField[] | — | Override the fetched tag fields (name + values), skipping the fetch. Pass [] to hide all tag UI; omit to fetch the business's fields with their values. |
allowCreateTag | boolean | true | Allow consumers to offer creation of new tag values (see Tags). |
plan | "managed" | "diy" | — | Override the business plan — "managed" (Done for you) or "diy" (Do it yourself); skips the business fetch. Drives the status labels and filter options (see Plan behaviour). Defaults to the fetched plan, or "managed". |
hasMore | boolean | — | Force the load-more banner when using entries (storybook/tests). |
state | "loading" | "error" | "empty" | — | Force a specific state for testing. |
onConfirmed | (transaction) => void | — | Called after a transaction is confirmed (status set to confirmed). |
onContextSubmitted | (transaction, message) => void | — | Notification fired when a comment is submitted (the agent chat is created and the categorization message sent). Receives the transaction and the message. |
onTagsChanged | (transaction, field, values) => void | — | Notification hook fired once per edited field after a successful tag write (see Tags). |
childrenrequired | ReactNode | — | Compound parts. |
Parts
Container
Always rendered. Fetches transactions and external accounts, and provides context.
| Part | Description |
|---|---|
Transactions.Root | Owns fetching, the confirm mutation, the context callback, and the inline-form state. |
Success
Renders when at least one transaction is available.
| Part | Description |
|---|---|
Transactions.Success | State wrapper. Compose the table inside. |
Transactions.Rows | Iterates the rows, providing a per-row context to each. |
Transactions.RowasChild? | Per-row wrapper. Adds data-status and data-direction. |
Transactions.DateasChild?, format? | Posting date — shows "Apr 30"; sets dateTime + a full-date title (pair with <time> via asChild). Pass format(date) to override. |
Transactions.DescriptionasChild? | The transaction's description. |
Transactions.AccountasChild? | Name of the external account the transaction belongs to. |
Transactions.AmountasChild?, format? | Signed amount (negative for money out). Adds data-direction (inflow/outflow). |
Transactions.StatusasChild?, format? | Lifecycle status label, plan-dependent — Done for you: Needs Attention / In Review / Confirmed; Do it yourself: Needs Attention / Confirmed (see Plan behaviour). Adds data-status. |
Transactions.CategoryasChild? | Name of the first category. |
Transactions.Split / Single | Gates that render only for split (multi-category) / single-category transactions. |
Transactions.Lines | Iterates the transaction's category lines, providing a per-line context. |
Transactions.LineNameasChild? | A split line's category name (inside <Lines>). |
Transactions.LineAmountasChild?, format? | A split line's signed amount (inside <Lines>). |
Transactions.HasTags | Renders children only when the business defines at least one tag field (see Tags). |
Transactions.Pending | Renders children while the transaction still needs review. |
Transactions.Confirmed | Renders children once the transaction's status is confirmed. |
Transactions.ConfirmasChild? | Button that confirms the row's transaction (sets its status to confirmed). |
Transactions.ProvideContextasChild? | Button that opens the inline context form for the row. |
Transactions.TriggerasChild? | Toggles the row's details panel on click (e.g. wrap the row to expand a split). |
Transactions.Details | Renders children while the row's details panel is expanded (the split breakdown). |
Transactions.Context | Renders children while the row's context form is open. |
Transactions.HasMore | Renders children (the load-more banner) only when another page can be fetched. |
Transactions.LoadMoreasChild? | Button/link that fetches and appends the next page. Sets data-loading while in flight. |
Loading
Renders while the fetch is in flight.
| Part | Description |
|---|---|
Transactions.Loading | State wrapper. Render skeleton rows inside. |
Empty
Renders when there are no transactions.
| Part | Description |
|---|---|
Transactions.Empty | State wrapper. Render an empty-state message inside. |
Error
Renders on fetch error.
| Part | Description |
|---|---|
Transactions.Error | State wrapper. Compose the error UI inside. |
Transactions.ErrorMessageasChild? | Renders the error message string. |
Transactions.RetryasChild? | Button that re-runs the fetch. |
Hooks
| Part | Description |
|---|---|
useTransactions() | Hook returning the full context (rows, confirm, submitContext, …). Also exposes the filters (statusFilter/accountFilter + setters and options), pagination (hasMore, loadMore, loadingMore), and the comment flow (contextPending, reviewingIds — the set of rows currently being reviewed). |
useTransactionsRow() | Hook returning the current row inside <Rows>. |
Tags
When tagFields isn't forced to [], every row exposes one Tag surface — a picker grouped by field, covering every tag field the business defines. A row can carry values from more than one field at once. Edits (via setRowTags on useTransactions()) write per field through the transactions PATCH merge map: the supplied list replaces that field's values, an empty list clears it, and fields the edit doesn't mention are left untouched.
A field carrying more than one value has the transaction's amount split evenly across those values in reports — there's no per-value amount to set. A value that doesn't exist yet on a field is created automatically (subject to allowCreateTag); matching is case-insensitive, so "NYC" and "nyc" are treated as the same value.
Writes are optimistic — the row updates immediately — and roll back silently if the write fails, consistent with the rest of the SDK, which never surfaces write errors to the UI.
Plan behaviour
Asset businesses are on one of two plans, and some components behave differently on each. On Done for you (the managedplan) a bookkeeper reviews and categorises the business's books for them; on Do it yourself (the diy plan) there is no bookkeeper, so the business keeps its own books. The plan is resolved from the business automatically — override it with the plan prop.
The review lifecycle differs because Done for you has a bookkeeper in the loop and Do it yourself doesn't. The component resolves the plan from the business (or the plan prop) and adjusts the labels, the status filter, and what happens when a row submits context:
| Behaviour | Done for youmanaged | Do it yourselfdiy |
|---|---|---|
| Status labels | Three labels: Needs Attention (awaiting the business), In Review (with the bookkeeper) and Confirmed. | Two labels: Needs Attention and Confirmed. With no bookkeeper, an in_review transaction also reads Needs Attention— it's the business's to handle. |
| Status filter options | Needs Attention / In Review / Confirmed. | Needs Attention / Confirmed — there is no bookkeeper↔business hand-off, so the business_pending option is dropped. |
Submitting context (ProvideContext → Context) | Runs the categorisation chat and leaves the transaction for the bookkeeper to pick up. | Runs the categorisation chat and, since there's no bookkeeper, advances the transaction into review (bookkeeper_pending) itself. |