Partner Integration · API contract

CryptoTaxEdge classification API

You own the ledger, the chart of accounts, and the close workflow. You send transactions; we return the canonical category, tax treatment, confidence, and per-leg reasoning.
Endpoints
POST app.cryptotaxedge.com/v1/classify-batch Up to 100 transactions per call. Returns one result per tx; your tx_id is echoed back as id.
POST app.cryptotaxedge.com/v1/classify Single transaction by hash. Same result shape, one record.
MCP mcp.cryptotaxedge.com · classify_batch Optional — the same tool over JSON-RPC for agent-native stacks. Most integrations use the REST endpoints above.
Authentication

Each request carries a bearer token. Create your own API key in Settings → API keys — sign in (free, no credit card), click “Create API key”, and copy the token. Developer keys include 250 classifications a month on the free tier (~25,000 on Pro); the same key works on both the REST API and the MCP server. For partner integrations with volume pricing, contact us.

Authorization: Bearer YOUR_API_KEY

Rate limit is per-IP (300 req/min for authenticated requests, 60 req/min unauthenticated). tx_id is yours — we echo it back so you can correlate results to your records. chain is optional and auto-detected when omitted. We never return source or vendor internals.

Try it — sample transactions

Three known-good Ethereum hashes you can drop straight into a request:

Token swap ethereum
0x280710a5673a8ff1af7f623ddb5148417ac36539228d0eec8edb8a57b19383c2
Multi-step token-for-token exchange → category "swap".
Lending withdrawal ethereum
0x9b5693fc24d2e31c59317f53f7ca77b3d570ad86999bd22a4fc53a7d06a48da6
Withdraw collateral from a lending protocol → category "collateral_withdraw".
Request
curl -X POST https://app.cryptotaxedge.com/v1/classify-batch \
  -H 'Authorization: Bearer YOUR_PARTNER_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "hashes": [
      { "tx_id": "row_1", "hash": "0x280710a5673a8ff1af7f623ddb5148417ac36539228d0eec8edb8a57b19383c2", "chain": "ethereum" },
      { "tx_id": "row_2", "hash": "0x9b5693fc24d2e31c59317f53f7ca77b3d570ad86999bd22a4fc53a7d06a48da6", "chain": "ethereum" }
    ]
  }'

Agent-native stacks can call the same classify_batch tool over MCP (JSON-RPC 2.0) at mcp.cryptotaxedge.com — same parameters, same key. MCP setup →

Response — simple transaction
{
  "api_version": "v1",
  "hash": "0x280710a5673a8ff1af7f623ddb5148417ac36539228d0eec8edb8a57b19383c2",
  "chain": "ethereum",
  "category": "swap",
  "treatment": "disposal",
  "taxable": true,
  "confidence": 77,
  "needs_review": false,
  "ledger_action": "Trade",
  "grey_area": null,
  "assets": {
    "sent":     [ { "symbol": "stETH", "amount": "0.002297", "decimals": 18 } ],
    "received": [ { "symbol": "USDC",  "amount": "3.723749", "decimals": 6 } ],
    "gas": null
  }
}
Response — multi-step transaction (flash loan, batch NFT, bridge, DCA)

Complex transactions additionally return a per-leg breakdown plus a memo, so you can post the correct number of taxable events for a single on-chain transaction.

{
  "category": "swap",
  "treatment": "disposal",
  "confidence": 88,
  "parent": { "category": "swap", "description": "Flash-loan arbitrage: borrow, two swap legs, repay." },
  "legs": [
    { "leg_index": 0, "role": "flash_borrow", "category": "borrow", "taxable": false },
    { "leg_index": 1, "role": "arb_swap_1",  "category": "swap",   "taxable": true },
    { "leg_index": 2, "role": "arb_swap_2",  "category": "swap",   "taxable": true },
    { "leg_index": 3, "role": "flash_repay",  "category": "repay",  "taxable": false }
  ],
  "memo": "Borrow and repay are non-events; recognize gain or loss on the two swap legs."
}
Treatment semantics

treatment is one of disposal · income · non_taxable · expense · needs_review. confidence is an integer 0–100. When the engine cannot reach a confident verdict it returns needs_review: true with taxable: null — a deliberate deferral, never a silent guess, and never billed. Positions with more than one defensible treatment additionally return a grey_area block naming the basis and the alternate view.

Errors

Every error uses one envelope — { "error": { "code", "message" } } — with standard HTTP semantics:

HTTP 400  { "error": { "code": "invalid_hash",  "message": "hash must be a 0x-prefixed 64-hex EVM transaction hash or a base58 Solana signature" } }
HTTP 401  { "error": { "code": "unauthorized", "message": "auth required" } }
HTTP 404  { "error": { "code": "tx_not_found", "message": "transaction not found on the specified chain" } }
HTTP 429  { "error": { "code": "rate_limited", "message": "rate limit exceeded" } }
Canonical taxonomy

Every classification resolves to one of eleven stable categories. The field ledger_action carries the suggested ledger label; category carries the canonical type.

swap transfer income_receipt fee_payment borrow repay collateral_supply collateral_withdraw liquidity_add liquidity_remove unclassified