Tax loss harvesting

Find lots that would sell at a loss, show them to the account owner, and sell exactly the lots they pick.

Part of Build tax center experiences. Tax loss harvesting means selling lots that are worth less than they cost, so the realized loss offsets gains. To support it, your app shows the account owner which lots would sell at a loss at today's price and lets them sell those lots specifically.

By the end of this page you have found an account's lots with an unrealized loss and sold one of them with SPECID (specific identification), so the realized loss comes from exactly that lot.

Before you begin

List the account's assets

Call GET /v1/inventory/summaries for the assets the account holds, as in Retrieve inventory. Each entry names an asset to check.

Price each asset's lots

For each asset, call GET /v1/inventory with its asset_code and your current price. The examples continue Set up inventory and gains: the account holds 1.5 ETH bought at $3,250, and ETH is now $2,900.

curl -G $BASE_URL/v1/inventory \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "account_id=acct_5f2e7d10" \
  --data-urlencode "asset_code=ETH" \
  --data-urlencode "price=2900"
{
  "data": {
    "asset": { "code": "ETH", "name": "Ethereum", "type": "Crypto", "uuid": "b7a005b5-f4d5-44ea-ae80-d4f9e8313558" },
    "lots": [
      {
        "id": "b72696f9-0f10-5827-94c3-289b6366a599",
        "acquisition_datetime": "2026-02-14T16:20:11Z",
        "term": "short-term",
        "quantity": "1.5",
        "fiat_asset_code": "USD",
        "cost": "4875.00",
        "unit_cost": "3250.00",
        "current_value": "4350.00",
        "unrealized_gain_loss": "-525.00",
        "percent_unrealized_gain_loss": "-0.10769"
      }
    ],
    "lots_ordered_by": "HIFO"
  }
}

Lots with a negative unrealized_gain_loss would sell at a loss. Show them with their term and keep their id, which the sale needs. Lots with missing_cost_basis: true have no cost to compare with, so leave them out.

Sell the chosen lots

When the account owner sells, send the sale with disposition_method set to SPECID and the chosen lots in inventory_lots on the sent line item, keyed by lot id. Here the account owner sells 0.5 ETH from the February lot:

curl -X POST $BASE_URL/v1/transactions/external-id \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "trade_88230",
    "account_id": "acct_5f2e7d10",
    "type": "trade",
    "datetime": "2026-09-22T15:12:00Z",
    "disposition_method": "SPECID",
    "sent": [{
      "asset_amount": { "amount": "0.5", "asset": { "code": "ETH", "type": "Crypto" } },
      "rates": [{ "amount": "2900.00", "asset": { "code": "USD", "type": "Fiat" } }],
      "inventory_lots": {
        "b72696f9-0f10-5827-94c3-289b6366a599": { "quantity": "0.5" }
      }
    }],
    "received": [{
      "asset_amount": { "amount": "1450.00", "asset": { "code": "USD", "type": "Fiat" } },
      "rates": [{ "amount": "1.00", "asset": { "code": "USD", "type": "Fiat" } }]
    }]
  }'

The lot quantities must add up to the line item's amount. Supported methods lists every SPECID rule. Once inventory has caught up, Retrieve gains shows the sale as a $175 short-term loss: 0.5 ETH sold for $1,450 against a cost of $1,625.

Where to go next