---
updatedAt: 2026-10-13T18:31:48.000Z
agentTools:
  projectIndex: https://apidocs.taxbit.com/llms.txt
---

# User-provided cost basis

Attach the acquisition dates and costs an account owner gives you to a deposit that arrived without a cost basis.

Part of [Handle transfers](https://apidocs.taxbit.com/docs/transfers). When an account owner moves an asset onto your platform, the deposit's lot is missing cost basis. If the account owner can tell you when they acquired the asset and what they paid, attach that to the deposit as transfer lots, and Taxbit uses it for inventory and gains.

By the end of this page you have attached user-provided lots to a deposit, read them back, and know how to replace or remove them.

## Before you begin

* A bearer token. See [Authenticate your tenant](https://apidocs.taxbit.com/docs/accessing-the-api).
* A `deposit` already sent, as in [Handle transfers](https://apidocs.taxbit.com/docs/transfers). The examples use that page's deposit, `dep_40731`: 0.75 ETH received on September 2.
* The acquisition details the account owner provided for the asset: for each lot, the quantity, what it cost, and when it was acquired.

## Create the transfer lots

Send the lots to `POST /v1/transfer-lots/transactions/{transactionId}`, where `{transactionId}` is your `id` for the deposit.

```bash
curl -X POST $BASE_URL/v1/transfer-lots/transactions/dep_40731 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transfer_lots": [
      { "quantity": "0.5", "cost_basis": "1400.00", "acquisition_transaction_datetime": "2025-11-03T12:00:00Z" },
      { "quantity": "0.25", "cost_basis": "825.00", "acquisition_transaction_datetime": "2026-03-18T12:00:00Z" }
    ]
  }'
```

```json
{
  "status": "success"
}
```

Each lot needs a `quantity` and a `cost_basis`, the lot's value at acquisition. `cost_basis` must not be negative; a negative value returns 400. `acquisition_transaction_datetime` is when the account owner acquired the lot.

`effective_datetime` sets the date the user-provided basis applies from. Without it, the lots apply from the time of the deposit. Platforms that collect an account owner's basis after a tax year has been filed usually set it to the first day of the current year, so earlier years stay as filed.

The lots' quantities must add up to the deposit's received amount, no lot's `acquisition_transaction_datetime` can be later than the deposit's datetime, and `effective_datetime` can't be earlier than the deposit's datetime; any of these returns 400.

## Read the lots back

```bash
curl $BASE_URL/v1/transfer-lots/transactions/dep_40731 \
  -H "Authorization: Bearer $TOKEN"
```

```json
{
  "transaction_id": "dep_40731",
  "transaction_type": "deposit",
  "transfer_lots": [
    {
      "quantity": "0.5",
      "cost_basis": "1400.00",
      "acquisition_transaction_datetime": "2025-11-03T12:00:00Z",
      "created_datetime": "2026-09-02T09:20:41Z",
      "modified_datetime": "2026-09-02T09:20:41Z"
    },
    {
      "quantity": "0.25",
      "cost_basis": "825.00",
      "acquisition_transaction_datetime": "2026-03-18T12:00:00Z",
      "created_datetime": "2026-09-02T09:20:41Z",
      "modified_datetime": "2026-09-02T09:20:41Z"
    }
  ]
}
```

A 203 instead of a 200 means the stored lots no longer pass the checks above, for example lots saved through the older transfer-lots endpoint, which didn't run them. The `warnings` array says which check. Send the lots again to fix it.

To read the lots of several transactions at once, call `GET /v1/transfer-lots/transactions` with the `account_id` and up to 25 `client_transaction_id` values, all from that account.

Elsewhere in the API, a transaction with user-provided lots carries the tag `has_transfer_lot_data` set to `"true"` in transaction reads, and a gain from those lots carries `account_owner_edited: true` in `GET /v1/gains`.

## Replace or remove the lots

Posting lots again for the same deposit replaces the existing ones. To remove them and return the deposit to missing cost basis, delete them; the request returns 204.

```bash
curl -X DELETE $BASE_URL/v1/transfer-lots/transactions/dep_40731 \
  -H "Authorization: Bearer $TOKEN"
```

## If the request fails

* **400.** The lots don't fit the deposit, or a field failed validation. The message says which: `Transaction not a Transfer In` when the transaction isn't a deposit, `Summed lot quantity (X) doesn't equal transfer-in quantity (Y)` when the quantities don't add up, `Transfer lots with acquisition_transaction_datetime after transfer-in datetime (X) are invalid.` when a lot was acquired after the deposit, `effective_datetime (X) cannot be before desposit transaction datetime (Y)` when the effective date is too early (the misspelling is in the API's message), or a negative `cost_basis`.
* **401.** The bearer token is missing, invalid, or expired. Request a new one and retry.
* **404.** No transaction has that `id`: `Transaction not found`. Send the deposit first.
* **429.** Too many requests. Slow down and retry.

The [Errors](https://apidocs.taxbit.com/docs/errors) page has every error shape, the rate limits, and which calls are safe to retry.

## Parameters

Only the fields used above. The full schemas are in the [Create transfer lots](https://apidocs.taxbit.com/reference/post_transfer-lots-transactions-transaction-id) and [Get transfer lots](https://apidocs.taxbit.com/reference/get_transfer-lots-transactions-transaction-id) references.

| Field                                              | Type   | Required | Description                                                                                |
| -------------------------------------------------- | ------ | -------- | ------------------------------------------------------------------------------------------ |
| `transfer_lots`                                    | array  | Required | The lots. Replaces any existing lots on the deposit.                                       |
| `transfer_lots[].quantity`                         | string | Required | Amount of the asset in the lot.                                                            |
| `transfer_lots[].cost_basis`                       | string | Required | Non-negative value of the lot at acquisition.                                              |
| `transfer_lots[].acquisition_transaction_datetime` | string | Optional | ISO 8601 timestamp of when the lot was acquired.                                           |
| `effective_datetime`                               | string | Optional | ISO 8601 timestamp the user-provided basis applies from. Default: the time of the deposit. |

## Where to go next

[Retrieve inventory](https://apidocs.taxbit.com/docs/consuming-inventory) shows the deposit's lots with their new cost. Back to [Handle transfers](https://apidocs.taxbit.com/docs/transfers).

# Sibling pages

* [Internal personal transfers](https://apidocs.taxbit.com/docs/internal-personal-transfers.md)
* [Gifts](https://apidocs.taxbit.com/docs/gifts.md)
* [Inheritance](https://apidocs.taxbit.com/docs/inheritance.md)