User-Provided Cost Basis
Overview
When end-users transfer digital assets onto your platform, the initial acquisition information of the transfer-in transaction will be considered "missing cost basis" (see Inventory Key Terms). As a result, gains and losses cannot be accurately calculated.
Digital Asset exchanges that have built out a customer experience to accept user-provided cost-basis information can send the transfer information to Taxbit to calculate and maintain accurate inventory values. Taxbit leverages the user-provided cost basis values to calculate inventory and manage dispositions at the lot-level. Taxbit will also indicate impacted disposition items that have a user-provided cost basis value.
Creating Transfer Lots
A set of Transfer Lots
can be created and associated with a transfer-in transaction. A Transfer Lots item consists of an Acquisition Date (of the lot), Quantity (in the lot), and Cost Basis (value of lot at acquisition). You can leverage the Transfer-Lots APIs with the POST , GET and DELETE.
Transfer Lots can only be created for Transfer-In transactions
Creating transfer-lots for any other transaction type will result in a 400 error response.
In the following example, we will: walk through creating a transfer-in transaction (with missing cost basis), review inventory with missing cost basis, create the transfer lots representing user-provided cost basis, and review the impact to inventory.
post /v1/transaction (transfer-in)
First, we will show creating a transfer-in transaction of 1.75BTC. It has no cost basis information.
curl --request POST \
--url https://api.multi1.enterprise.taxbit.com/v1/transactions/external-id \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data '{
"account_id": "{{account_id}}",
"id": "{{transfer-in-transaction-id}}",
"datetime": "2024-01-01T00:00:00.000Z",
"type": "deposit",
"received": [
{
"asset_amount": {
"amount": "1.75",
"asset": {
"code": "BTC",
"type": "crypto"
}
}
}
],
"version": "2.0"
}'
{
"status": "success",
"message": "Transaction post successful."
}
get /v1/inventory
When we call the inventory, we will note that there is a missing_cost_basis = true
curl --request GET \
--url '{{base-url}}/v1/inventory?account_id={{account-id}}&asset_code=BTC' \
--header 'Authorization: Bearer {{token}}'
{
"data": {
"asset": {
"uuid": "9cd9f4d4-078b-4e44-a308-7662fec0f546",
"name": "Bitcoin",
"code": "BTC",
"type": "Crypto"
},
"fiat_asset": {
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396",
"name": "United States Dollar",
"code": "USD",
"type": "Fiat"
},
"summary": {
"latest_transaction_datetime": "2024-01-01T00:00:00.000Z",
"total_quantity": "1.75",
"total_cost": "0",
"average_unit_cost": "0",
"total_quantity_with_cost_basis": "0",
"total_quantity_missing_cost_basis": "1.75"
},
"lots": [
{
"id": "c73deecc-fd19-50cc-9ab4-2b024a76a23d",
"acquisition_datetime": "2024-01-01T00:00:00Z",
"term": "short-term",
"quantity": "1.75",
"missing_cost_basis": true
}
]
}
}
post /v1/transfer-lots
If a user provides cost-basis information for a transfer-in transaction, you can send that data as an array of transfer-lots on the source transaction.
curl --request POST \
--url '{{base_url}}/v1/transfer-lots/{{transfer-in-transaction-id}}' \
--header 'Authorization: Bearer {{token}}' \
--header 'Content-Type: application/json' \
--data '{
"transfer_lots": [
{
"quantity": ".5",
"cost_basis": "20000.00",
"acquisition_transaction_datetime": "2023-06-15T12:00:00Z"
},
{
"quantity": "1.0",
"cost_basis": "18050.50",
"acquisition_transaction_datetime": "2023-05-10T09:30:00Z"
},
{
"quantity": ".25",
"cost_basis": "17000.50",
"acquisition_transaction_datetime": "2023-04-25T14:45:00Z"
}
]
}'
get /v1/transfer-lots
You may retrieve transfer lots associated with a specific transaction after creating them.
curl --request GET
--url '{{base_url}}/v1/transfer-lots/transactions/{{transfer-in-transaction-id}}'
--header 'Authorization: Bearer {{token}}'
{
"transaction_id": "{{transfer-in-transaction-id}}",
"transfer_lots": [
{
"cost_basis": "20000",
"transaction_id": "{{transfer-in-transaction-id}}",
"created_datetime": "2024-08-09T21:10:08.975Z",
"acquisition_transaction_datetime": "2023-06-15T12:00:00Z",
"modified_datetime": "2024-08-09T21:10:08.975Z",
"quantity": "0.5"
},
{
"cost_basis": "18050.5",
"transaction_id": "{{transfer-in-transaction-id}}",
"created_datetime": "2024-08-09T21:10:08.975Z",
"acquisition_transaction_datetime": "2023-05-10T09:30:00Z",
"modified_datetime": "2024-08-09T21:10:08.975Z",
"quantity": "1"
},
{
"cost_basis": "17000.5",
"transaction_id": "{{transfer-in-transaction-id}}",
"created_datetime": "2024-08-09T21:10:08.975Z",
"acquisition_transaction_datetime": "2023-04-25T14:45:00Z",
"modified_datetime": "2024-08-09T21:10:08.975Z",
"quantity": "0.25"
}
]
}
get /v1/ inventory
Note that inventory will also be updated with calculations based on the respective transfer-lot values sent to Taxbit.
{
"data": {
"asset": {
"uuid": "9cd9f4d4-078b-4e44-a308-7662fec0f546",
"name": "Bitcoin",
"code": "BTC",
"type": "Crypto"
},
"fiat_asset": {
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396",
"name": "United States Dollar",
"code": "USD",
"type": "Fiat"
},
"summary": {
"latest_transaction_datetime": "2024-01-01T00:00:00.000Z",
"total_quantity": "1.75",
"total_cost": "55051",
"average_unit_cost": "31457.714285714285714286",
"total_quantity_with_cost_basis": "1.75"
},
"lots": [
{
"id": "29bb8990-60f6-5bff-b73b-e4f840025276",
"acquisition_datetime": "2023-04-25T14:45:00Z",
"term": "long-term",
"quantity": "0.25",
"fiat_asset_code": "USD",
"cost": "17000.5",
"unit_cost": "68002"
},
{
"id": "336218b1-ee25-5327-93a6-45167b9ddd56",
"acquisition_datetime": "2023-06-15T12:00:00Z",
"term": "long-term",
"quantity": "0.5",
"fiat_asset_code": "USD",
"cost": "20000",
"unit_cost": "40000"
},
{
"id": "6cc4608e-df72-5b9f-a80a-cf2086e02f7f",
"acquisition_datetime": "2023-05-10T09:30:00Z",
"term": "long-term",
"quantity": "1",
"fiat_asset_code": "USD",
"cost": "18050.5",
"unit_cost": "18050.5"
}
]
}
}
Validations
During a POST
, the quantity of assets of a set of transfer lots must match the transfer transaction’s quantity. If there is a mismatch in quantity, there will be a failed 400 response.
If a transaction with existing transfer lots is updated and the validation rules are broken, Taxbit will return the transfer lots with a 203 response.
During an update of a transaction with existing transfer lots, the following will conditionally occur:
- If transaction date-time moves backward, any impacted transfer lots where the transfer-lot timestamp is later than the transfer-transaction timestamp will be ignored, and missing cost basis lots will fill the remaining quantity of the transfer
- Calling a GET transfer-lots for this transaction will return a 203 response.
- If quantity of the transfer-in transaction changes, ignore all lots & create MCB lot for the transfer-in.
Downstream API Impacts
Creating transfer-lots with user-provided-cost-basis for values will have downstream impacts on Transactions and Gains items. Taxbit’s API can inform if there has been an impact or derivation from a user-provided-cost-basis value.
- Transactions GET – the
tag has_transfer_lot_data = true
if the cost basis was manually set on the transfer_in transaction - Gains (/v1/gains/cost-bases) GET –
account_owner_edited = true
when a gain item is impacted by a user-provided cost basis
Updated 2 months ago