# Transaction-Level and Item-Level Expenses

Every expense Sail classifies starts as either a transaction or an item. This page explains the difference, how enrichment connects them, and why Sail keeps them separate instead of merging everything into one combined view.

## What an expense is

An expense is the core unit Sail works with, a transaction or a purchased item that Sail classifies for Section 213(d) eligibility. Every expense comes from one of four sources (`source_type`):

* A card or bank connection
* A store connection
* A pushed external transaction
* An uploaded receipt

Which source produced an expense determines whether you get transaction-level or item-level detail. See the full field list in [List Expenses](/reference/expenses/get-users-user-id-expenses).

## Transaction-level data

A card or bank connection reports one expense per transaction, the same level of detail your bank statement shows:

* A merchant
* A date
* An amount

On the [`Expense`](/reference/expenses/get-users-user-id-expenses) object, this shows up as `origin.type: transaction`, with `origin.detail` carrying the raw bank descriptor (for example, `WALGREENS #4821 RX`).

Transaction-level data tells you that a purchase happened and where, but not what was actually bought. A $49.00 charge at Walgreens could be a prescription, a birthday card, or both in the same basket. That ambiguity is part of what drives some expenses into `itemization_required` during classification. See [Expense Classification](/docs/concepts/expense-classification) for all four classification outcomes.

## Item-level data

A store connection, where a user logs into a merchant directly through Sail's [Connect Account Widget](/docs/concepts/connect-widget) (Amazon, Walgreens, Target, CVS, Walmart, and Costco, among others), reports individual products instead of one transaction total. The same is true for a receipt upload once it's processed. On the [`Expense`](/reference/expenses/get-users-user-id-expenses) object, this shows up as `origin.type: product`, with `origin.detail` carrying the product title.

Item-level data resolves the ambiguity transaction-level data can't, Sail classifies each item on its own, so a prescription and a birthday card from the same store visit no longer have to share one eligibility outcome.

## How enrichment links the two

When a card or bank transaction's merchant is one Sail can also connect to directly, the expense's `merchant.supported_merchant_id` field is set (for example, `mer_costco`). A non-null `supported_merchant_id` is the signal to prompt the user to connect that store, so future purchases at the same merchant get item-level detail instead of a flat transaction total. The same signal applies to transactions you push yourself through an external connection. Connecting a matching store login enriches your pushed data with item-level detail too.

Whether that item-level data comes from a store connection or from an itemized receipt, the resulting item-level expenses carry `parent_expense_id`, pointing back to the original transaction-level expense they enriched. See [Expense Classification](/docs/concepts/expense-classification) for when itemization is required.

{/* ASSUMPTION, NOT CONFIRMED (2026-08-19): not pursuing further with Jonah for V0. Docs proceed on the assumption that a transaction-level expense with parent_expense_id children does not get double-counted in expenses/summary totals, even though no field (Expense.status is being removed with nothing replacing it, per [[08-expense-status-removal]]) currently confirms a mechanism for that. This is a deliberate, unverified working assumption made under deadline pressure, not a confirmed fact — revisit if this surfaces as a real support question post-launch. */}

## Why Sail keeps them separate

Sail doesn't merge a transaction and its item-level detail into one combined record. Each stays its own expense, connected only through `supported_merchant_id` or `parent_expense_id`. This is deliberate, a flat, item-level view lets you classify at whatever level of detail you actually have, without waiting for every source to be connected before anything becomes usable.

## Data sources at a glance

Because each source stays separate rather than merging into one record, here's exactly what each one produces on its own.

| Source (`source_type`) | Produces | Connected through |
| :--- | :--- | :--- |
| `card` | Transaction-level | A card or bank connection |
| `store` | Item-level | A store or merchant connection |
| `external` | Transaction-level, unless enriched | A pushed transaction, through your own external connection |
| `receipt_upload` | Item-level | An uploaded receipt |

## Next steps

* To connect a user's card, bank, or store accounts and start retrieving expenses, see [Enrich Transactions with Item-Level Data](/docs/guides/enrich-transactions-with-item-level-data).
* To see how Sail classifies an expense's HSA/FSA eligibility, see [Expense Classification](/docs/concepts/expense-classification).
* To see the three kinds of account connections Sail supports and what each produces, see [Account Connections](/docs/concepts/account-connections).