Skip to content

US Tax Reporting

The Tax Reporting API turns a wallet’s on-chain history into US/IRS-ready filings. Qeychain runs every transaction through a FIFO cost-basis engine, classifies each disposal as short- or long-term, recognizes ordinary income (staking, airdrops, mining, interest) at fair market value, and renders the results as the exact line items the IRS expects.

Everything on this page operates on the supported /api/v1 surface and returns the standardized response envelope described in Responses & Errors.

  • Form 8949 — Sales and Other Dispositions of Capital Assets, split into Part I (short-term) and Part II (long-term). Available as JSON, CSV, and PDF.
  • Schedule 1 — ordinary crypto income (staking, airdrops, mining, DeFi interest) reported at FMV for Line 8z, with per-event detail.
  • Tax summary with estimated liability — net capital gains/losses, ordinary income, and an estimated federal tax figure (including NIIT) at rates you supply.
  • FIFO cost basis — deterministic, IRS-compliant lot matching with short-/long-term holding classification.
  • Wash-sale detection — fully implemented, opt-in (off by default; see Wash-sale detection).
  • Async generation — kick off a background job for very large wallets and poll for the result.

Valuation is in USD. Supported assets are fungible tokens and native coins across EVM chains (0x…), Bitcoin, and Solana. NFTs are not tracked.

All tax endpoints require authentication. Send your access token as a Bearer JWT in the Authorization header:

GET /api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/8949?tax_year=2024 HTTP/1.1
Host: api.qeychain.xyz
Authorization: Bearer <your-access-token>

Unauthenticated requests receive 401 UNAUTHORIZED. See the Authentication guide for how to obtain a token.

The reporting endpoints live under /api/v1/wallets/{address}/tax-reports/…. They share these inputs:

Name Type Required Description
address path string yes Wallet address. EVM (0x…), Bitcoin, or Solana.
tax_year query int yes Four-digit year between 2009 and the current year.
taxpayer_timezone query string no IANA timezone used to classify a transaction’s calendar date and holding period. Defaults to America/New_York.
owned_wallets query string no Every wallet you own, so transfers between your own wallets are recognized as non-taxable rather than sells. Repeat the param or pass a comma-separated list.

GET /api/v1/wallets/{address}/tax-reports/8949

Returns every taxable disposal for the year as Form 8949 line items, split into short-term (Part I) and long-term (Part II), with category and grand totals. Items are sorted by date sold.

Terminal window
curl -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/8949?tax_year=2024"
{
"success": true,
"data": {
"tax_year": 2024,
"address": "0x742d35cc6634c0532925a3b844bc454e4438f44e",
"short_term_items": [
{
"description": "1.5 ETH",
"date_acquired": "03/14/2024",
"date_sold": "09/02/2024",
"proceeds": "4200.00",
"cost_basis": "3600.00",
"adjustment_code": null,
"adjustment_amount": null,
"gain_or_loss": "600.00",
"is_long_term": false
}
],
"short_term_proceeds": "4200.00",
"short_term_cost_basis": "3600.00",
"short_term_adjustments": "0.00",
"short_term_gain_loss": "600.00",
"long_term_items": [
{
"description": "0.25 BTC",
"date_acquired": "01/20/2022",
"date_sold": "06/11/2024",
"proceeds": "16250.00",
"cost_basis": "9500.00",
"adjustment_code": null,
"adjustment_amount": null,
"gain_or_loss": "6750.00",
"is_long_term": true
}
],
"long_term_proceeds": "16250.00",
"long_term_cost_basis": "9500.00",
"long_term_adjustments": "0.00",
"long_term_gain_loss": "6750.00",
"total_proceeds": "20450.00",
"total_cost_basis": "13100.00",
"total_gain_loss": "7350.00",
"disposal_count": 2
},
"meta": {
"request_id": "b3f1c2a4-9d70-4c1e-8f2a-2c9d5e7a1f04",
"timestamp": "2026-01-15T09:12:33.412Z",
"version": "1.0.0"
}
}
Field Type Description
description string Quantity and symbol, e.g. 1.5 ETH (Form 8949 column a).
date_acquired string MM/DD/YYYY. Renders VARIOUS when a lot has no reliable acquisition date.
date_sold string MM/DD/YYYY disposal date in the taxpayer timezone.
proceeds decimal Sale price in USD (column d).
cost_basis decimal FIFO cost or other basis in USD (column e).
adjustment_code string, nullable W when a wash-sale adjustment applies (column f), otherwise null.
adjustment_amount decimal, nullable Disallowed loss added back (column g), otherwise null.
gain_or_loss decimal Gain (positive) or loss (negative) in USD (column h).
is_long_term boolean true if held more than one year.

