User-provided cost basis
Attach the acquisition dates and costs a user gives you to a deposit that arrived without a cost basis.
Part of Handle transfers. When a user moves an asset onto your platform, the deposit's lot is missing cost basis. If the user 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-entered 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.
- A
depositalready sent, as in Handle transfers. The examples use that page's deposit,dep_40731: 0.75 ETH received on September 2. - The acquisition details the user entered 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.
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" }
]
}'{
"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 user acquired the lot.
effective_datetime sets the date the user-entered basis applies from. Without it, the lots apply from the time of the deposit. Platforms that collect a user'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
curl $BASE_URL/v1/transfer-lots/transactions/dep_40731 \
-H "Authorization: Bearer $TOKEN"{
"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-entered 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.
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 Inwhen 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 negativecost_basis. - 401. The bearer token is missing, invalid, or expired. Mint 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.
Parameters
Only the fields used above. The full schemas are in the Create transfer lots and Get transfer lots 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-entered basis applies from. Default: the time of the deposit. |
Where to go next
Retrieve inventory shows the deposit's lots with their new cost. Back to Handle transfers.
Updated 7 days ago
