@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:read
  • transaction:update
  • external_account:read
  • business:read
  • tag:read
  • journal_entry:read
  • journal_entry:create

API reference

Root props

PropTypeDefaultDescription
yearnumberOverride the AssetProvider's year for the date range.
monthnumber | nullOverride the AssetProvider's month (1-12); null forces the whole year. Omit to inherit the provider's month.
startDatetimestringISO datetime overriding the start of the provider-derived year/month period.
endDatetimestringISO datetime overriding the end of the provider-derived year/month period.
accountIdsstring[]Only include transactions for these external account ids.
ledgerTypeLedgerTypeOnly 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.
ledgerSubtypeLedgerSubTypeOnly 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.
defaultStatusFilterstringPre-select the status filter ("business_pending" | "bookkeeper_pending" | "confirmed", or "all"). Uncontrolled — the user can still change it.
defaultAccountFilterstringPre-select the account filter (an external account id, or "all"). A specific account overrides accountIds. Uncontrolled — the user can still change it.
pageSizenumberPage size passed to the API.
entriesTransactionOverride[]Override the rows shown (skips the API fetch). Used by storybook/tests.
tagFieldsTransactionTagField[]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.
allowCreateTagbooleantrueAllow 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".
hasMorebooleanForce the load-more banner when using entries (storybook/tests).
state"loading" | "error" | "empty"Force a specific state for testing.
onConfirmed(transaction) => voidCalled after a transaction is confirmed (status set to confirmed).
onContextSubmitted(transaction, message) => voidNotification 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) => voidNotification hook fired once per edited field after a successful tag write (see Tags).
childrenrequiredReactNodeCompound parts.

Parts

Container

Always rendered. Fetches transactions and external accounts, and provides context.

PartDescription
Transactions.RootOwns fetching, the confirm mutation, the context callback, and the inline-form state.

Success

Renders when at least one transaction is available.

PartDescription
Transactions.SuccessState wrapper. Compose the table inside.
Transactions.RowsIterates the rows, providing a per-row context to each.
Transactions.Row
asChild?
Per-row wrapper. Adds data-status and data-direction.
Transactions.Date
asChild?, format?
Posting date — shows "Apr 30"; sets dateTime + a full-date title (pair with <time> via asChild). Pass format(date) to override.
Transactions.Description
asChild?
The transaction's description.
Transactions.Account
asChild?
Name of the external account the transaction belongs to.
Transactions.Amount
asChild?, format?
Signed amount (negative for money out). Adds data-direction (inflow/outflow).
Transactions.Status
asChild?, 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.Category
asChild?
Name of the first category.
Transactions.Split / SingleGates that render only for split (multi-category) / single-category transactions.
Transactions.LinesIterates the transaction's category lines, providing a per-line context.
Transactions.LineName
asChild?
A split line's category name (inside <Lines>).
Transactions.LineAmount
asChild?, format?
A split line's signed amount (inside <Lines>).
Transactions.HasTagsRenders children only when the business defines at least one tag field (see Tags).
Transactions.PendingRenders children while the transaction still needs review.
Transactions.ConfirmedRenders children once the transaction's status is confirmed.
Transactions.Confirm
asChild?
Button that confirms the row's transaction (sets its status to confirmed).
Transactions.ProvideContext
asChild?
Button that opens the inline context form for the row.
Transactions.Trigger
asChild?
Toggles the row's details panel on click (e.g. wrap the row to expand a split).
Transactions.DetailsRenders children while the row's details panel is expanded (the split breakdown).
Transactions.ContextRenders children while the row's context form is open.
Transactions.HasMoreRenders children (the load-more banner) only when another page can be fetched.
Transactions.LoadMore
asChild?
Button/link that fetches and appends the next page. Sets data-loading while in flight.

Loading

Renders while the fetch is in flight.

PartDescription
Transactions.LoadingState wrapper. Render skeleton rows inside.

Empty

Renders when there are no transactions.

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

Error

Renders on fetch error.

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

Hooks

PartDescription
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:

BehaviourDone for youmanagedDo it yourselfdiy
Status labelsThree 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 optionsNeeds Attention / In Review / Confirmed.Needs Attention / Confirmed — there is no bookkeeper↔business hand-off, so the business_pending option is dropped.
Submitting context (ProvideContextContext)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.