GET /api/v1/wallets/{address}/tax-reports/8949/export

Same data as above, returned as a downloadable file instead of JSON.

Name Type Required Description
format query string no csv (default) or pdf.
tax_year query int yes Four-digit tax year.
taxpayer_timezone query string no Defaults to America/New_York.
Terminal window
# CSV (spreadsheet-ready, with short-term, long-term, and summary rows)
curl -L -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/8949/export?tax_year=2024&format=csv" \
-o Form8949_2024.csv
# PDF (formatted Part I / Part II tables with totals)
curl -L -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/8949/export?tax_year=2024&format=pdf" \
-o Form8949_2024.pdf

Both responses are file downloads (text/csv or application/pdf) with a Content-Disposition attachment header — not the JSON envelope.

GET /api/v1/wallets/{address}/tax-reports/schedule-1

Reports crypto received as ordinary income, recognized at fair market value on the date of receipt, categorized for Schedule 1, Line 8z. Each category includes the individual events for record-keeping.

Categories: staking rewards, airdrops, mining rewards, and DeFi interest, plus an other bucket.

Terminal window
curl -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/schedule-1?tax_year=2024"
{
"success": true,
"data": {
"tax_year": 2024,
"address": "0x742d35cc6634c0532925a3b844bc454e4438f44e",
"taxpayer_timezone": "America/New_York",
"staking_income": "812.40",
"staking_events": [
{
"date": "2024-05-06T14:03:11Z",
"type": "staking",
"symbol": "ETH",
"quantity": "0.240000000",
"fair_market_value": "742.10",
"tx_hash": "0x9c1f…8ab2",
"chain": "ethereum"
}
],
"airdrop_income": "150.00",
"airdrop_events": [],
"mining_income": "0.00",
"mining_events": [],
"defi_interest_income": "64.18",
"defi_interest_events": [],
"other_income": "0.00",
"other_events": [],
"total_ordinary_income": "1026.58",
"event_count": 3
},
"meta": {
"request_id": "7a2e1b90-3c44-4f0a-bb31-0e9d6f2c5a11",
"timestamp": "2026-01-15T09:14:02.981Z",
"version": "1.0.0"
}
}

Each event carries date, type, symbol, quantity, fair_market_value (the income amount in USD at receipt), and — when available — tx_hash and chain.

GET /api/v1/wallets/{address}/tax-reports/summary

Combines capital gains, ordinary income, and wash-sale disallowances for the year, then computes an estimated federal tax liability at rates you provide. The estimate is a planning aid, not a filed figure.

Name Type Required Description
tax_year query int yes Four-digit tax year.
short_term_rate query float no Short-term capital gains rate 0–1. Default 0.37.
long_term_rate query float no Long-term capital gains rate 0–1. Default 0.20.
ordinary_income_rate query float no Ordinary income rate 0–1. Default 0.37.
taxpayer_timezone query string no Default America/New_York.

The estimate also applies the 3.8% Net Investment Income Tax (NIIT) on net investment income plus ordinary income.

Terminal window
curl -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/summary?tax_year=2024&long_term_rate=0.15"
{
"success": true,
"data": {
"address": "0x742d35cc6634c0532925a3b844bc454e4438f44e",
"tax_year": 2024,
"taxpayer_timezone": "America/New_York",
"total_capital_gains": "7350.00",
"net_short_term_gains": "600.00",
"net_long_term_gains": "6750.00",
"total_capital_losses": "0.00",
"net_short_term_losses": "0.00",
"net_long_term_losses": "0.00",
"wash_sale_disallowances": "0.00",
"wash_sale_count": 0,
"total_ordinary_income": "1026.58",
"staking_income": "812.40",
"airdrop_income": "150.00",
"mining_income": "0.00",
"defi_interest_income": "64.18",
"other_income": "0.00",
"estimated_tax_liability": {
"short_term_tax": "222.00",
"long_term_tax": "1012.50",
"ordinary_income_tax": "379.83",
"niit_tax": "318.14",
"total_estimated_tax": "1932.47",
"rates_used": {
"short_term_rate": "0.37",
"long_term_rate": "0.15",
"ordinary_income_rate": "0.37",
"niit_rate": "0.038"
}
},
"disposal_count": 2,
"income_event_count": 3
},
"meta": {
"request_id": "f5d2c7e1-6a48-4b93-9c2e-1d3f8b0a7e56",
"timestamp": "2026-01-15T09:15:44.220Z",
"version": "1.0.0"
}
}

