{"openapi":"3.1.0","info":{"title":"Cosmos Tax API","version":"1.5.0","description":"Tax records for Cosmos Hub, read straight from an index of every block: taxable events, a double-entry journal, open lots, CARF and DAC8 summaries, past-date balances, validator statements and where commission went, plus the IRS forms and tax-software files the website produces. Every USD value cites a published, versioned pricing methodology. The v1 reads need no sign-up and no key.\n\n**Coverage**: Cosmos Hub mainnet (cosmoshub-4) from genesis on 2021-02-18. The history backfill is still filling earlier years: `/api/tax/v1/index-coverage` gives per-year coverage, and every report and export says whether its own period is complete (`index_coverage` in JSON bodies, the X-Index-Coverage headers on JSON and CSV, and a -not-fully-indexed marker in download filenames). Until the Gaia v6 upgrade (block 8,695,000 on 2021-12-14) the Hub emitted no coin_received or coin_spent events, so events before then are read from messages and module events, and past-date balances start at the end of 2021-12-14: an earlier date is refused with 409, as is a date before Gaia v15 (block 19,639,600 on 2024-03-20) when the wallet changed its stake between that date and the upgrade. Governance votes and other non-taxable activity are excluded. These are records for tax preparation, not tax advice.\n\n**Pricing**: one USD reference price per denom per UTC day (`/api/tax/v1/methodology`, v17 since 2026-11-09). IBC tokens are priced as their home-chain asset after their denom trace is proven hop by hop; Gravity DEX deposits, withdrawals and swaps are read from the block's batch settlement events. A row with no price is flagged `price_missing` and left out of USD totals rather than counted as zero.\n\n**Wallet-by-wallet**: cost basis and capital-gain lots are computed separately per address and never pooled across wallets (universal basis pooling ended 2025-01-01 under Rev. Proc. 2024-28). A multi-address query returns each wallet's own events/lots concatenated, each attributable to its address; combined totals shown anywhere (e.g. a summary card) are a sum of independent per-wallet figures, not a shared basis pool.\n\n**Flagged receipts**: a report refuses with 409 `asset_review_required` while a receipt in its period is suspected spam or has a token identity that does not match its denom. `/api/tax/v1/asset-review` lists them with their decision keys; send the decisions as `asset_decisions` (nothing is stored).\n\n**Rate limit**: 60 requests per 60 seconds per client IP across /api/tax/v1. Every answer carries `RateLimit` and `RateLimit-Policy` (IETF draft) and X-RateLimit-Limit, -Remaining and -Reset; over the limit is a 429 problem with Retry-After.\n\n**Authentication**: none for /api/tax/v1 and the Files endpoints. Saved reports, entities and preferences take the site session or an API key created under Account (`Authorization: Bearer blk_...`) with the `tax:read` or `tax:write` scope. The delegator-report widget takes its own per-validator `api_key`.\n\n**Versioning**: the path carries the major version, which changes only for a breaking change. Within v1, fields, endpoints and enum values are added without notice, so ignore members you do not know. A removal is announced in the changelog (/api-docs/changelog) at least 90 days ahead and the endpoint sends Deprecation and Sunset headers until then. The methodology_version in each response says which published pricing rules made its USD values.\n\n**Discover first**: `/api/tax/v1/catalog` lists every event category the indexer classifies (and whether it is taxable), the reward triggers, the CosmWasm contracts and protocols it knows, the bookkeeping tags, the export formats and the Gaia releases it has reviewed. `/api/tax/v1/tags` is the tag vocabulary for the `tags` parameter.\n\nThe raw document is served at `/api/tax/v1/openapi.json`; a plain-text orientation for agents is at `/llms.txt`; service health is on /status and the disclosure policy on /security. Every error is an RFC 9457 problem (`application/problem+json`) with a stable `code`, every response carries `X-Request-Id`, rate-limited endpoints send `RateLimit` and `RateLimit-Policy`, and a 429 or 503 carries `Retry-After`. Authenticate with the site session or an API key (`Authorization: Bearer blk_...`, created under Account). Full conventions: https://bryanlabs.net/api-docs/conventions."},"servers":[{"url":"/","description":"bryanlabs.net"}],"tags":[{"name":"Events","description":"Taxable events for one or more addresses, and the flagged receipts that need a decision before any report is produced."},{"name":"Balances","description":"Wallet holdings: current, at the end of a past day, and quarter-end and year-end statements."},{"name":"Pricing","description":"Published FMV methodology and the ATOM/USD price series it generates."},{"name":"Validators","description":"Validator operator statements, where commission went, on-chain jurisdiction attestations, and the delegator-report widget."},{"name":"Books","description":"Controller reports: general-ledger journal, open positions, and the CARF and DAC8 summary."},{"name":"Reference","description":"What the indexer tracks, the tag vocabulary, and chain release tracking."},{"name":"Files","description":"The files the report page produces: IRS forms, tax-software and books exports, period statements, the evidence bundle and 1099-DA reconciliation. No sign-in; POST a JSON body with the same chain, addresses, period, asset decisions and tags as /api/tax/v1/events."},{"name":"Account settings","description":"A signed-in person's tax entities and preferences. Session or API key (tax:read, tax:write)."},{"name":"Saved reports","description":"A signed-in person's saved report queries with their tags and asset decisions. Session or API key (tax:read, tax:write)."}],"paths":{"/api/tax/v1/events":{"get":{"tags":["Events"],"summary":"Tax events","description":"Every taxable and record-only event for one or more addresses in a period: staking rewards and commission, income, transfers, IBC in and out, swaps (including Gravity DEX batch settlements), fees, delegations and NFTs, each with its USD value at that day's reference price. A row with no reference price for its denom and day is flagged `price_missing` and left out of USD totals, never valued at $0 (/api/tax/v1/methodology, fallback_order). The response says whether its own period is fully indexed: `index_coverage` in the JSON body and the X-Index-Coverage headers on JSON and CSV alike. A period that is not fully indexed still answers, with the missing years named, rather than failing. Events before the Gaia v6 upgrade (2021-12-14) are read from messages and module events, because the chain emitted no coin events then. Answers 409 asset_review_required while a flagged receipt in the period has no decision.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"Comma-separated public address(es), e.g. cosmos1abc,cosmos1def. Each wallet is computed on its own; see Wallet-by-wallet above."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["all","rewards","staking","income","transfers","ibc_in","ibc_out","ibc","swaps","fees","delegations","nfts"],"default":"all"},"example":"rewards","description":"Event category. Default: all."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Bookkeeping tags as a JSON object: {\"<TX_HASH>\": \"internal_transfer\", \"<TX_HASH>:<denom>\": \"spam\"}. Vocabulary at /api/tax/v1/tags. Changes the treatment of the tagged row in every export; never stored."},{"name":"asset_decisions","in":"query","required":false,"schema":{"type":"string"},"description":"Decisions for flagged receipts (suspected spam or identity mismatch), as a JSON object. Keys are one of: a record_id from /api/tax/v1/asset-review (one receipt), denom:<raw_denom> (every flagged receipt of that token in the period), or policy:spam (every receipt flagged as suspected spam that has no more specific decision). The most specific key wins. Values: {\"mode\": \"exclude\"} treats the receipts as valueless (no income, zero basis, kept out of tax-software imports); {\"mode\": \"override\", \"token\": \"ATOM\", \"quantity\": \"29.55\", \"value_usd\": \"120.10\", \"cost_basis_usd\": \"120.10\", \"acquired_date\": \"2026-03-04\"} supplies totals for one receipt; {\"mode\": \"override\", \"token\": \"FOO\", \"unit_value_usd\": \"0.5\"} under a denom: key prices each receipt of that token at quantity times unit value on its own date. policy:spam is exclude only. An unknown record_id is a 400; an idle denom: or policy: key is accepted (and listed in unmatched_decision_keys on /asset-review) so standing rules can be sent with every request. Up to 500 entries and 256 KiB. Nothing is stored server-side."},{"name":"spam_policy","in":"query","required":false,"schema":{"type":"string","enum":["ask","valueless"],"default":"ask"},"description":"Shorthand for the policy:spam decision: valueless adds {\"policy:spam\": {\"mode\": \"exclude\"}} to asset_decisions, so every suspected-spam receipt without a more specific decision is carried at zero."},{"name":"start","in":"query","required":false,"schema":{"type":"string"},"example":"2026-10-01","description":"Inclusive start, YYYY-MM-DD (from 00:00 UTC) or RFC 3339. Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string"},"example":"2026-10-31","description":"Inclusive end, YYYY-MM-DD (through 23:59:59 UTC) or RFC 3339. Default: now."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"json (default) or csv, one row per event with the same columns as the Generic CSV export."}],"responses":{"200":{"description":"Tax events (JSON) or a CSV file when format=csv.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"cosmoshub"},"type":{"type":"string","example":"rewards"},"addresses":{"type":"array","items":{"type":"string"}},"start":{"type":"string","nullable":true},"end":{"type":"string","nullable":true},"summary":{"type":"object","properties":{"taxableEvents":{"type":"integer","example":42},"recordOnlyEvents":{"type":"integer","example":0,"description":"Rows kept for completeness that never reach Form 8949 (taxable false)."},"stakingRewards":{"type":"number","example":12.34},"incomeUsd":{"type":"number","example":0.91},"totalReceived":{"type":"number","example":12.34},"totalSent":{"type":"number","example":0},"totalFees":{"type":"number","example":0.01},"symbol":{"type":"string","example":"ATOM"},"firstDate":{"type":"string","example":"2026-01-02 09:14:00"},"lastDate":{"type":"string","example":"2026-06-20 21:03:00"},"priceMissingCount":{"type":"integer","example":0,"description":"Rows with priceMissing true. Their valueUsd is 0, meaning unknown, so incomeUsd understates income by their value."},"decimalsAssumedCount":{"type":"integer","example":0,"description":"Rows whose denom decimals could not be resolved, so the amount is a best guess."}}},"count":{"type":"integer","example":42},"events":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","example":"2026-01-02 09:14:00"},"sentAmount":{"type":"string"},"sentCurrency":{"type":"string"},"receivedAmount":{"type":"string","example":"0.91"},"receivedCurrency":{"type":"string","example":"ATOM"},"feeAmount":{"type":"string"},"feeCurrency":{"type":"string"},"label":{"type":"string","example":"reward"},"description":{"type":"string"},"txHash":{"type":"string","example":"ABC123..."},"category":{"type":"string","example":"reward","description":"Indexer classification; the full list is /api/tax/v1/catalog."},"taxable":{"type":"boolean","description":"False for record-only rows (delegation principal, internal transfer, protocol deposit)."},"detail":{"type":"string","description":"Human-readable context: the contract, protocol, or auto-claim trigger."},"userTag":{"type":"string","description":"The tag supplied in `tags` for this row, echoed back."},"validatorAddress":{"type":"string"},"validatorMoniker":{"type":"string"},"rewardTrigger":{"type":"string","example":"delegate"},"source":{"type":"string","example":"claim","description":"What produced a reward row: claim, commission, delegate, redelegate, undelegate, authz and so on. Absent on other rows."},"valueUsd":{"type":"number","description":"USD at that day's reference price. 0 with priceMissing true means unknown, not worthless."},"priceMissing":{"type":"boolean","description":"No reference price for this denom on this day after the fallback order in /api/tax/v1/methodology."},"priceImplied":{"type":"boolean","description":"The USD value came from the other side of a swap, not a price feed."},"decimalsAssumed":{"type":"boolean","description":"Decimals for this denom were not found in the asset registry or the bank module, so the amount is a best guess."},"excluded":{"type":"boolean","description":"An asset_decisions or spam_policy decision removed this receipt from income and lots. Kept for the record."}}}},"index_coverage":{"$ref":"#/components/schemas/PeriodCoverage"}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid address, chain, type, date, format, tags or asset_decisions.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The tax service could not be reached or failed (code upstream_error). Retry shortly.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"503":{"description":"This wallet's staking history is being replayed under the current methodology; Retry-After says when to try again. No totals are returned rather than a wrong number.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/balances":{"get":{"tags":["Balances"],"summary":"ATOM holdings","description":"Returns Cosmos Hub holdings for an address. Without `date` it reads current ATOM holdings (liquid, staked, unclaimed rewards) from the node and records them. With `date` it rebuilds the wallet at the end of that UTC day from the indexed chain history: every denom in the bank, staked and unbonding ATOM per validator (`holdings`), USD values, and `status` exact or approximate (an approximate line gives `max_error_base`, the most it can be off in base units). Unclaimed rewards cannot be rebuilt for a past date, so `reward` is null there. A date the index cannot rebuild exactly yet is refused with 409 and the reason, including any date before the end of 2021-12-14 (Gaia v6): the chain emitted no coin_received or coin_spent events before then, and a date before 2024-03-20 (Gaia v15) when the wallet delegated, undelegated or redelegated between the date and that upgrade, since staking events did not name the delegator before it. `history=true` returns the recorded current-holdings series. A dated lookup reads every indexed block since the date, so a date years back can take tens of seconds.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"One public address, cosmos1..."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"Rebuild holdings at the end of this UTC day, YYYY-MM-DD, 2021-12-14 or later. Default: current holdings from the node."},{"name":"history","in":"query","required":false,"schema":{"type":"boolean"},"description":"Set true to return the full daily series instead of a single point."}],"responses":{"200":{"description":"Holdings (a single point, or { history: [...] } when history=true).","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","example":"cosmos1abc..."},"date":{"type":"string","example":"2026-06-30"},"liquid":{"type":"number","example":12.5},"staked":{"type":"number","example":480},"unbonding":{"type":"number","example":0,"description":"Dated lookups only."},"reward":{"type":"number","nullable":true,"example":3.21,"description":"Null on a dated lookup: unclaimed rewards are not rebuilt."},"total":{"type":"number","example":492.5},"total_usd":{"type":"string","example":"2210.40","description":"Dated lookups only. Every priced holding, not just ATOM."},"status":{"type":"string","enum":["exact","approximate"],"description":"Dated lookups only."},"height":{"type":"integer","description":"Dated lookups only: the last block of that UTC day."},"block_time":{"type":"string","format":"date-time","description":"Dated lookups only: that block's time."},"anchor_height":{"type":"integer","description":"Dated lookups only: the recent block whose node state the rebuild starts from."},"methodology_version":{"type":"string","example":"v17"},"reward_note":{"type":"string","description":"Dated lookups only: why reward is null."},"unpriced_lines":{"type":"integer","description":"Dated lookups only: holdings with no reference price that day, left out of total_usd."},"holdings":{"type":"array","description":"Dated lookups only: one line per denom in the bank, and per validator for staked and unbonding ATOM.","items":{"type":"object","properties":{"bucket":{"type":"string","enum":["liquid","staked","unbonding"]},"validator":{"type":"string","description":"Operator address, on staked and unbonding lines."},"denom":{"type":"string"},"symbol":{"type":"string"},"amount_base":{"type":"string"},"quantity":{"type":"string"},"price_usd":{"type":"string","nullable":true},"value_usd":{"type":"string","nullable":true},"price_missing":{"type":"boolean"},"decimals_assumed":{"type":"boolean","description":"No registry entry gave the denom's decimals, so the quantity is a best guess."},"approximate":{"type":"boolean"},"max_error_base":{"type":"string","description":"On an approximate line: the most it can be off by, in base units."}}}},"symbol":{"type":"string","example":"ATOM"}}}}}},"400":{"description":"Missing or invalid address, chain or date.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"404":{"description":"No balance is recorded for this address yet (history=true).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"409":{"description":"The index cannot rebuild this date exactly: it is before the end of 2021-12-14, before 2024-03-20 with a stake change in between, or its blocks are not indexed yet. The detail gives the reason; no partial number is returned.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The balance service did not answer or sent an unreadable reply.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/balance-statement":{"get":{"tags":["Balances"],"summary":"Quarter-end and year-end balances","description":"A wallet's holdings at the end of each quarter and the year end of `year`, or at up to 12 listed `dates`, each rebuilt from the indexed chain history at the end of the UTC day, as JSON or CSV. Every date carries its own `status`: exact, approximate (lines give `max_error_base`), incomplete (the index cannot rebuild it yet) or not_reached (in the future). A date that is not exact or approximate has null amounts and a `reason`. Unclaimed staking rewards are not included. The CSV has one row per holding per date.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"One public address, cosmos1..."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"year","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{4}$"},"example":"2025","description":"Statement year: Mar 31, Jun 30, Sep 30 and Dec 31. Required unless dates is given."},{"name":"dates","in":"query","required":false,"schema":{"type":"string"},"example":"2026-06-30,2026-09-30","description":"Up to 12 dates, YYYY-MM-DD, comma separated, instead of year."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"json (default) or csv: address, date, label, status, height, bucket, validator, denom, symbol, quantity, price_usd, value_usd, price_missing, approximate, max_error_base, reason."}],"responses":{"200":{"description":"One balance per date, or CSV with one row per holding per date.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string"},"chain":{"type":"string","example":"mainnet"},"symbol":{"type":"string","example":"ATOM"},"methodology_version":{"type":"string","example":"v17"},"note":{"type":"string","description":"What exact, approximate, incomplete and not_reached mean."},"balances":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"label":{"type":"string","example":"Q3","description":"Q1 to Q4 or Year end with year; empty with dates."},"date":{"type":"string","format":"date"},"status":{"type":"string","enum":["exact","approximate","incomplete","not_reached"]},"reason":{"type":"string","description":"Why a date is incomplete or not_reached."},"height":{"type":"integer","nullable":true},"anchor_height":{"type":"integer","nullable":true},"block_time":{"type":"string","format":"date-time","nullable":true},"liquid":{"type":"number","nullable":true},"staked":{"type":"number","nullable":true},"unbonding":{"type":"number","nullable":true},"reward":{"type":"number","nullable":true,"description":"Always null: unclaimed rewards are not rebuilt for a past date."},"reward_note":{"type":"string"},"total":{"type":"number","nullable":true},"total_usd":{"type":"string","nullable":true},"unpriced_lines":{"type":"integer"},"symbol":{"type":"string"},"holdings":{"type":"array","nullable":true,"items":{"type":"object","properties":{"bucket":{"type":"string","enum":["liquid","staked","unbonding"]},"validator":{"type":"string","description":"Operator address, on staked and unbonding lines."},"denom":{"type":"string"},"symbol":{"type":"string"},"amount_base":{"type":"string"},"quantity":{"type":"string"},"price_usd":{"type":"string","nullable":true},"value_usd":{"type":"string","nullable":true},"price_missing":{"type":"boolean"},"decimals_assumed":{"type":"boolean","description":"No registry entry gave the denom's decimals, so the quantity is a best guess."},"approximate":{"type":"boolean"},"max_error_base":{"type":"string","description":"On an approximate line: the most it can be off by, in base units."}}}}}}}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid address, chain, year, dates or format.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The balance service did not answer or sent an unreadable reply.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/price-series":{"get":{"tags":["Pricing"],"summary":"ATOM/USD price series","description":"Returns the daily USD reference price series for a denom (ATOM by default), generated by the same pricing pipeline every tax report uses. found=false means no price was published for that day (see the methodology endpoint for how that's handled). chain accepts cosmoshub, cosmoshub-4 or mainnet.","parameters":[{"name":"denom","in":"query","required":false,"schema":{"type":"string","default":"uatom"},"description":"Base denom as it appears on the Hub, including ibc/<hash> denoms. Default: uatom (ATOM)."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Inclusive start, YYYY-MM-DD. Default: 90 days before end."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"Inclusive end, YYYY-MM-DD. Default: today."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"json (default) or csv."}],"responses":{"200":{"description":"The price series (JSON) or a CSV file when format=csv.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"cosmoshub"},"denom":{"type":"string","example":"uatom"},"methodology_version":{"type":"string","example":"v17"},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","example":"2026-06-20"},"usd":{"type":"number","example":1.95},"found":{"type":"boolean","example":true}}}}}}},"text/csv":{"schema":{"type":"string"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid date or chain, end before start, or a range over 730 days.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/methodology":{"get":{"tags":["Pricing"],"summary":"FMV pricing methodology","description":"Returns the published methodology behind every USD value in a report: price sources, timestamp granularity, aggregation rule, fallback order, and how missing prices are handled, plus how rewards, record-only rows, protocol actions and past-date balances are classified. Versioned and dated; every report, statement and journal line cites the version that priced it. v16 (2026-11-09) prices IBC tokens through their proven denom trace with home-chain decimals, reads Gravity DEX settlements from block events, and documents the Hub before Gaia v6. v17 (2026-11-09) refuses a past-date balance the rebuild cannot read yet: any date before Gaia v6, and a date before Gaia v15 when the wallet delegated, undelegated or redelegated between that date and the upgrade. Human-readable form: /tax/methodology.","parameters":[],"responses":{"200":{"description":"The current methodology.","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string","example":"v17"},"effective_date":{"type":"string","format":"date","example":"2026-11-09"},"sources":{"type":"array","items":{"type":"string"}},"timestamp_granularity":{"type":"string"},"aggregation_rule":{"type":"string"},"fallback_order":{"type":"array","items":{"type":"string"}},"missing_price_handling":{"type":"string"},"reward_classification":{"type":"string","description":"What counts as staking income and what is principal."},"validator_metadata":{"type":"string","description":"Where monikers and jurisdictions come from."},"asset_identity":{"type":"string","description":"How suspected spam and token-identity mismatches are held for a decision."},"protocol_activity":{"type":"string","description":"How CosmWasm protocol actions, Skip Go routes and NFT migrations are classified."},"record_categories":{"type":"string","description":"Record-only categories and block-event movements."},"user_tags":{"type":"string","description":"What a bookkeeping tag changes."},"classification_completeness":{"type":"string","description":"What holds a report back until reviewed."},"historical_balances":{"type":"string","description":"How a past-date balance is rebuilt, and its limits."}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/recognition-policy":{"get":{"tags":["Pricing"],"summary":"Income recognition policy","description":"Returns the documented policy for WHEN staking rewards and validator commission are recognized as income. \"at-claim\" today (income at withdrawal, matching dominion-and-control under Rev. Rul. 2023-14); the field exists so recognition timing is a citable, versioned policy rather than an implicit assumption.","parameters":[],"responses":{"200":{"description":"The current recognition policy.","content":{"application/json":{"schema":{"type":"object","properties":{"policy":{"type":"string","example":"at-claim"},"effective_date":{"type":"string","format":"date","example":"2026-07-04"},"explanation":{"type":"string"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/delegator-report":{"get":{"tags":["Validators"],"summary":"Delegator staking-income report","description":"Returns a compact staking-income summary for one delegator address, for a validator's embedded widget (see /tax/widget/delegator-report). CORS-enabled unlike the rest of this API, since it's meant to be called directly from a validator's own site. Requires an api_key (email hello@bryanlabs.net to get one during this pilot phase); the key's allowed origin is enforced when the caller's browser sends an Origin header.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"The delegator's public address, e.g. cosmos1abc..."},{"name":"api_key","in":"query","required":true,"schema":{"type":"string"},"description":"Your validator API key."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Inclusive start, YYYY-MM-DD. Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"Inclusive end, YYYY-MM-DD. Default: all time."}],"responses":{"200":{"description":"The delegator's staking-income summary.","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string"},"chain":{"type":"string","example":"cosmoshub"},"rewards_amount":{"type":"string","example":"12.345678"},"symbol":{"type":"string","example":"ATOM"},"rewards_usd":{"type":"string","example":"24.10"},"taxable_events":{"type":"integer","example":8},"price_missing_rows":{"type":"integer","example":0},"recognition_policy":{"type":"string","example":"at-claim"},"methodology_version":{"type":"string","example":"v17"},"powered_by":{"type":"string","example":"BryanLabs (bryanlabs.net/tax)"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Missing or invalid address or date.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"Missing or unknown api_key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The browser's Origin is not one this key allows.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"429":{"description":"The key's rate limit is exceeded; Retry-After says when to try again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The tax service did not answer or sent an unreadable reply.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/v1/index-coverage":{"get":{"tags":["Reference"],"summary":"Which blocks are indexed, per year","description":"Per calendar year from cosmoshub-4 genesis (2021-02-18): the block range, how many blocks are expected and how many are indexed, whether the year is complete, the earliest and latest fully covered dates, the covered date ranges and the gaps. indexed_range is the contiguous indexed run ending at the latest block. Reports for any period can be generated; this says which ones are complete. Computed in the background every few minutes and served from cache, so polling it is cheap. With start and/or end it also returns period, the same check every report carries as index_coverage.","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Start date, YYYY-MM-DD (inclusive, from 00:00 UTC). Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"End date, YYYY-MM-DD (inclusive, through 23:59:59 UTC). Default: now."}],"responses":{"200":{"description":"Index coverage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexCoverage"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid chain or date.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Coverage is still being computed after a restart (code coverage_warming), or the tax service is unavailable. Retry-After says when to try again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/catalog":{"get":{"tags":["Reference"],"summary":"What the indexer tracks","description":"Every event category the indexer classifies with its taxable flag and group, the reward triggers, the CosmWasm contracts and protocols it recognizes (with first-seen height), the message types it replays, the bookkeeping tags, the export formats, the reports, the Gaia releases it has reviewed, and announced upstream changes. Read this first to learn what a report can contain. Human-readable form: /tax/coverage.","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."}],"responses":{"200":{"description":"The catalog.","content":{"application/json":{"schema":{"type":"object","properties":{"chain_id":{"type":"string","example":"cosmoshub"},"chain":{"type":"string","example":"cosmoshub-4"},"methodology_version":{"type":"string","example":"v17"},"methodology_date":{"type":"string","format":"date","example":"2026-11-09"},"native_asset":{"type":"object"},"categories":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"},"taxable":{"type":"boolean"},"group":{"type":"string"},"description":{"type":"string"}}}},"triggers":{"type":"array","items":{"type":"object","properties":{"trigger":{"type":"string"},"categories":{"type":"string"},"description":{"type":"string"}}}},"contracts":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"protocol":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"first_seen_height":{"type":"integer"}}}},"message_types":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"object"}},"export_formats":{"type":"array","items":{"type":"object"}},"reports":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"purpose":{"type":"string"}}}},"gaia_releases":{"type":"array","items":{"type":"object"}},"upcoming_changes":{"type":"array","items":{"type":"string"}}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Unknown or unsupported chain.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/tags":{"get":{"tags":["Reference"],"summary":"Bookkeeping tag vocabulary","description":"The tags accepted by the `tags` parameter (GET) or `userTags` body field (POST) with the export treatment each produces. Keys are a transaction hash or hash:denom.","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."}],"responses":{"200":{"description":"The vocabulary.","content":{"application/json":{"schema":{"type":"object","properties":{"key_forms":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"object","properties":{"tag":{"type":"string"},"label":{"type":"string"},"treatment":{"type":"string"}}}},"usage":{"type":"string"},"defaults":{"type":"array","description":"What each kind of row already is before any tag, and how US individual, business and retirement returns and other regimes treat it.","items":{"type":"object","properties":{"rows":{"type":"string"},"default_treatment":{"type":"string"},"action":{"type":"string","description":"What, if anything, to tag for this kind of row."},"us_individual":{"type":"string"},"us_business":{"type":"string"},"us_retirement_account":{"type":"string"},"elsewhere":{"type":"string"}}}},"defaults_note":{"type":"string"},"saved_reports":{"type":"object","description":"Where to read and change a saved report's tags, and the scopes needed.","additionalProperties":true}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Unknown or unsupported chain.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/journal":{"get":{"tags":["Books"],"summary":"General-ledger journal","description":"Double-entry journal in USD for a controller's books: one debit and one credit line per entry (Digital Assets: ATOM, Income: Staking Rewards, Expense: Network Fees, Realized Gain/Loss, ...), per wallet, FIFO, priced by the published methodology, in strict date order. Each line carries price_usd (the unit reference price, so a reporting currency can be applied at your own rate), counterparty, validator and validator_country (ISO code from the disclosure registry, or undisclosed) and methodology_version. Accepts asset_decisions and tags like /events. USD only: no reporting-currency conversion is provided.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"Comma-separated public address(es), e.g. cosmos1abc,cosmos1def. Each wallet is computed on its own; see Wallet-by-wallet above."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Start date, YYYY-MM-DD (inclusive, from 00:00 UTC). Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"End date, YYYY-MM-DD (inclusive, through 23:59:59 UTC). Default: now."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Bookkeeping tags as a JSON object, e.g. {\"<TX_HASH>\": \"internal_transfer\"}. Vocabulary: /api/tax/v1/tags."},{"name":"asset_decisions","in":"query","required":false,"schema":{"type":"string"},"description":"Decisions for flagged receipts (suspected spam or identity mismatch), as a JSON object. Keys are one of: a record_id from /api/tax/v1/asset-review (one receipt), denom:<raw_denom> (every flagged receipt of that token in the period), or policy:spam (every receipt flagged as suspected spam that has no more specific decision). The most specific key wins. Values: {\"mode\": \"exclude\"} treats the receipts as valueless (no income, zero basis, kept out of tax-software imports); {\"mode\": \"override\", \"token\": \"ATOM\", \"quantity\": \"29.55\", \"value_usd\": \"120.10\", \"cost_basis_usd\": \"120.10\", \"acquired_date\": \"2026-03-04\"} supplies totals for one receipt; {\"mode\": \"override\", \"token\": \"FOO\", \"unit_value_usd\": \"0.5\"} under a denom: key prices each receipt of that token at quantity times unit value on its own date. policy:spam is exclude only. An unknown record_id is a 400; an idle denom: or policy: key is accepted (and listed in unmatched_decision_keys on /asset-review) so standing rules can be sent with every request. Up to 500 entries and 256 KiB. Nothing is stored server-side."},{"name":"spam_policy","in":"query","required":false,"schema":{"type":"string","enum":["ask","valueless"],"default":"ask"},"description":"Shorthand for the policy:spam decision: valueless adds {\"policy:spam\": {\"mode\": \"exclude\"}} to asset_decisions, so every suspected-spam receipt without a more specific decision is carried at zero."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["csv","json"],"default":"csv"},"description":"csv (default, ready for a ledger import) or json."}],"responses":{"200":{"description":"Journal lines.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"}},"start":{"type":"string","format":"date-time","nullable":true},"end":{"type":"string","format":"date-time","nullable":true},"note":{"type":"string","description":"The chart of accounts used."},"count":{"type":"integer"},"lines":{"type":"array","items":{"type":"object","properties":{"date_utc":{"type":"string","format":"date","example":"2026-10-01"},"tx_hash":{"type":"string"},"entry_id":{"type":"string","example":"54531E7309-0","description":"Shared by the debit and credit line of one entry."},"account":{"type":"string","example":"Digital Assets: ATOM"},"debit_usd":{"type":"string","example":"109.61","description":"Cents; empty on a credit line."},"credit_usd":{"type":"string","example":"","description":"Cents; empty on a debit line."},"asset":{"type":"string","example":"ATOM"},"quantity":{"type":"string","example":"62.919927"},"price_usd":{"type":"string","example":"1.7420894504355602","description":"Unit reference price used, unrounded, so another reporting currency can be applied."},"category":{"type":"string","example":"commission"},"memo":{"type":"string"},"counterparty":{"type":"string"},"validator":{"type":"string","example":"Binance Node"},"validator_country":{"type":"string","example":"undisclosed","description":"ISO 3166 code from the jurisdiction registry, or undisclosed."},"methodology_version":{"type":"string","example":"v17"}}}},"index_coverage":{"$ref":"#/components/schemas/PeriodCoverage"}}}}}},"400":{"description":"Missing or invalid address, date or tag.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The tax service could not be reached or failed (code upstream_error). Retry shortly.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/asset-review":{"get":{"tags":["Events"],"summary":"Flagged receipts awaiting a decision","description":"The receipts the exporters flag (suspected spam, a token identity that does not match the on-chain denom, an unpriced asset) for the wallets and period, each with the record_id an asset decision is keyed by, folded into groups (one per token, with its denom: decision key, receipt and pending counts, dates, total quantity, reason codes and a sample memo) and a reason_glossary explaining each reason code with its usual treatment. Every report endpoint answers 409 while a flagged receipt in its period has no decision; call this to see them, decide per token (or per receipt), then pass the decisions as asset_decisions. Supplying asset_decisions here shows what is still pending and which keys matched nothing. Nothing is stored server-side.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"Comma-separated public address(es), e.g. cosmos1abc,cosmos1def. Each wallet is computed on its own; see Wallet-by-wallet above."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Start date, YYYY-MM-DD (inclusive, from 00:00 UTC). Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"End date, YYYY-MM-DD (inclusive, through 23:59:59 UTC). Default: now."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Bookkeeping tags as a JSON object, e.g. {\"<TX_HASH>\": \"internal_transfer\"}. Vocabulary: /api/tax/v1/tags."},{"name":"asset_decisions","in":"query","required":false,"schema":{"type":"string"},"description":"Decisions for flagged receipts (suspected spam or identity mismatch), as a JSON object. Keys are one of: a record_id from /api/tax/v1/asset-review (one receipt), denom:<raw_denom> (every flagged receipt of that token in the period), or policy:spam (every receipt flagged as suspected spam that has no more specific decision). The most specific key wins. Values: {\"mode\": \"exclude\"} treats the receipts as valueless (no income, zero basis, kept out of tax-software imports); {\"mode\": \"override\", \"token\": \"ATOM\", \"quantity\": \"29.55\", \"value_usd\": \"120.10\", \"cost_basis_usd\": \"120.10\", \"acquired_date\": \"2026-03-04\"} supplies totals for one receipt; {\"mode\": \"override\", \"token\": \"FOO\", \"unit_value_usd\": \"0.5\"} under a denom: key prices each receipt of that token at quantity times unit value on its own date. policy:spam is exclude only. An unknown record_id is a 400; an idle denom: or policy: key is accepted (and listed in unmatched_decision_keys on /asset-review) so standing rules can be sent with every request. Up to 500 entries and 256 KiB. Nothing is stored server-side."},{"name":"spam_policy","in":"query","required":false,"schema":{"type":"string","enum":["ask","valueless"],"default":"ask"},"description":"Shorthand for the policy:spam decision: valueless adds {\"policy:spam\": {\"mode\": \"exclude\"}} to asset_decisions, so every suspected-spam receipt without a more specific decision is carried at zero."}],"responses":{"200":{"description":"Flagged receipts.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string"},"addresses":{"type":"array","items":{"type":"string"}},"pending":{"type":"integer","description":"Flagged receipts with no decision yet."},"message":{"type":"string"},"reviews":{"type":"array","items":{"type":"object","description":"One flagged receipt: record_id, the transaction, denom, quantity, the reason it was flagged, and the current decision if any."}},"decisions":{"type":"object","additionalProperties":true},"groups":{"type":"array","items":{"type":"object","properties":{"denom":{"type":"string"},"decision_key":{"type":"string"},"reported_label":{"type":"string"},"token_name":{"type":"string"},"base_token":{"type":"string"},"source_chain":{"type":"string"},"channel_path":{"type":"string"},"suspected_spam":{"type":"boolean"},"reason_codes":{"type":"array","items":{"type":"string"}},"receipts":{"type":"integer"},"pending":{"type":"integer"},"first_date":{"type":"string"},"last_date":{"type":"string"},"total_quantity":{"type":"string"},"sample_memo":{"type":"string"},"record_ids":{"type":"array","items":{"type":"string"}},"decision":{"type":"object","additionalProperties":true}}}},"unmatched_decision_keys":{"type":"array","items":{"type":"string"}},"reason_glossary":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"title":{"type":"string"},"text":{"type":"string"},"explainer":{"type":"string"},"suggested":{"type":"string"}}}},"decision_keys":{"type":"object","additionalProperties":{"type":"string"}},"how_to_decide":{"type":"string"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Missing or invalid address or date.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/positions":{"get":{"tags":["Books"],"summary":"Open positions","description":"Open lots and unrealized gain or loss per asset as of a date (default today), per wallet, FIFO, the same replay Form 8949 uses. Quantity with unknown basis arrived from outside our view (an exchange or IBC receipt): valued, but with no cost basis here. Lots come only from acquisitions in the indexed history; coins acquired in blocks the history backfill has not reached yet are not represented, and index_coverage says whether everything from genesis to the as-of date is indexed. Staked and unbonding coins stay in quantity because delegating is not a disposal; the liquid, staked and unbonding split is on /balances. USD figures are rounded to cents.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"Comma-separated public address(es), e.g. cosmos1abc,cosmos1def. Each wallet is computed on its own; see Wallet-by-wallet above."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"As-of date, YYYY-MM-DD (end of that UTC day). Default: today."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Bookkeeping tags as a JSON object, e.g. {\"<TX_HASH>\": \"internal_transfer\"}. Vocabulary: /api/tax/v1/tags."},{"name":"asset_decisions","in":"query","required":false,"schema":{"type":"string"},"description":"Decisions for flagged receipts (suspected spam or identity mismatch), as a JSON object. Keys are one of: a record_id from /api/tax/v1/asset-review (one receipt), denom:<raw_denom> (every flagged receipt of that token in the period), or policy:spam (every receipt flagged as suspected spam that has no more specific decision). The most specific key wins. Values: {\"mode\": \"exclude\"} treats the receipts as valueless (no income, zero basis, kept out of tax-software imports); {\"mode\": \"override\", \"token\": \"ATOM\", \"quantity\": \"29.55\", \"value_usd\": \"120.10\", \"cost_basis_usd\": \"120.10\", \"acquired_date\": \"2026-03-04\"} supplies totals for one receipt; {\"mode\": \"override\", \"token\": \"FOO\", \"unit_value_usd\": \"0.5\"} under a denom: key prices each receipt of that token at quantity times unit value on its own date. policy:spam is exclude only. An unknown record_id is a 400; an idle denom: or policy: key is accepted (and listed in unmatched_decision_keys on /asset-review) so standing rules can be sent with every request. Up to 500 entries and 256 KiB. Nothing is stored server-side."},{"name":"spam_policy","in":"query","required":false,"schema":{"type":"string","enum":["ask","valueless"],"default":"ask"},"description":"Shorthand for the policy:spam decision: valueless adds {\"policy:spam\": {\"mode\": \"exclude\"}} to asset_decisions, so every suspected-spam receipt without a more specific decision is carried at zero."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"}}],"responses":{"200":{"description":"Positions.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"}},"as_of":{"type":"string","format":"date","example":"2026-10-31"},"methodology_version":{"type":"string","example":"v17"},"note":{"type":"string"},"count":{"type":"integer"},"positions":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"asset":{"type":"string","example":"ATOM"},"denom":{"type":"string","example":"uatom"},"quantity":{"type":"string"},"cost_basis_usd":{"type":"string"},"basis_unknown_quantity":{"type":"string","description":"Part of quantity with no cost basis in view (arrived by transfer or IBC)."},"market_price_usd":{"type":"string"},"market_value_usd":{"type":"string"},"unrealized_gain_usd":{"type":"string"},"price_missing":{"type":"boolean","description":"No reference price on the as-of date; market value and gain are 0 meaning unknown."},"lots":{"type":"integer"},"oldest_lot":{"type":"string","format":"date"}}}},"index_coverage":{"$ref":"#/components/schemas/PeriodCoverage"}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid address or date.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"409":{"description":"Flagged receipts up to the as-of date need a decision (code asset_review_required). Positions replay the whole history, so call /asset-review with end set to the as-of date and no start. Decisions for receipts after the as-of date are accepted and ignored.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/carf":{"get":{"tags":["Books"],"summary":"CARF and DAC8 summary","description":"A wallet's activity shaped like the Relevant Transactions an exchange reports under the OECD Crypto-Asset Reporting Framework (XML schema v1.5, July 2025) and the EU's DAC8: per asset, CryptotoCryptoIn/Out for swaps and NFT trades, CryptoTransferIn with CARF501 to CARF509 and CryptoTransferOut with CARF601 to CARF606, each with the number of transactions, the amount net of fees (2 decimals) and the number of units (6 decimals). Use it to reconcile what an exchange reports about you; it is not a filing. Staking rewards and validator commission are CARF502; delegations, unbonding and other record-only rows are left out because nothing left the owner; tags set the transfer type (payment, airdrop, gift, internal_transfer, expense, lost). Amounts are in the chosen currency, converted from USD with the ECB euro reference rates for each day (the last fixing on or before it). Assets are named by ticker with the on-chain denom, not by ISO 24165 DTI code.","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string"},"example":"cosmos18ruzecmqj9pv8ac0gvkgryuc7u004te9xr2mcr","description":"Comma-separated public address(es), e.g. cosmos1abc,cosmos1def. Each wallet is computed on its own; see Wallet-by-wallet above."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"year","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{4}$"},"example":"2025","description":"Calendar year (UTC). Replaces start and end."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Start date, YYYY-MM-DD (inclusive, from 00:00 UTC). Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"End date, YYYY-MM-DD (inclusive, through 23:59:59 UTC). Default: now."},{"name":"currency","in":"query","required":false,"schema":{"type":"string","default":"USD","example":"CHF"},"description":"ISO 4217 reporting currency: USD, EUR, CHF, GBP, JPY, CAD, AUD, NZD, SEK, NOK, DKK, PLN, CZK, HUF, RON, ISK, TRY, ILS, INR, SGD, HKD, KRW, CNY, BRL, MXN, ZAR, THB, MYR, PHP or IDR."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","detail"],"default":"json"},"description":"json, the summary as CSV, or detail (every row with its CARF element and code, as CSV)."},{"name":"detail","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"With format=json, include every row as events."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Bookkeeping tags as a JSON object, e.g. {\"<TX_HASH>\": \"internal_transfer\"}. Vocabulary: /api/tax/v1/tags."},{"name":"asset_decisions","in":"query","required":false,"schema":{"type":"string"},"description":"Decisions for flagged receipts (suspected spam or identity mismatch), as a JSON object. Keys are one of: a record_id from /api/tax/v1/asset-review (one receipt), denom:<raw_denom> (every flagged receipt of that token in the period), or policy:spam (every receipt flagged as suspected spam that has no more specific decision). The most specific key wins. Values: {\"mode\": \"exclude\"} treats the receipts as valueless (no income, zero basis, kept out of tax-software imports); {\"mode\": \"override\", \"token\": \"ATOM\", \"quantity\": \"29.55\", \"value_usd\": \"120.10\", \"cost_basis_usd\": \"120.10\", \"acquired_date\": \"2026-03-04\"} supplies totals for one receipt; {\"mode\": \"override\", \"token\": \"FOO\", \"unit_value_usd\": \"0.5\"} under a denom: key prices each receipt of that token at quantity times unit value on its own date. policy:spam is exclude only. An unknown record_id is a 400; an idle denom: or policy: key is accepted (and listed in unmatched_decision_keys on /asset-review) so standing rules can be sent with every request. Up to 500 entries and 256 KiB. Nothing is stored server-side."},{"name":"spam_policy","in":"query","required":false,"schema":{"type":"string","enum":["ask","valueless"],"default":"ask"},"description":"Shorthand for the policy:spam decision: valueless adds {\"policy:spam\": {\"mode\": \"exclude\"}} to asset_decisions, so every suspected-spam receipt without a more specific decision is carried at zero."}],"responses":{"200":{"description":"The summary.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string"},"addresses":{"type":"array","items":{"type":"string"}},"start":{"type":"string"},"end":{"type":"string"},"standard":{"type":"object"},"currency":{"type":"string","example":"CHF"},"fxSource":{"type":"string","nullable":true},"assets":{"type":"array","items":{"type":"object","properties":{"asset":{"type":"string","example":"ATOM"},"denoms":{"type":"array","items":{"type":"string"}},"buckets":{"type":"array","items":{"type":"object","properties":{"element":{"type":"string","example":"CryptoTransferIn"},"code":{"type":"string","nullable":true,"example":"CARF502"},"type":{"type":"string","nullable":true,"example":"Staking income"},"transactions":{"type":"integer"},"amount":{"type":"number"},"units":{"type":"number"},"unpriced":{"type":"integer"}}}},"feesPaid":{"type":"object","properties":{"transactions":{"type":"integer"},"amount":{"type":"number"},"units":{"type":"number"}}}}}},"notIncluded":{"type":"object","properties":{"recordOnly":{"type":"integer"},"fees":{"type":"integer"},"spam":{"type":"integer"},"excluded":{"type":"integer"},"pending":{"type":"integer"}}},"unconvertible":{"type":"integer"},"events":{"type":"array","items":{"type":"object"}},"index_coverage":{"$ref":"#/components/schemas/PeriodCoverage"}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid address, year, date, currency or format.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"502":{"description":"The ECB exchange-rate source did not answer.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/validator-statement":{"get":{"tags":["Validators"],"summary":"Validator operator statement","description":"Commission the operator withdrew and the rewards delegators actually withdrew through this validator (claims and auto-withdrawals), by month, with unique delegators and the operator's disclosed jurisdiction. Aggregated in the database over indexed columns, so a large validator over a full year answers in a few seconds. The coverage object says what the index covers and whether the methodology replay has finished; months still being replayed, or that fall in blocks the history backfill has not reached, carry incomplete=true. index_coverage says whether the whole period is indexed. price_missing_events counts reward events with no reference price (usually rewards paid in a denom other than ATOM); they add nothing to the USD columns. USD figures are exact decimals as strings and are not rounded; round at display. The CSV has one row per month plus a TOTAL row.","parameters":[{"name":"validator","in":"query","required":true,"schema":{"type":"string"},"example":"cosmosvaloper18ruzecmqj9pv8ac0gvkgryuc7u004te9rh7w5s","description":"Operator address, cosmosvaloper1... The bech32 checksum is verified, so a typo is a 400, not an empty statement."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-01","description":"Start date, YYYY-MM-DD (inclusive, from 00:00 UTC). Default: all time."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"},"example":"2026-10-31","description":"End date, YYYY-MM-DD (inclusive, through 23:59:59 UTC). Default: now."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"}}],"responses":{"200":{"description":"The statement.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"chain_id":{"type":"string","example":"cosmoshub"},"chain":{"type":"string","example":"mainnet"},"validator":{"type":"string","example":"cosmosvaloper18ruzecmqj9pv8ac0gvkgryuc7u004te9rh7w5s"},"moniker":{"type":"string","example":"Binance Node"},"jurisdiction":{"type":"string","example":"CH","description":"ISO country code the operator account attested on chain, or undisclosed."},"methodology_version":{"type":"string","example":"v17"},"recognition_policy":{"type":"string","example":"at-claim"},"note":{"type":"string","description":"What each column counts."},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","example":"2026-10"},"symbol":{"type":"string","example":"ATOM"},"commission_amount":{"type":"string","example":"8072.819147","description":"Commission the operator withdrew, ATOM."},"commission_usd":{"type":"string","example":"13991.05","description":"At each withdrawal day's reference price. Unrounded decimal."},"delegator_rewards_amount":{"type":"string","description":"Rewards delegators withdrew through this validator, ATOM."},"delegator_rewards_usd":{"type":"string","description":"Unrounded decimal."},"reward_events":{"type":"integer"},"unique_delegators":{"type":"integer"},"price_missing_days":{"type":"integer","description":"Days with a reward event that had no reference price."},"price_missing_events":{"type":"integer","description":"Reward events with no reference price, left out of the USD columns."},"incomplete":{"type":"boolean","description":"The month is still being replayed or falls in blocks the backfill has not reached."}}}},"total":{"type":"object","properties":{"month":{"type":"string","example":"2026-10"},"symbol":{"type":"string","example":"ATOM"},"commission_amount":{"type":"string","example":"8072.819147","description":"Commission the operator withdrew, ATOM."},"commission_usd":{"type":"string","example":"13991.05","description":"At each withdrawal day's reference price. Unrounded decimal."},"delegator_rewards_amount":{"type":"string","description":"Rewards delegators withdrew through this validator, ATOM."},"delegator_rewards_usd":{"type":"string","description":"Unrounded decimal."},"reward_events":{"type":"integer"},"unique_delegators":{"type":"integer"},"price_missing_days":{"type":"integer","description":"Days with a reward event that had no reference price."},"price_missing_events":{"type":"integer","description":"Reward events with no reference price, left out of the USD columns."},"incomplete":{"type":"boolean","description":"The month is still being replayed or falls in blocks the backfill has not reached."}},"description":"The period's sum; month is TOTAL."},"coverage":{"type":"object","properties":{"index_start":{"type":"string","format":"date-time","description":"First indexed block time."},"index_end":{"type":"string","format":"date-time","description":"Latest indexed block time."},"replay_cursor":{"type":"string"},"complete":{"type":"boolean","description":"The methodology replay has finished for this period."},"note":{"type":"string"}}},"index_coverage":{"$ref":"#/components/schemas/PeriodCoverage"}}}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid date, or the operator address failed its bech32 checksum (a typo).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"404":{"description":"No validator with this operator address on the chain, now or in the indexed history.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/validator-commission-flows":{"get":{"tags":["Validators"],"summary":"Where a validator's commission went","description":"Each commission withdrawal followed from the wallet it was paid to, through that wallet's transfers, delegations, unbonding and IBC sends, and up to three wallets further. Every month's withdrawn commission is split into classes (held, restaked_own, restaked_other, unbonding, locked, the *_downstream classes, exchange, exchange_like, ibc_out, fees, swapped, spent, tokenized, burned, community_pool, module, contract_or_ica, beyond_hops, busy_wallet, unresolved); classes describes each. Coins mixed with other coins need a rule, so both first in first out and pro-rata are stored and either can be read. exchange comes only from labeled addresses with a named source; exchange_like is inferred from deposit-style memos and reported separately. USD is the amount at that month's commission-weighted ATOM price, the value when earned. Traces are rebuilt daily; status is ok, reconciled, drift or error, and reconciliation says how many wallets were replayed, how many lacked an opening balance or could not be read, and any overdraw. Selling commission is normal; the figures describe on-chain movements, not intent. The daily trace job has not published its first traces yet, so every validator answers 404 until it does; /commission-flows reports how many are traced.","parameters":[{"name":"validator","in":"query","required":true,"schema":{"type":"string"},"example":"cosmosvaloper18ruzecmqj9pv8ac0gvkgryuc7u004te9rh7w5s","description":"Operator address, cosmosvaloper1... The bech32 checksum is verified, so a typo is a 400, not an empty statement."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"rule","in":"query","required":false,"schema":{"type":"string","enum":["fifo","pro_rata"],"default":"fifo"}},{"name":"start","in":"query","required":false,"schema":{"type":"string","example":"2026-01"},"description":"First month, YYYY-MM (a YYYY-MM-DD date is read as its month)."},{"name":"end","in":"query","required":false,"schema":{"type":"string","example":"2026-12"},"description":"Last month, inclusive."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"csv has one row per month and class: month, withdrawn_atom, class, detail, via_unbonding, amount_atom, share, usd_at_withdrawal."}],"responses":{"200":{"description":"The trace.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"mainnet"},"validator":{"type":"string"},"moniker":{"type":"string"},"rule":{"type":"string","enum":["fifo","pro_rata"]},"rules":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["ok","reconciled","drift","error"]},"reason":{"type":"string"},"from":{"type":"string","format":"date"},"as_of":{"type":"string","format":"date","nullable":true},"reconciliation":{"type":"object"},"receivers":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"first_withdrawal":{"type":"string","format":"date-time"},"last_withdrawal":{"type":"string","format":"date-time"},"withdrawals":{"type":"integer"},"amount_base":{"type":"string"},"amount":{"type":"string"}}}},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","example":"2026-09","description":"YYYY-MM, or total."},"withdrawn":{"type":"string","description":"Commission withdrawn in the month, ATOM."},"price_usd":{"type":"string","nullable":true},"withdrawn_usd":{"type":"string","nullable":true},"untracked":{"type":"object","additionalProperties":{"type":"string"},"description":"Commission in other denoms, base units, not traced."},"flows":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","example":"restaked_own"},"detail":{"type":"string"},"via_unbonding":{"type":"boolean"},"amount":{"type":"string"},"share":{"type":"string"},"usd_at_withdrawal":{"type":"string","nullable":true}}}}}}},"total":{"type":"object","properties":{"month":{"type":"string","example":"2026-09","description":"YYYY-MM, or total."},"withdrawn":{"type":"string","description":"Commission withdrawn in the month, ATOM."},"price_usd":{"type":"string","nullable":true},"withdrawn_usd":{"type":"string","nullable":true},"untracked":{"type":"object","additionalProperties":{"type":"string"},"description":"Commission in other denoms, base units, not traced."},"flows":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","example":"restaked_own"},"detail":{"type":"string"},"via_unbonding":{"type":"boolean"},"amount":{"type":"string"},"share":{"type":"string"},"usd_at_withdrawal":{"type":"string","nullable":true}}}}}},"classes":{"type":"object","additionalProperties":{"type":"string"}},"method":{"type":"string"},"symbol":{"type":"string","example":"ATOM"}}}},"text/csv":{"schema":{"type":"string"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Missing or invalid validator, rule, month or format.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"404":{"description":"No trace for this validator yet: the daily job has not traced it (no validator is traced until the job's first run lands), or the operator address is unknown.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/commission-flows":{"get":{"tags":["Validators"],"summary":"Where commission goes across the Hub","description":"The validator-commission-flows classes summed over every traced validator, by month. There is no per-validator breakdown and the figures are never used to rank validators. Only IBC and exchange lines keep their detail. Validators whose trace failed are counted in statuses and left out of the sums. Until the daily trace job publishes its first traces, validators is 0, months is empty and the USD fields of total are null: an honest empty answer, not an error.","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."},{"name":"rule","in":"query","required":false,"schema":{"type":"string","enum":["fifo","pro_rata"],"default":"fifo"},"description":"How coins mixed with other coins are split: first in first out, or pro-rata."},{"name":"start","in":"query","required":false,"schema":{"type":"string","example":"2026-01"},"description":"First month, YYYY-MM."},{"name":"end","in":"query","required":false,"schema":{"type":"string","example":"2026-12"},"description":"Last month, inclusive."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"}}],"responses":{"200":{"description":"The Hub-wide sum.","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string","example":"mainnet"},"rule":{"type":"string","enum":["fifo","pro_rata"]},"rules":{"type":"array","items":{"type":"string"}},"validators":{"type":"integer","description":"Validators with a trace in the sum. 0 until the daily trace job's first run."},"statuses":{"type":"object","additionalProperties":{"type":"integer"},"description":"Validators per trace status."},"as_of":{"type":"string","format":"date","nullable":true},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","example":"2026-09","description":"YYYY-MM, or total."},"withdrawn":{"type":"string","description":"Commission withdrawn in the month, ATOM."},"price_usd":{"type":"string","nullable":true},"withdrawn_usd":{"type":"string","nullable":true},"untracked":{"type":"object","additionalProperties":{"type":"string"},"description":"Commission in other denoms, base units, not traced."},"flows":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","example":"restaked_own"},"detail":{"type":"string"},"via_unbonding":{"type":"boolean"},"amount":{"type":"string"},"share":{"type":"string"},"usd_at_withdrawal":{"type":"string","nullable":true}}}}}}},"total":{"type":"object","properties":{"month":{"type":"string","example":"2026-09","description":"YYYY-MM, or total."},"withdrawn":{"type":"string","description":"Commission withdrawn in the month, ATOM."},"price_usd":{"type":"string","nullable":true},"withdrawn_usd":{"type":"string","nullable":true},"untracked":{"type":"object","additionalProperties":{"type":"string"},"description":"Commission in other denoms, base units, not traced."},"flows":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","example":"restaked_own"},"detail":{"type":"string"},"via_unbonding":{"type":"boolean"},"amount":{"type":"string"},"share":{"type":"string"},"usd_at_withdrawal":{"type":"string","nullable":true}}}}}},"classes":{"type":"object","additionalProperties":{"type":"string"}},"method":{"type":"string"},"symbol":{"type":"string"}}}},"text/csv":{"schema":{"type":"string"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid rule, month or format.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/validators/jurisdictions":{"get":{"tags":["Validators"],"summary":"Validator jurisdiction attestations","description":"Validators whose operator account attested a country of establishment on chain: a successful transaction signed by the operator account (the cosmos1 form of the cosmosvaloper address) with the memo `bryanlabs-tax:jurisdiction v1 country=<ISO alpha-2> [entity=\"Legal Name\"] [source=https://...]`. The transaction hash is the source and the block time the attestation date; the latest attestation wins and country=none revokes. Nothing is inferred from websites or monikers, and every other validator is reported as undisclosed. Each row carries the validator's current status (bonded, unbonding, unbonded, jailed) so a reader can tell an active validator from one that has left the set. Validate a memo first with /validators/attest/check.","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."}],"responses":{"200":{"description":"The attestations.","content":{"application/json":{"schema":{"type":"object","properties":{"basis":{"type":"string"},"chain":{"type":"string","example":"mainnet"},"validators_on_chain":{"type":"integer"},"validators_disclosed":{"type":"integer"},"undisclosed_label":{"type":"string","example":"undisclosed"},"how_to_attest":{"type":"object","additionalProperties":{"type":"string"}},"jurisdictions":{"type":"array","items":{"type":"object","properties":{"operator_address":{"type":"string"},"account_address":{"type":"string"},"moniker":{"type":"string"},"status":{"type":"string","example":"bonded"},"country":{"type":"string","example":"CH"},"entity":{"type":"string"},"source":{"type":"string","format":"uri"},"tx_hash":{"type":"string"},"block_height":{"type":"integer"},"disclosed_at":{"type":"string","format":"date-time"},"revoked":{"type":"boolean"}}}}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Unknown or unsupported chain.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/validators/attest/check":{"get":{"tags":["Validators"],"summary":"Validate a jurisdiction attestation memo","description":"Parses a bryanlabs-tax:jurisdiction memo exactly as the indexer would and reports whether it is valid, what it attests, and (given an operator address) which account must sign the transaction for it to count. Nothing is recorded; the registry only reads memos that landed on chain.","parameters":[{"name":"memo","in":"query","required":true,"schema":{"type":"string"},"example":"bryanlabs-tax:jurisdiction v1 country=CH entity=\"Example Validator AG\" source=https://example.com/imprint"},{"name":"operator","in":"query","required":false,"schema":{"type":"string"},"example":"cosmosvaloper1..."},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."}],"responses":{"200":{"description":"The verdict.","content":{"application/json":{"schema":{"type":"object","properties":{"memo":{"type":"string"},"valid":{"type":"boolean"},"error":{"type":"string"},"parsed":{"type":"object","properties":{"country":{"type":"string"},"entity":{"type":"string"},"source":{"type":"string"},"revoke":{"type":"boolean"}}},"operator_address":{"type":"string"},"operator_error":{"type":"string"},"must_be_signed_by":{"type":"string","description":"The cosmos1 account that must sign."},"moniker":{"type":"string"},"status":{"type":"string"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"memo is required.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/v1/chain/releases":{"get":{"tags":["Reference"],"summary":"Gaia release tracking","description":"Every Gaia (Cosmos Hub) release the indexer has reviewed with its tax-layer impact, the upstream changes announced but not released, and the latest run of the daily release watcher: the node's version and SDK, the newest upstream release, any pending upgrade plan, and whether a release needs review (attention).","parameters":[{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"cosmoshub"},"description":"Chain id. Default: cosmoshub. Enabled values: cosmoshub."}],"responses":{"200":{"description":"Release tracking.","content":{"application/json":{"schema":{"type":"object","properties":{"attention":{"type":"boolean"},"stale":{"type":"boolean"},"latest_reviewed":{"type":"object"},"releases":{"type":"array","items":{"type":"object","properties":{"version":{"type":"string","example":"v21.0.1"},"date":{"type":"string","format":"date"},"upgrade_height":{"type":"integer","nullable":true,"description":"The block the release took effect at on mainnet."},"cosmos_sdk":{"type":"string"},"summary":{"type":"string"},"indexer_impact":{"type":"string"},"reviewed":{"type":"boolean"}}}},"upcoming_changes":{"type":"array","items":{"type":"string"}},"watcher":{"type":"object","nullable":true}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"400":{"description":"Unknown or unsupported chain.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}}}},"429":{"description":"More than 60 requests in 60 seconds from this IP (code rate_limited). Retry after Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}},"503":{"description":"Tax service unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"RateLimit":{"description":"Current window state, for example `\"hourly\";r=12;t=1812` (requests remaining, seconds to reset).","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The policy in force, for example `\"hourly\";q=1000;w=3600` (quota, window seconds).","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Present on 429 and 503.","schema":{"type":"integer"}}}}}}},"/api/tax/reports":{"get":{"tags":["Saved reports"],"summary":"List my saved reports","description":"Every saved report of the calling account: name, chain, addresses, period, entity, asset decisions and tags. Requires the site session or an API key with `tax:read`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[],"responses":{"200":{"description":"The reports.","content":{"application/json":{"schema":{"type":"object","properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/SavedReport"}}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:read scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"post":{"tags":["Saved reports"],"summary":"Save a report query","description":"Creates a saved report for the calling account. Names are unique per account. Requires `tax:write`. Tags and asset decisions are validated the same way as the `tags` and `asset_decisions` parameters.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","chain","addresses"],"properties":{"name":{"type":"string","maxLength":80},"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"minItems":1},"startDate":{"type":"string","nullable":true,"description":"ISO date-time or null for all time."},"endDate":{"type":"string","nullable":true},"entity":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"type":{"type":"string"},"retirement":{"type":"boolean"}}},"assetDecisions":{"type":"object","additionalProperties":{"type":"object"}},"userTags":{"$ref":"#/components/schemas/UserTags"}}}}}},"responses":{"201":{"description":"Created.","content":{"application/json":{"schema":{"type":"object","properties":{"report":{"$ref":"#/components/schemas/SavedReport"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid body, address, tag or decision.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"A report with that name already exists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/reports/{id}":{"get":{"tags":["Saved reports"],"summary":"Read a saved report with its data","description":"The saved query plus its computed report (same pipeline as the website; `?resync=true` forces a fresh computation) and the exact export and document request bodies that replay it. Requires `tax:read`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"name":"resync","in":"query","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"The report, its data and replayable export bodies.","content":{"application/json":{"schema":{"type":"object","properties":{"report":{"$ref":"#/components/schemas/SavedReport"},"data":{"type":"object"},"exports":{"type":"object"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:read scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"patch":{"tags":["Saved reports"],"summary":"Rename, or replace decisions or tags","description":"Changes the name, the whole asset-decision map, or the whole tag map. To change single tags without resending the rest use `PATCH /api/tax/reports/{id}/tags`. Requires `tax:write`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":80},"assetDecisions":{"type":"object","additionalProperties":{"type":"object"}},"userTags":{"$ref":"#/components/schemas/UserTags"}}}}}},"responses":{"200":{"description":"Updated.","content":{"application/json":{"schema":{"type":"object","properties":{"report":{"$ref":"#/components/schemas/SavedReport"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid body, tag or decision.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"A report with that name already exists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"delete":{"tags":["Saved reports"],"summary":"Delete a saved report","description":"Removes the saved query. The chain data is untouched. Requires `tax:write`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted (also when it did not exist).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/reports/{id}/viewed":{"post":{"tags":["Saved reports"],"summary":"Mark a saved report as viewed","description":"Records that the owner looked at the report now (`last_viewed_at`), which is what \"anything new since I last looked?\" compares against. The report page calls it on open. Requires `tax:read`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Recorded.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid report id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:read scope, or the account has no email.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/reports/{id}/tags":{"get":{"tags":["Saved reports"],"summary":"Read a report's tags","description":"The bookkeeping tags on the report, with the vocabulary. Requires `tax:read`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"The tags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTags"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:read scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"patch":{"tags":["Saved reports"],"summary":"Set or clear single tags","description":"Merges into the report's tags: `set` adds or changes tags, `clear` removes keys. Keys are a transaction hash (the whole transaction) or hash:denom (one asset in it); values are from /api/tax/v1/tags (internal_transfer, payment, income, gift, airdrop, protocol_deposit, expense, spam, lost). The website and every export, form and journal entry for the report follow the new tags on the next computation. Requires `tax:write`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"set":{"$ref":"#/components/schemas/UserTags"},"clear":{"type":"array","items":{"type":"string"},"description":"Keys to remove."}},"example":{"set":{"A5FE42C0B4E4E6E7E8F9A0B1C2D3E4F5A6B7C8D9E0F1A2B3C4D5E6F7A8B9C0D1":"internal_transfer"},"clear":["F28EE8E1D2C3B4A5968778695A4B3C2D1E0F1A2B3C4D5E6F7A8B9C0D1E2F3A4B"]}}}}},"responses":{"200":{"description":"The tags after the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTags"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Unknown tag, bad key, or more than 20000 tags.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"put":{"tags":["Saved reports"],"summary":"Replace all tags","description":"Replaces the whole tag map; `{\"tags\": {}}` clears every tag. Requires `tax:write`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tags"],"properties":{"tags":{"$ref":"#/components/schemas/UserTags"}}}}}},"responses":{"200":{"description":"The tags after the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportTags"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Unknown tag or bad key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/reports/{id}/tags/bulk":{"post":{"tags":["Saved reports"],"summary":"Tag every row that matches a filter","description":"Tags (or with `tag: null` untags) every transaction in the report that matches an events `type` filter and/or a list of hashes, in one call. `mode: fill` (default) leaves rows that already carry a tag alone; `overwrite` replaces them. `dry_run: true` reports the counts and saves nothing. The response says how many matched rows already have a default treatment (staking income, fees, delegations, swaps are classified by the engine and need no tag). Requires `tax:write`.","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTagRequest"}}}},"responses":{"200":{"description":"What changed (or would change).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTagResult"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"202":{"description":"The report is still computing; retry after `Retry-After` seconds (code report_pending).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Unknown tag or filter (codes invalid_tags, invalid_filter, invalid_request, too_many_tags).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key, or an unknown key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The key lacks the tax:write scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"Not one of the caller's reports.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"The report has no rows or failed to compute (code report_unavailable).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/forms":{"post":{"tags":["Files"],"summary":"IRS forms","description":"Form 8949 (filled IRS PDF, or CSV lines with format=csv), Schedule D (PDF), the income report for Schedule 1 (CSV), the Form 990-T unrelated business income estimate (CSV, or the worksheet PDF with form=990t-pdf), or the whole package (cover summary, Schedule D and Form 8949 in one PDF). A response header reports any unknown-basis total.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","addresses"],"properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"example":["cosmos1..."]},"startDate":{"type":"string","format":"date-time","nullable":true},"endDate":{"type":"string","format":"date-time","nullable":true},"assetDecisions":{"type":"object","description":"As on /api/tax/v1/events: keyed by record_id, denom:<raw_denom> or policy:spam."},"userTags":{"$ref":"#/components/schemas/UserTags"},"form":{"type":"string","enum":["8949","scheduled","income","990t","990t-pdf","package"],"default":"8949"},"format":{"type":"string","enum":["pdf","csv"],"default":"pdf"},"entity":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"retirement":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The form. When the period is not fully indexed, a PDF carries the notice on every page.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/pdf":{"schema":{"type":"string","format":"binary"}},"text/csv":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Missing or invalid chain, addresses, dates or form.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"No rows for this form in the period.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"500":{"description":"The PDF could not be generated; the CSV still works.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"502":{"description":"The tax service did not answer.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/export":{"post":{"tags":["Files"],"summary":"Tax software, books and CARF exports","description":"CSV in the import format of Koinly, CryptoTaxCalculator, CoinTracker, CoinLedger, Cryptio or Bitwave, a generic CSV, the general-ledger journal, or the CARF summary and event detail (with currency).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","addresses","format"],"properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"example":["cosmos1..."]},"startDate":{"type":"string","format":"date-time","nullable":true},"endDate":{"type":"string","format":"date-time","nullable":true},"assetDecisions":{"type":"object","description":"As on /api/tax/v1/events: keyed by record_id, denom:<raw_denom> or policy:spam."},"userTags":{"$ref":"#/components/schemas/UserTags"},"format":{"type":"string","enum":["koinly","cryptotaxcalculator","cointracker","coinledger","cryptio","bitwave","generic","journal","carf","carf-detail"]},"currency":{"type":"string","default":"USD","description":"carf and carf-detail only."}}}}}},"responses":{"200":{"description":"The CSV.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"text/csv":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Unknown format, currency, chain or address.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"No rows in the period.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"502":{"description":"The tax service did not answer.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/statement":{"post":{"tags":["Files"],"summary":"Period statement","description":"Opening and closing balances with the period's income, fees and activity for a group of addresses, as PDF (default) or CSV.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","addresses"],"properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"example":["cosmos1..."]},"startDate":{"type":"string","format":"date-time","nullable":true},"endDate":{"type":"string","format":"date-time","nullable":true},"assetDecisions":{"type":"object","description":"As on /api/tax/v1/events: keyed by record_id, denom:<raw_denom> or policy:spam."},"userTags":{"$ref":"#/components/schemas/UserTags"},"entityName":{"type":"string"},"format":{"type":"string","enum":["pdf","csv"],"default":"pdf"}}}}}},"responses":{"200":{"description":"The statement. When the period is not fully indexed, a PDF carries the notice on every page.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/pdf":{"schema":{"type":"string","format":"binary"}},"text/csv":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Missing or invalid chain, addresses or dates.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"502":{"description":"The tax service did not answer.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/evidence-bundle":{"post":{"tags":["Files"],"summary":"Evidence bundle","description":"One zip with the report CSVs, the coverage attestation and the methodology reference, for an auditor or a file.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","addresses"],"properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"example":["cosmos1..."]},"startDate":{"type":"string","format":"date-time","nullable":true},"endDate":{"type":"string","format":"date-time","nullable":true},"assetDecisions":{"type":"object","description":"As on /api/tax/v1/events: keyed by record_id, denom:<raw_denom> or policy:spam."},"userTags":{"$ref":"#/components/schemas/UserTags"},"entityName":{"type":"string"}}}}}},"responses":{"200":{"description":"The zip, with index-coverage.json for the period.","headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}},"X-Index-Coverage":{"description":"complete, incomplete (part of the period is not indexed yet) or unknown (coverage still being computed).","schema":{"type":"string","enum":["complete","incomplete","unknown"]}},"X-Index-Coverage-Warning":{"description":"Present when the period is not fully indexed: a plain-English notice to show with the data.","schema":{"type":"string"}},"X-Index-Coverage-Incomplete-Years":{"description":"Comma-separated calendar years in the period that are not fully indexed.","schema":{"type":"string","example":"2024,2025"}},"X-Index-Coverage-Note":{"description":"Present when the period starts before cosmoshub-4 genesis: those days are on earlier chains, are not indexed, and do not make the period incomplete.","schema":{"type":"string"}}},"content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Missing or invalid chain, addresses or dates.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"502":{"description":"The tax service did not answer.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/reconcile-1099da":{"post":{"tags":["Files"],"summary":"Reconcile a Form 1099-DA","description":"Matches broker-reported disposals against your own on-chain disposals and returns what matched, what the broker reported without basis, and what it missed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","addresses","brokerRows"],"properties":{"chain":{"type":"string","example":"cosmoshub"},"addresses":{"type":"array","items":{"type":"string"},"example":["cosmos1..."]},"startDate":{"type":"string","format":"date-time","nullable":true},"endDate":{"type":"string","format":"date-time","nullable":true},"assetDecisions":{"type":"object","description":"As on /api/tax/v1/events: keyed by record_id, denom:<raw_denom> or policy:spam."},"userTags":{"$ref":"#/components/schemas/UserTags"},"brokerRows":{"type":"array","items":{"type":"object","required":["asset","dateSold","proceeds"],"properties":{"asset":{"type":"string"},"description":{"type":"string"},"dateAcquired":{"type":"string","nullable":true},"dateSold":{"type":"string"},"proceeds":{"type":"number"},"costBasis":{"type":"number","nullable":true},"basisReportedToIrs":{"type":"boolean"}}}}}}}}},"responses":{"200":{"description":"The reconciliation.","content":{"application/json":{"schema":{"type":"object","properties":{"reconciled":{"type":"array","description":"One entry per broker row.","items":{"type":"object","properties":{"broker":{"type":"object","additionalProperties":true},"matched":{"type":"boolean"},"onChainMatches":{"type":"array","items":{"type":"object","additionalProperties":true}},"suggestedCostBasis":{"type":"number","nullable":true,"description":"Basis from your own lots when the broker reported none."},"brokerBasisMissing":{"type":"boolean"}}}},"onChainOnly":{"type":"array","description":"Your on-chain disposals the broker did not report.","items":{"type":"object","properties":{"address":{"type":"string"},"description":{"type":"string"},"dateSold":{"type":"string"},"proceeds":{"type":"number"},"costBasis":{"type":"number"},"basisUnknown":{"type":"boolean"}}}},"summary":{"type":"object","properties":{"totalBrokerRows":{"type":"integer"},"matched":{"type":"integer"},"noOnChainMatch":{"type":"integer"},"brokerBasisMissing":{"type":"integer"},"onChainOnlyCount":{"type":"integer"}}}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"No broker rows, or invalid input.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"Flagged receipts need a decision first (code asset_review_required). `pending` says how many; GET /api/tax/v1/asset-review lists them with their decision keys. Pass asset_decisions (keyed by record_id, denom:<raw_denom> or policy:spam) or spam_policy=valueless, or save the decisions in the report on the website.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"502":{"description":"The tax service could not be reached or failed (code upstream_error). Retry shortly.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/entities":{"get":{"tags":["Account settings"],"summary":"List entities","security":[{"ApiKey":[]},{"Session":[]}],"description":"The calling account's entities (a person, an S-Corp, an HSA, a Roth IRA or a solo 401(k)) with their addresses. Session or an API key with tax:read.","responses":{"200":{"description":"The entities.","content":{"application/json":{"schema":{"type":"object","properties":{"entities":{"type":"array","items":{"$ref":"#/components/schemas/TaxEntity"}}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:read scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"post":{"tags":["Account settings"],"summary":"Create an entity","security":[{"ApiKey":[]},{"Session":[]}],"description":"Names are unique per account. Session or an API key with tax:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string","maxLength":80,"example":"Roth IRA"},"type":{"type":"string","enum":["personal","scorp","hsa","roth","solo401k"]},"addresses":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"The entity.","content":{"application/json":{"schema":{"type":"object","properties":{"entity":{"$ref":"#/components/schemas/TaxEntity"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid name, type or address.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:write scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"An entity with this name already exists (code duplicate_entity_name).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/entities/{id}":{"patch":{"tags":["Account settings"],"summary":"Change an entity","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"description":"Send any of name, type and addresses. Only the calling account's own entities are found. Session or an API key with tax:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":80},"type":{"type":"string","enum":["personal","scorp","hsa","roth","solo401k"]},"addresses":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"The entity.","content":{"application/json":{"schema":{"type":"object","properties":{"entity":{"$ref":"#/components/schemas/TaxEntity"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid id, body or address.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:write scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"404":{"description":"No such entity on this account.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"409":{"description":"An entity with this name already exists (code duplicate_entity_name).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"delete":{"tags":["Account settings"],"summary":"Delete an entity","security":[{"ApiKey":[]},{"Session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"description":"Removes the entity; its wallets and saved reports are untouched. Session or an API key with tax:write.","responses":{"200":{"description":"Deleted (also when it did not exist).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Invalid entity id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:write scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/preferences":{"get":{"tags":["Account settings"],"summary":"Read tax preferences","security":[{"ApiKey":[]},{"Session":[]}],"description":"Reporting locale, the default spam policy and remembered per-token asset rules with their change log. Session or an API key with tax:read.","responses":{"200":{"description":"The preferences.","content":{"application/json":{"schema":{"type":"object","properties":{"preferences":{"$ref":"#/components/schemas/TaxPreferences"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:read scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}},"put":{"tags":["Account settings"],"summary":"Change tax preferences","security":[{"ApiKey":[]},{"Session":[]}],"description":"Send any of locale (ISO country code, or null to follow the browser), spamPolicy (ask or valueless) and assetRules (up to 500, keyed by denom:<raw_denom>). Session or an API key with tax:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"locale":{"type":"string","nullable":true,"example":"CH"},"spamPolicy":{"type":"string","enum":["ask","valueless"],"nullable":true},"assetRules":{"type":"object","additionalProperties":{"type":"object","properties":{"decision":{"type":"object"},"label":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}},"responses":{"200":{"description":"The preferences after the change.","content":{"application/json":{"schema":{"type":"object","properties":{"preferences":{"$ref":"#/components/schemas/TaxPreferences"}}}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"400":{"description":"Unknown country code, invalid rule, or nothing valid to change.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"401":{"description":"No session and no API key (code unauthorized, with WWW-Authenticate), or an unknown, revoked or expired key (code invalid_api_key).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}},"403":{"description":"The API key lacks the tax:write scope (code insufficient_scope).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}},"/api/tax/v1/openapi.json":{"get":{"tags":["Reference"],"summary":"This document","description":"The OpenAPI 3.1 document for this API, raw.","parameters":[],"responses":{"200":{"description":"OpenAPI document.","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"X-Request-Id":{"description":"Correlation id for this request. Send your own on the request to have it echoed.","schema":{"type":"string"}}}}}}}},"components":{"securitySchemes":{"Session":{"type":"apiKey","in":"cookie","name":"__Secure-bryanlabs.session-token","description":"The site session. Browser calls carry it automatically."},"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"blk_...","description":"A personal API key from Account, sent as Authorization: Bearer. Carries the scopes it was created with."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 Problem Details. `code` is the stable, documented reason; `detail` is for humans.","required":["type","title","status","detail","code"],"properties":{"type":{"type":"string","format":"uri","description":"Link to the code's entry in the API conventions."},"title":{"type":"string","description":"Short summary of the status."},"status":{"type":"integer"},"detail":{"type":"string","description":"What went wrong, for a person."},"code":{"type":"string","description":"Stable machine-readable reason, safe to branch on."},"instance":{"type":"string","description":"Path of the request."},"request_id":{"type":"string","description":"Same value as the X-Request-Id header. Quote it when asking for help."},"retry_after":{"type":"integer","description":"Seconds until the request can succeed, when the refusal is temporary."},"error":{"type":"string","deprecated":true,"description":"Alias of detail. Sunset 2027-04-01."},"success":{"type":"boolean","deprecated":true,"description":"Always false. Sunset 2027-04-01."}},"additionalProperties":true,"examples":[{"type":"https://bryanlabs.net/api-docs/conventions#not_found","title":"Not Found","status":404,"detail":"No snapshot for that chain.","code":"not_found","instance":"/api/snapshots/v1/chains/nope/snapshots/latest","request_id":"3b1e4f0a-7c2d-4e8b-9a61-1f0c2d3e4a5b"}]},"PeriodCoverage":{"type":"object","description":"Whether a requested period is fully indexed. When complete is false, warning is a notice to show with the data.","properties":{"status":{"type":"string","enum":["complete","incomplete","unknown"]},"complete":{"type":"boolean"},"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date","description":"Last day of the period that was checked, inclusive. Capped at the latest indexed block."},"before_genesis":{"type":"boolean","description":"The period starts before cosmoshub-4 genesis. Earlier Cosmos Hub chains are not indexed; those days count as covered and note says so."},"incomplete_years":{"type":"array","items":{"type":"object","properties":{"year":{"type":"integer"},"percent_indexed":{"type":"number"},"indexed_blocks":{"type":"integer"},"expected_blocks":{"type":"integer"},"earliest_covered_date":{"type":"string","format":"date","nullable":true},"latest_covered_date":{"type":"string","format":"date","nullable":true}}}},"warning":{"type":"string"},"note":{"type":"string","description":"Information that does not make the period incomplete, such as the days before genesis."}}},"IndexCoverage":{"type":"object","properties":{"chain_id":{"type":"string","example":"cosmoshub"},"chain":{"type":"string","example":"cosmoshub-4"},"status":{"type":"string","enum":["ready","scanning"],"description":"scanning until every height has been read once; until then unread heights count as not indexed."},"criterion":{"type":"string","description":"What counts as an indexed block."},"genesis_height":{"type":"integer","example":5200791},"genesis_date":{"type":"string","format":"date","example":"2021-02-18"},"tip_height":{"type":"integer"},"tip_time":{"type":"string","format":"date-time"},"computed_at":{"type":"string","format":"date-time"},"complete":{"type":"boolean","description":"Every block from genesis to the tip is indexed."},"indexed_range":{"type":"object","nullable":true,"properties":{"first_height":{"type":"integer"},"last_height":{"type":"integer"},"blocks":{"type":"integer"},"from":{"type":"string","format":"date"},"through":{"type":"string","format":"date"}}},"years":{"type":"array","items":{"type":"object","properties":{"year":{"type":"integer","example":2025},"first_height":{"type":"integer"},"last_height":{"type":"integer"},"expected_blocks":{"type":"integer"},"indexed_blocks":{"type":"integer"},"tx_indexed_blocks":{"type":"integer"},"block_events_indexed_blocks":{"type":"integer"},"percent_indexed":{"type":"number","description":"Rounded down to 0.1, so 100 means complete."},"complete":{"type":"boolean"},"tx_complete":{"type":"boolean"},"block_events_complete":{"type":"boolean"},"in_progress":{"type":"boolean","description":"The current year, still being produced."},"earliest_covered_date":{"type":"string","format":"date","nullable":true},"latest_covered_date":{"type":"string","format":"date","nullable":true},"covered_ranges":{"type":"array","description":"Fully covered UTC date ranges, at most 50.","items":{"type":"object","properties":{"from":{"type":"string","format":"date"},"through":{"type":"string","format":"date"}}}},"covered_range_count":{"type":"integer"},"gaps":{"type":"array","description":"Unindexed block ranges, at most 50.","items":{"type":"object","properties":{"first_height":{"type":"integer"},"last_height":{"type":"integer"},"blocks":{"type":"integer"},"from":{"type":"string","format":"date"},"through":{"type":"string","format":"date"}}}},"gap_count":{"type":"integer"}}}},"note":{"type":"string"},"period":{"$ref":"#/components/schemas/PeriodCoverage"}}},"UserTags":{"type":"object","description":"Bookkeeping tags keyed by transaction hash or hash:denom. Values from /api/tax/v1/tags. An empty string removes the key.","additionalProperties":{"type":"string","enum":["internal_transfer","payment","income","gift","airdrop","protocol_deposit","expense","spam","lost",""]},"example":{"A5FE42C0B4E4E6E7E8F9A0B1C2D3E4F5A6B7C8D9E0F1A2B3C4D5E6F7A8B9C0D1":"internal_transfer"}},"ReportTags":{"type":"object","properties":{"report_id":{"type":"integer"},"tags":{"$ref":"#/components/schemas/UserTags"},"count":{"type":"integer"},"changed":{"type":"object","properties":{"set":{"type":"integer"},"cleared":{"type":"integer"}}},"vocabulary":{"type":"array","items":{"type":"string"}},"vocabulary_url":{"type":"string"},"key_forms":{"type":"array","items":{"type":"string"}}}},"BulkTagRequest":{"type":"object","required":["tag"],"properties":{"tag":{"type":"string","nullable":true,"description":"A tag from /api/tax/v1/tags, or null to clear.","example":"internal_transfer"},"filter":{"type":"string","enum":["all","rewards","staking","income","transfers","ibc_in","ibc_out","ibc","swaps","fees","delegations","nfts"],"description":"Rows to address, the same groups as the events `type` parameter.","example":"ibc_out"},"tx_hashes":{"type":"array","items":{"type":"string"},"description":"Optional explicit hashes; intersected with the filter when both are sent."},"mode":{"type":"string","enum":["fill","overwrite"],"default":"fill"},"dry_run":{"type":"boolean","default":false}}},"BulkTagResult":{"type":"object","properties":{"report_id":{"type":"integer"},"dry_run":{"type":"boolean"},"tag":{"type":"string","nullable":true},"filter":{"type":"string","nullable":true},"mode":{"type":"string"},"matched_rows":{"type":"integer"},"matched_transactions":{"type":"integer"},"changed":{"type":"integer"},"skipped_already_tagged":{"type":"integer"},"matched_with_default_treatment":{"type":"integer"},"note":{"type":"string"},"tags_count":{"type":"integer"},"sample":{"type":"array","items":{"type":"string"}}}},"TaxEntity":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"type":{"type":"string","enum":["personal","scorp","hsa","roth","solo401k"]},"addresses":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"TaxPreferences":{"type":"object","properties":{"locale":{"type":"string","nullable":true,"example":"CH","description":"ISO country code, or null to follow the browser."},"spamPolicy":{"type":"string","enum":["ask","valueless"],"nullable":true},"assetRules":{"type":"object","description":"Remembered decisions keyed by denom:<raw_denom>.","additionalProperties":{"type":"object","additionalProperties":true}},"assetRulesLog":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"key":{"type":"string"},"action":{"type":"string","enum":["set","clear"]},"label":{"type":"string"},"mode":{"type":"string"}}}},"updatedAt":{"type":"string","format":"date-time","nullable":true}}},"SavedReport":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"chain":{"type":"string"},"addresses":{"type":"array","items":{"type":"string"}},"startDate":{"type":"string","nullable":true},"endDate":{"type":"string","nullable":true},"entity":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"type":{"type":"string"},"retirement":{"type":"boolean"}}},"assetDecisions":{"type":"object","additionalProperties":{"type":"object"}},"userTags":{"$ref":"#/components/schemas/UserTags"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}