POST /api/v1/wallets/{address}/tax-reports/generate

For very large wallets, generate a report in the background instead of waiting on a synchronous request. The call returns a job_id; poll the Jobs API for status and the finished result.

Name Type Required Description
tax_year query int yes Four-digit tax year.
report_type query string no full (default), 8949, schedule-1, or summary.
format query string no json (default), csv, or pdf.
taxpayer_timezone query string no Default America/New_York.
Terminal window
curl -X POST -H "Authorization: Bearer $QEYCHAIN_TOKEN" \
"https://api.qeychain.xyz/api/v1/wallets/0x742d35cc6634c0532925a3b844bc454e4438f44e/tax-reports/generate?tax_year=2024&report_type=8949&format=pdf"
{
"success": true,
"data": {
"job_id": "a1c9e4f2-70b8-4d5a-9f11-6b2c3d4e5f60",
"status": "pending",
"poll_url": "/api/v1/jobs/a1c9e4f2-70b8-4d5a-9f11-6b2c3d4e5f60",
"estimated_duration_seconds": 30
},
"meta": {
"request_id": "c0b1a2d3-4e5f-6789-abcd-ef0123456789",
"timestamp": "2026-01-15T09:16:10.004Z",
"version": "1.0.0"
}
}

Poll GET /api/v1/jobs/{job_id} for status (pending, processing, completed, failed) and, once complete, retrieve the output. See the Jobs endpoints in the API Reference for the full lifecycle.

Qeychain computes cost basis with FIFO — the oldest lot of an asset is consumed first on each disposal. This is applied consistently across Form 8949, Schedule 1, and the tax summary.

  • Gas fees paid to acquire an asset are added to that lot’s cost basis, per IRS guidance, reducing taxable gain on later disposal.
  • Ordinary income (staking, airdrops, mining, interest) is recognized at fair market value on the date received; that FMV becomes the cost basis of the received lot.
  • Non-taxable events — transfers between your own wallets, bridges, wrap/unwrap, stake/unstake — preserve cost basis and do not realize gain or loss. Pass owned_wallets so self-transfers are classified correctly.

Holding period follows IRS calendar-date rules, not raw 24-hour periods:

  • Long-term = held more than one year (disposed after the one-year anniversary of acquisition). Leap years are handled correctly, so exactly one year is treated as short-term.
  • Short-term = held one year or less.

Dates are evaluated in the taxpayer_timezone you supply, so a disposal near midnight is assigned to the correct calendar day.

Qeychain includes a complete wash-sale engine (30-day window before and after a loss, proportional loss disallowance, and cross-chain “substantially identical” matching such as ETH / WETH / stETH). When a wash sale is detected, the affected Form 8949 line item carries adjustment code W and the disallowed loss is added to the replacement lot’s basis.

Unrealized gains, harvesting, and TurboTax export

Section titled “Unrealized gains, harvesting, and TurboTax export”
  • Unrealized gain/loss — current, per-position unrealized G/L (open lots marked to market) is available from the Holdings API rather than the tax endpoints. See the Holdings guide.
  • Tax-loss harvesting and TurboTax TXF export are available on Qeychain’s backward-compatible /api/… surface (/api/reports/tax-loss-opportunities/{address} and /api/tax-summary/{address}/export/turbotax). They use the same FIFO engine.
  1. Pull Form 8949 (/tax-reports/8949) for each tax_year and carry the Part I / Part II totals onto your Schedule D.
  2. Pull Schedule 1 (/tax-reports/schedule-1) and report total_ordinary_income on Line 8z.
  3. Use /tax-reports/summary for a liability estimate at your marginal rates while planning.
  4. Always pass every wallet you control via owned_wallets so internal transfers are not counted as taxable disposals.