Bicora API · v1

Access standardized Bitcoin DeFi risk indicators.

Read-only JSON over HTTP. Every response is derived from the latest scoring snapshot (methodology v1.0.0) and is refreshed on the pipeline schedule (every 6 hours). The v1 API runs locally or self-hosted today; a hosted public API is planned. No authentication is required in v0.1; responses are cacheable for 60 seconds. All monetary values are USD unless a field says BTC or STX, and all scores are 0–100 where higher means lower risk.

Base URL
http://localhost:4000
Self-hosted. Hosted api.bicora.xyz: planned.

Running the stack

npm install
npm run pipeline      # index Stacks data, then compute scores -> data/snapshot.json
npm run api           # http://localhost:4000  (file store, or PostgreSQL when DATABASE_URL is set)
npm run dashboard     # http://localhost:3000  (reads API_URL when set, else the committed snapshot)
GET

/health

Service status: the store in use (file or PostgreSQL), the generation time of the snapshot being served and the methodology version.

Example
curl http://localhost:4000/health

{ "ok": true, "store": "file", "snapshotAt": "2026-10-06T02:49:19.530Z", "methodology": "1.0.0" }
GET

/v1/snapshot

Returns the full denormalised snapshot the dashboard renders, with camelCase field names. It is the only endpoint that carries the informational Bitcoin Staking block (staking) and the per-protocol data-quality fields (dataQuality, metrics.activitySampled). Returns 503 until the pipeline has produced a snapshot.

Example
curl http://localhost:4000/v1/snapshot

{
  "generatedAt": "2026-10-06T02:49:19.530Z",
  "methodologyVersion": "1.0.0",
  "market": { "protocolsTracked": 5, "totalTvlUsd": 146687220.8, ... },
  "protocols": [ { "slug": "zest", "metrics": { ... }, "dataQuality": { ... }, "score": { ... }, ... } ],
  "events": [ ... ],
  "staking": {
    "source": "live",
    "fetchedAt": "2026-10-06T02:49:19.530Z",
    "stackedStx": 448329575.89,
    "stxPriceUsd": 0.375632,
    "stackingTvlUsd": 168406935.25,
    "pctSupplyStacked": 0.2395,
    "currentCycle": 144,
    "btcYieldPerCycleEst": 9.2278,
    "targetBtcApy": 0.03,
    "btcBonded": null,
    "liquidStackedUsd": 30240635.31,
    "history": [ { "cycle": 144, "stackedStx": 448279555.39, "signers": 31 }, ... ],
    ...
  }
}
GET

/v1/protocol-risk

Returns protocol risk metrics: the overall score and band, the four component scores with every factor, effective weights, current liquidity, 7-day activity and the daily history for the requested window.

Query parameters
NameTypeDescription
protocolstringProtocol slug, e.g. zest. Omit for all tracked protocols. Unknown slugs return 404.
window7d | 30d | 90dHistory window for tvl_history and score_history. Default 30d.
Example
curl "http://localhost:4000/v1/protocol-risk?protocol=zest&window=7d"

{
  "updated_at": "2026-09-18T06:25:31.000Z",
  "methodology_version": "1.0.0",
  "protocols": [{
    "protocol": "zest",
    "name": "Zest Protocol",
    "category": "Lending",
    "overall_score": 68,
    "band": "Moderate",
    "liquidity_score": 72.5,
    "activity_score": 16.3,
    "collateral_health": 93.9,
    "transparency_score": 93.7,
    "effective_weights": { "liquidity": 30, "activity": 25, "collateral": 25, "transparency": 20 },
    "liquidity_usd": 65385202,
    "borrowed_usd": 13581728,
    "tvl_source": "DefiLlama",
    "tvl_fetched_at": "2026-09-18T06:21:04.000Z",
    "tvl_as_of": "2026-09-18T06:00:00.000Z",
    "utilization": 0.172,
    "tx_7d": 104,
    "unique_senders_7d": 34,
    "score_delta_7d": null,
    "components": [ { "key": "liquidity", "factors": [ ... ] }, ... ],
    "tvl_history": [ { "date": "2026-09-12", "tvlUsd": 64210044, "borrowedUsd": 13402112 }, ... ],
    "score_history": [ { "date": "2026-09-18", "overall": 68, ... } ]
  }]
}
GET

/v1/market-health

Returns ecosystem metrics across the tracked protocols: liquidity tracked with 7d / 30d change, active addresses, transactions, the average risk score, the band distribution and the 90-day ecosystem TVL series. Bitcoin Staking values are not included in any of these figures.

Example
curl http://localhost:4000/v1/market-health

{
  "updated_at": "2026-09-18T06:25:31.000Z",
  "protocols": 5,
  "liquidity_usd": 109789459,
  "bicora_overlap_adjusted_estimate_usd": 104512010,
  "mapped_receipt_token_overlap_usd": 5277449,
  "mapped_receipt_tokens": ["STSTX", "STSTXBTC", "STBTC"],
  "liquidity_change_7d": 0.015,
  "liquidity_change_30d": -0.042,
  "active_addresses_7d": 223,
  "transactions_7d": 2830,
  "avg_risk_score": 63,
  "band_distribution": { "Low": 0, "Moderate": 3, "Elevated": 2, "High": 0 },
  "tvl_history": [ ... ]
}
GET

/v1/risk-alerts

Returns detected risk events such as liquidity movement, utilisation thresholds, activity swings and score changes (at most 200). Each event carries a severity (info, watch, alert) and the measured delta. No events are generated from Bitcoin Staking data.

Query parameters
NameTypeDescription
sinceISO 8601Only events at or after this timestamp.
kindstringliquidity | activity | collateral | transparency | score
Example
curl "http://localhost:4000/v1/risk-alerts?since=2026-09-17T00:00:00Z"

{
  "events": [
    { "slug": "zest", "ts": "2026-09-18T06:25:31.000Z", "kind": "activity", "severity": "watch",
      "message": "Zest Protocol transaction success rate 67% over 7 days", "delta": 0.667 }
  ]
}
GET

/v1/methodology

Returns the methodology version, the nominal component weights and the risk band thresholds, so integrators can label scores consistently.

Example
curl http://localhost:4000/v1/methodology

{
  "version": "1.0.0",
  "scale": "0-100, higher is safer",
  "weights": { "liquidity": 0.3, "activity": 0.25, "collateral": 0.25, "transparency": 0.2 },
  "bands": { "Low": "75-100", "Moderate": "60-74", "Elevated": "40-59", "High": "0-39" },
  "docs": "https://bicora.xyz/methodology"
}

TVL & on-chain pipeline

One scheduled run (GitHub Actions, every 6 hours at minute 17 UTC) executes two steps and commits the result:

  1. Indexer (backend/indexer). For each protocol in config/protocols.json: TVL, borrowed and token breakdown from DefiLlama; contract metadata and 14 days of transactions on the registered contracts from the Hiro Stacks API. Writes one raw record per protocol.
  2. Scoring engine (backend/scoring-engine). Cleans TVL history (adapter outliers below 5% of the 90-day median are excluded and counted), scores each protocol, detects events, builds ecosystem aggregates, then builds the informational Bitcoin Staking block from Hiro PoX endpoints and CoinGecko. Writes the snapshot served by the API and the dashboard.

Where TVL comes from today

  • Every protocol TVL value Bicora serves (liquidity_usd, borrowed_usd, tvl_history, market-health totals, liquidStackedUsd) is DefiLlama’s figure for the Stacks chain, labelled “TVL · DefiLlama” on the dashboard with its fetch time. These are the only TVL values used by the Risk Index. What each adapter covers is listed under protocol TVL coverage.
  • On-chain data from Hiro is used for contract existence, contract age and transaction activity, not for TVL.
  • The one USD value Bicora computes itself is staking.stackingTvlUsd (on-chain PoX state × CoinGecko price). It is informational and outside the Risk Index.

Bicora-calculated protocol TVL Planned

A protocol TVL computed by Bicora from on-chain contract balances is not implemented. It is not in the pipeline, the snapshot or the API, and nothing on this page or the dashboard is derived from it. It is planned as a parallel comparison against DefiLlama only. Scores use DefiLlama TVL; changing the scoring input would require a new methodology version.

Data sources

All sources are public. A Hiro API key (HIRO_API_KEY) is optional and only raises rate limits.

SourceEndpointWhat is readUsed for
DefiLlamaGET /protocol/{llamaSlug}Stacks-chain TVL series (chainTvls.Stacks, excludes borrowed), Stacks-borrowed series, current values, latest token breakdown in USDProtocol TVL, borrowed, utilisation, TVL history, ecosystem totals, liquid-stacked overlap
Hiro Stacks APIGET /extended/v1/contract/{id}Contract existence, deploy block height, source sizeContract coverage, transparency inputs
Hiro Stacks APIGET /extended/v1/tx/{deploy tx}Deployment time (Bitcoin block time)Contract age
Hiro Stacks APIGET /extended/v1/address/{contract}/transactionsTransactions on each registered contract, newest first: 50 per page, up to 24 pages (1,200) per contract per run, back 14 daystx_7d, unique_senders_7d, success rate, week-over-week trend
Hiro Stacks APIGET /v2/poxActive PoX state: STX stacked this cycle, liquid supply, cycle and phase lengths, blocks to next cycle, minimum thresholdBitcoin Staking (informational)
Hiro Stacks APIGET /extended/v2/pox/cycles?limit=16Total stacked and signer count per reward cycleBitcoin Staking cycle history (informational)
Hiro Stacks APIGET /extended/v1/burnchain/rewards?limit=250Most recent PoX reward payouts on Bitcoin (canonical only)Realized BTC rewards estimate (informational)
CoinGeckoGET /simple/price?ids=blockstackSTX spot price in USD at run timeBitcoin Staking USD value only (informational)
stacks.co (cited)stacks.co/bitcoin-stakingTarget BTC APY (~3%), cumulative BTC distributed (~4,224 BTC, read 2026-09), bond period (25,200 blocks)Static reference values on the staking block, not live data

Failed requests are retried with exponential backoff on HTTP 429, 5xx and network errors. A failure after retries is recorded rather than replaced with a guess (see data status).

Contract coverage

Activity metrics and contract-age inputs are measured only on these registered contracts. Transactions that reach a protocol through other contracts (routers, aggregators, newer versions not yet registered) are not counted, so activity can be understated. The list below is read from the current snapshot.

ProtocolContractRoleIndexed
StackingDAO
Liquid Stacking
SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-stx-v2stSTX core (deposit / withdraw)Yes
StackingDAO
Liquid Stacking
SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-ststxbtc-v2stSTXbtc coreYes
StackingDAO
Liquid Stacking
SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-stbtc-v1stBTC coreYes
StackingDAO
Liquid Stacking
SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.ststx-tokenstSTX tokenYes
Zest Protocol
Lending
SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.borrow-helper-v2-1-8User entry point (supply / withdraw / borrow / repay / liquidation-call)Yes
Zest Protocol
Lending
SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-borrow-v2-1Pool borrow coreYes
Zest Protocol
Lending
SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-0-reserve-v2-0Reserve stateYes
ALEX
DEX / AMM
SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01AMM v2 poolYes
ALEX
DEX / AMM
SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-vault-v2-01AMM v2 vaultYes
Bitflow
DEX / AMM
SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M.stableswap-stx-ststx-v-1-2StableSwap STX/stSTXYes
Bitflow
DEX / AMM
SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M.stableswap-usda-aeusdc-v-1-4StableSwap USDA/aeUSDCYes
Bitflow
DEX / AMM
SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M.stableswap-aeusdc-susdt-v-1-2StableSwap aeUSDC/sUSDTYes
Granite
Lending
SPSX722NK9V3A8D3CVQT0CDY4EBQ3E9FSDDE61FT.borrower-v1Borrower (USDCx market v2)Yes
Granite
Lending
SPSX722NK9V3A8D3CVQT0CDY4EBQ3E9FSDDE61FT.liquidity-provider-v1Liquidity provider (USDCx market v2)Yes
Granite
Lending
SP3M2BYF7RGF8WKW5FVDNJ6WR8D7AR9BHDXAKPXZE.borrower-v1Borrower (USDCx market v1)Yes
Granite
Lending
SP26NGV9AFZBX7XBDBS2C7EC7FCPSAV9PKREQNMVS.borrower-v1Borrower (aeUSDC market)Yes
Granite
Lending
SP26NGV9AFZBX7XBDBS2C7EC7FCPSAV9PKREQNMVS.liquidity-provider-v1Liquidity provider (aeUSDC market)Yes
  • TVL does not come from these contracts. DefiLlama’s adapter for each protocol defines which contracts its TVL covers.
  • Bitcoin Staking uses no registered contract list. It reads the active PoX contract’s state through Hiro’s /v2/pox, PoX cycles and burnchain rewards endpoints.

Pricing sources

  • Protocol TVL, borrowed, token breakdown, ecosystem totals: USD values as priced by DefiLlama. Bicora applies no price of its own and uses no on-chain price oracle.
  • Bitcoin Staking USD value: CoinGecko simple/price for STX (blockstack), one spot read per run. No averaging. If the read fails, stxPriceUsd and stackingTvlUsd are N/A for that run.
  • BTC reward figures are in BTC and are not converted to USD.
  • Dashboard price ticker (BTC, STX): fetched in the browser from CoinGecko, with Coinbase spot as fallback. Display only; not stored in the snapshot, not served by the API, not used in any score.

Timestamps & freshness

All timestamps are UTC. The pipeline runs every 6 hours; the API caches the snapshot in memory for 60 seconds; a dashboard pointed at the API revalidates every 5 minutes and falls back to the committed snapshot if the API is unreachable.

FieldMeaning
generatedAt / updated_atWhen the scoring run that built the snapshot finished computing (UTC). Every protocol, market and staking value in a response comes from that run.
tvl_history[].date, ecosystemTvlHistory[].dateUTC calendar day (YYYY-MM-DD) of a DefiLlama daily point. When DefiLlama reports several points for one day, the latest wins.
tvl_fetched_at (metrics.tvlFetchedAt)When Bicora’s indexer fetched the protocol’s DefiLlama figures. N/A on snapshots written before this field existed.
tvl_as_of (metrics.tvlAsOf)Time of DefiLlama’s latest Stacks data point in that response; TVL and borrowed come from the same response. N/A when unknown.
liquidity_usd (current)DefiLlama current value at fetch time, which can be more recent than the last daily point. The final ecosystem series point is replaced with the sum of current values so the chart ends on the headline figure.
score_history[].date, score.computedAtDay and time of the scoring run. One point per protocol per day; a later run on the same day replaces it.
events[].tsTime of the scoring run that detected the event.
contracts[].deployedAtBitcoin block time of the deploy transaction.
Activity windowsMeasured on transaction Bitcoin block time: the 7 days before the indexer run, and the 7 days before that.
staking.fetchedAtPipeline run time (see the staking field table for the carried-forward case).
staking.nextCycleEtaAn estimate, not an observed time.

TVL, supplied, borrowed, withdrawable

Four different measures. The dashboard shows them separately and never adds one to another.

MeasureFieldDefinitionStatus
TVL · DefiLlamaliquidity_usdValue of assets held in the contracts the DefiLlama adapter reads, on the Stacks chain, excluding borrowed value. The only TVL that feeds the Liquidity score. Shown with its source and fetch time.Scored
Borrowed · DefiLlamaborrowed_usdOutstanding loans as reported by the adapter (lending protocols only). Not part of TVL.Context; utilisation input
Gross supplied · estimate— (dashboard only)TVL + borrowed. Derived from the two DefiLlama inputs above, from the same response; not an official protocol figure. It can include collateral that is not lendable and miss what the adapter does not read.Estimate
Withdrawable now—Assets that could be withdrawn immediately (idle lending liquidity, unlocked STX). No source Bicora reads reports this, so it is N/A. TVL is not all immediately withdrawable: collateral backing loans and STX locked in a reward cycle are in TVL.N/A
Official reported total—A protocol’s own headline figure. Shown separately only when a reliable, timestamped source with stated product coverage is available. None is today.N/A

utilization = borrowed ÷ (TVL + borrowed) uses the same estimated denominator; see findings.

Protocol TVL coverage

What the DefiLlama adapter behind each protocol’s TVL reads, checked against the adapter source. Protocols not listed (ALEX, Bitflow, Granite) have not been reviewed: their coverage is partial / unverified.

StackingDAO · reviewed 2026-10-08 · DefiLlama-Adapters · projects/stackingdao/api.js ↗

  • Counts: STX backing stSTX and stSTXbtc: reserve-v1 and stx-reserve-v2, get-total-stx; sBTC backing stBTC: stbtc-reserve, get-total-sbtc.
  • Leaves out: Receipt tokens themselves (stSTX, stSTXbtc, stBTC): only their backing is counted, so nothing is counted twice inside StackingDAO; Any STX not held in those reserves, such as native-staking STX that stays in users’ own accounts (inferred from the adapter reading only the reserves; amount not measured).
  • Withdrawable now: N/A. Reserve STX can be stacked and locked until its reward cycle ends, and DefiLlama does not report the idle share. TVL is not immediately withdrawable.
  • Official total: N/A. StackingDAO’s own dashboard reports a higher total, but Bicora has no timestamped, machine-readable source for it, so it is not shown.
  • verifiedCoverage: DefiLlama reads only the three reserves, so STX held outside them (for example native staking) is not in this TVL.
  • unresolvedStackingDAO’s own dashboard was reported at about $101M across stBTC, stSTX, stSTXbtc and native staking, against $83.0M here (2026-10-08 13:45 UTC). That figure, its timestamp and its prices could not be checked from Bicora, so the gap (about $18M) and how much native staking explains it are not established.
  • verifiedOn 2026-10-07 the sBTC in the stBTC reserve rose by about $27M while Zest’s sBTC fell and its stBTC and borrowed value rose by similar amounts (DefiLlama token data). This matches Zest’s stBTC strategy vault, which borrows sBTC to mint stBTC; the attribution is inferred, not traced on-chain.

Zest Protocol · reviewed 2026-10-08 · DefiLlama-Adapters · projects/zest-v2/api.js ↗

  • Counts: Token balances held by the seven Zest v2 vaults (STX, sBTC, stBTC, stSTX, stSTXbtc, USDCx, USDh); sBTC posted as collateral in v0-market-vault; stBTC held by the stBTC strategy vault (zv-state-stbtc-0).
  • Leaves out: Other collateral in v0-market-vault: only its sBTC is read; Strategy vault balances in zv-ops-stbtc-0; Interest accrued but not yet repaid; The legacy Zest deployment (a separate DefiLlama listing, not tracked by Bicora).
  • Borrowed: Per vault, get-assets − get-available-assets: principal lent out, excluding accrued interest. From the same DefiLlama response and day as TVL.
  • Gross supplied: TVL + borrowed also counts collateral that is not lendable (sBTC in the market vault, strategy stBTC) and leaves out accrued interest and collateral the adapter does not read. It is an estimate from DefiLlama inputs, not Zest’s official total supplied.
  • Withdrawable now: N/A. Only the vaults’ idle balances can be withdrawn by suppliers, but DefiLlama reports TVL by token, not by holder, so Bicora cannot separate them from collateral. Collateral backing open loans is not withdrawable.
  • Official total: N/A. No reliable timestamped total from Zest is available to Bicora.
  • verifiedstBTC in Zest (about $51M on 2026-10-08) is a StackingDAO receipt token whose sBTC backing is also in StackingDAO’s TVL; The headline tracked-TVL sum counts it in both protocols; Bicora’s secondary overlap-adjusted estimate subtracts it.
  • verifiedBorrowed rose from about $16M to $43M on 2026-10-07 (DefiLlama). The matching token moves fit the stBTC strategy vault borrowing sBTC to mint stBTC; that attribution is inferred, not traced on-chain.

Double counting

  • Borrowed value. liquidity_usd excludes borrowed value; borrowed_usd is reported separately and never added to TVL or to ecosystem totals. Gross supplied (TVL + borrowed) is an estimate, see definitions.
  • Headline: tracked protocol TVL, unadjusted. The dashboard headline, market-health.liquidity_usd, its 7d / 30d changes and the 90-day chart are all the same series: the plain sum of each tracked protocol’s DefiLlama Stacks TVL, with no overlap adjustment.
  • Receipt tokens across protocols. stSTX, stSTXbtc and stBTC are StackingDAO receipt tokens whose backing (STX, sBTC) is already in StackingDAO’s TVL. When another tracked protocol holds them (Zest vaults, Bitflow and ALEX pools), its DefiLlama TVL counts them again, so the headline sum includes them twice.
  • Bicora overlap-adjusted estimate (secondary). bicora_overlap_adjusted_estimate_usd = sum − mapped_receipt_token_overlap_usd, shown as a secondary detail and attributed to Bicora. On 2026-10-08 13:45 UTC: $170.6M − $58.3M = $112.3M, almost all stBTC in Zest. It covers only the mapped StackingDAO receipt tokens listed in mapped_receipt_tokens, valued at the holder’s DefiLlama price and capped at StackingDAO’s TVL. Other overlaps are not looked for (unmapped receipt tokens such as other liquid-staking tokens, LP tokens, wrapped or bridged assets), so a token breakdown being present for every protocol is not proof of complete de-duplication. Protocols without a breakdown are listed in receiptOverlap.missingBreakdowns.
  • Bitcoin Staking vs DeFi TVL. stackingTvlUsd is never added to the ecosystem total, the Risk Index or any protocol figure. PoX stacking is not a DefiLlama protocol, so it is outside the DeFi figures except for STX stacked through liquid-staking protocols, which is counted both in that protocol’s DeFi TVL and in total STX stacked.
  • Liquid-stacked overlap. liquidStackedUsd shows that overlap so it can be subtracted rather than summed. It is the STX row of tracked Liquid Stacking protocols (StackingDAO) in their DefiLlama token breakdown. Until 2026-10-08 it used StackingDAO’s whole TVL, which also included the sBTC behind stBTC (about $53M) and overstated the overlap; corrected. Untracked liquid-staking protocols such as LISA are not included.
  • Chain-wide TVL. The “Stacks TVL” on stacks.co combines stacked STX, BTC on Stacks and DeFi. It is a different figure from both the ecosystem total and stackingTvlUsd and is not reproduced by Bicora.

N/A, partial, estimated, stale

N/A

The value is null in the API and shown as N/A on the dashboard. It means there is no authoritative public source, the source failed this run, or the input does not apply. N/A is never reported as zero. Examples: staking.btcBonded (always), borrowed_usd and utilization when the DefiLlama adapter reports no borrowing, collateral_health for protocols without collateralised borrowing (its weight is redistributed per the methodology), score_delta_7d until 7 days of history exist, and TVL changes when no earlier point exists.

Known exceptions: if the DefiLlama request fails for a protocol, the indexer records its TVL as 0 and adds a llama: warning (effects listed below). If activity fetching fails, counts are 0 with an activity: warning, which also lowers the Activity score. These warnings are in protocols[].dataQuality.warnings on /v1/snapshot and on the protocol page only. Check them before treating a 0 as real.

Partial

The value covers less than its intended scope. There is no single partial flag; it shows up as:

  • Activity windows that cover fewer than 7 days because the 1,200-transactions-per-contract cap was reached (metrics.activitySampled, and the factor note “Sampled: x of 7 days covered”).
  • No prior 7-day window when the previous week was not covered, so the week-over-week trend is N/A.
  • Registered contracts not found on Hiro (contracts[].found: false plus a warning), which are left out of activity.
  • A staking block with source: 'live' where some fields are null because one source (price, rewards or cycles) failed while /v2/pox succeeded.
  • Coverage limited by design: five tracked protocols in ecosystem totals, the last 16 reward cycles in staking history, StackingDAO only in liquidStackedUsd.

Estimated

The value is an approximation, not a direct measurement:

  • When activity is sampled, the Activity factors scale counts by 7 ÷ days covered. The raw tx_7d and unique_senders_7d values are not scaled.
  • btcRewardPerBlockAvg and btcYieldPerCycleEst (from a 250-record sample of recent rewards).
  • nextCycleEta (assumes 10-minute Bitcoin blocks).
  • liquidStackedUsd as a measure of overlap (see above).
  • liquidityScoreHistory (/v1/snapshot), back-filled by applying the liquidity factors to past TVL history rather than recorded at the time.

Stale

The value is older than the latest pipeline run:

  • staking.source: 'carried-forward'. /v2/pox failed, so the previous run’s staking block was reused unchanged. fetchedAt then shows the carrying run, and the original observation time is not recorded, so a block carried across several runs can be older than it looks. If there is no earlier block, all live staking fields are N/A and the notes say the fetch failed.
  • Cited static values (targetBtcApy, cumulativeBtcDistributed as of 2026-09, bondPeriodBlocks) are constants that change only when the code is updated.
  • Protocol data has no stale flag. Compare updated_at with the current time: anything older than about 6 hours means a scheduled run was missed. DefiLlama daily points can also lag the current TVL value.

When a DefiLlama fetch fails

Current behaviour, documented as-is. When the DefiLlama request for a protocol still fails after retries, the indexer stores TVL 0, borrowed null, an empty history and no token breakdown, and the run continues. Scoring treats that 0 as a real value. The table lists what this changes. As of 2026-10-06 no such failure appears in the committed score history. A correction is under review; scoring behaviour and the methodology are unchanged until it is approved.

AreaOutputEffectPersists
ScoresLiquidity HealthScores 0. The depth factor maps $0 to 0; trend, drawdown and volatility have no history and are excluded.This run
ScoresCollateral HealthN/A for lending protocols that report borrowing (Zest): borrowed value is null, so the component is dropped and its weight redistributed. Utilisation is N/A.This run
Scoresoverall_score, band, effective_weightsRecomputed with Liquidity at 0. Applied to the 2026-10-06 snapshot this would move Zest from 72 (Moderate) to 34 (High) and StackingDAO from 73 to 45 (Elevated).This run
ScoresProtocol Activity, Security & TransparencyUnaffected (Hiro data).—
Historiesscore_historyThe day records the lowered overall score and Liquidity 0. A later successful run on the same UTC day replaces it; if the failed run is the last of the day, the point is kept.Can be permanent
HistoriesRisk Index historyThat day’s index point averages in the lowered score, under the same same-day rule. Later index change7d / change30d and score_delta_7d can compare against it.Can be permanent
Historiestvl_history, liquidityScoreHistoryEmpty for the protocol in that snapshot. Rebuilt from DefiLlama on the next successful run.This run
Totalsmarket-health liquidity_usdOmits the protocol’s TVL (for Zest, about $79M of $147M on 2026-10-06).This run
Totalsmarket-health tvl_historyThe protocol is missing from every day of the 90-day series, not only today. liquidity_change_7d / 30d are computed over the remaining protocols, so they do not show the gap.This run
Totalsavg_risk_score, Risk Index, band_distributionLowered and shifted by the protocol’s lowered score (one protocol is a fifth of the average).This run (index history as above)
Totalsstaking.liquidStackedUsdN/A when the failed protocol is StackingDAO (a 0 sum is reported as null).This run
Totalsactive_addresses_7d, transactions_7dUnaffected.—
Alertsscore eventsA drop of 3+ points against the previous day fires a watch event, 8+ an alert. If the bad history point is kept, the next day’s recovery fires an “up” event too.Permanent (event log)
Alertsliquidity eventsNot fired: with no history there is nothing to compare against, so the zero itself raises no TVL alert.—
Alertscollateral eventsSuppressed for the run because utilisation is N/A, so a real 80% / 90% crossing would be missed.This run
VisibilitywarningsA llama: warning appears in dataQuality.warnings on /v1/snapshot and on the protocol page. /v1/protocol-risk and /v1/market-health return the figures with no warning.—

Bitcoin Staking (informational)

Informational · not in Risk Index

The Bitcoin Staking (Stacks Proof of Transfer) tracker is outside the Bicora Risk Index. It is not in the protocols array, has no score, band or component, generates no risk events, and is not part of market-health, the ecosystem TVL or the average risk score. It is available only as staking on /v1/snapshot and on the dashboard’s Bitcoin Staking page. The methodology, scoring inputs, weights and thresholds are unchanged by it.

PoX STX committed vs BTC bonded

  • STX committed (stackedStx): STX locked in Proof of Transfer for the current reward cycle, read live from on-chain PoX state. This is what stackingTvlUsd values.
  • BTC bonded (btcBonded): BTC locked by participants in the native Bitcoin Staking program. That BTC sits in individual Bitcoin L1 timelocks under the holders’ own keys, and there is no public aggregate source, so the field is always N/A. Bicora does not estimate it. BTC bonded is not part of stackingTvlUsd.

Target APY vs realized rewards

  • Target APY (targetBtcApy, ~3%): the published target for the native Bitcoin Staking program, cited from stacks.co. It is a constant, not a measurement and not a guarantee, and it does not describe classic PoX stacking yield.
  • Realized rewards (btcRewardPerBlockAvg, btcYieldPerCycleEst): BTC actually paid to PoX recipients, estimated from recent on-chain reward records. They are total BTC amounts across all stackers, not a per-holder rate. Bicora does not compute a realized APY.
  • cumulativeBtcDistributed is a cited stacks.co total, not summed by Bicora.

Fields

FieldTypeDefinitionStatus
source'live' | 'carried-forward'Whether this run fetched PoX state, or copied the previous block because /v2/pox failed.See Stale
fetchedAtISO 8601Time of the pipeline run that produced the block. On a carried-forward block this is the carrying run, not when the values were observed.Run time
stackedStxnumber | nullSTX committed to Proof of Transfer for the current reward cycle (/v2/pox current_cycle.stacked_ustx ÷ 10^6).Live
totalStxSupplynumber | nullLiquid STX supply (/v2/pox total_liquid_supply_ustx ÷ 10^6).Live
pctSupplyStackednumber | nullstackedStx ÷ totalStxSupply (0–1).Derived
stxPriceUsdnumber | nullCoinGecko STX/USD spot at run time.Live
stackingTvlUsd, stackedUsdnumber | nullstackedStx × stxPriceUsd. The two fields hold the same value. Null when the price is unavailable.Derived
currentCyclenumber | nullCurrent PoX reward cycle number.Live
cycleLengthBlocksnumber | nullReward phase + prepare phase length, in Bitcoin blocks.Live
blocksUntilNextCyclenumber | nullBitcoin blocks until the next reward phase.Live
nextCycleEtaISO 8601 | nullRun time + blocksUntilNextCycle × 10 minutes.Estimated
minThresholdStxnumber | nullMinimum STX to stack solo this cycle.Live
totalSignersnumber | nullSigners for the current cycle, from the cycles endpoint.Live
btcRewardPerBlockAvgnumber | nullAverage BTC paid to all PoX recipients per rewarded Bitcoin block, over the latest 250 canonical reward records.Estimated
btcYieldPerCycleEstnumber | nullbtcRewardPerBlockAvg × reward-phase length: total BTC paid to all stackers per cycle. An amount of BTC, not a rate.Estimated
targetBtcApynumberPublished ~3% target for the native Bitcoin Staking program (0.03). Constant in code, not measured.Cited (static)
cumulativeBtcDistributednumberPublished BTC paid out via PoX since 2021, as read from stacks.co in 2026-09. Constant in code.Cited (static)
btcBondednullBTC bonded in the native Bitcoin Staking program. Always null.N/A
bondPeriodBlocksnumberBitcoin Staking bond period, 25,200 Bitcoin blocks (~6 months), per the whitepaper.Cited (static)
programStatusstringProgram status label, fixed in code.Cited (static)
liquidStackedUsdnumber | nullSTX held by tracked Liquid Stacking protocols (StackingDAO’s STX row in its DefiLlama token breakdown): the part of the DeFi figures that is also in stackedStx. Its sBTC is excluded. Null when no STX row is reported.Derived
history[]{ cycle, stackedStx, signers }[]Up to the last 16 reward cycles, ascending. From the cycles endpoint, so the latest entry can differ slightly from stackedStx.Live
sources[], notes[]object[], string[]Source links and plain-language caveats written by the pipeline for this run.—

Findings affecting scores (reported, not applied)

Found during the 2026-10-08 TVL review. Scoring inputs, weights, thresholds and the methodology are unchanged; each correction below is a proposal for separate review.

  • Zest activity is measured on the legacy deployment. config/protocols.json registers Zest’s older contracts (SP2VCQJ…), while DefiLlama’s zest-v2 TVL and borrowed come from the v2 deployment (SP1A27KFY… vaults and market). On 2026-10-08 the registered contracts showed 39 transactions in 7 days, and two of them have 1 and 2 lifetime transactions. Zest’s Protocol Activity (28.2) and the contract-age and source factors therefore describe a deployment that is not the one its TVL measures. Proposed: register the v2 market entry point and vaults; this changes Activity and Transparency inputs and needs review.
  • Zest utilisation denominator includes collateral that is not lendable. TVL + borrowed includes sBTC posted in the market vault and strategy-vault stBTC, so borrowed ÷ (TVL + borrowed) understates vault utilisation and can overstate Collateral Health. The size is not measured. Proposed: compute utilisation per vault from on-chain reads (see the TVL mapping branch) before using it in scoring.
  • Looped capital raises StackingDAO’s TVL and Liquidity score. About $27M of the jump on 2026-10-07 matches sBTC borrowed from Zest and minted into stBTC. Per-protocol TVL counts it correctly as StackingDAO deposits, but it is leveraged, recursive liquidity (30-day trend +135%, trend factor 100). Proposed: decide in the methodology review whether receipt-token loops should be discounted in Liquidity Health.
  • Historical StackingDAO points. DefiLlama stored StackingDAO at about 1% of actual from 2026-08-09 to 09-07 (DefiLlama-Adapters issue #20960). Bicora’s outlier rule already excludes those points (32 excluded); no change needed.

Data definitions

  • liquidity_usd — TVL · DefiLlama: value locked on Stacks per DefiLlama, excluding borrowed value. Not all of it is immediately withdrawable.
  • tvl_source / tvl_fetched_at / tvl_as_of — source of the TVL figures (always DefiLlama), when Bicora fetched them, and DefiLlama’s latest data-point time. The two times are null on snapshots written before 2026-10-08.
  • borrowed_usd / utilization — outstanding borrows and borrowed ÷ (liquidity + borrowed), where the denominator is the estimated gross supplied; lending protocols only, null when the adapter reports no borrowing.
  • bicora_overlap_adjusted_estimate_usd / mapped_receipt_token_overlap_usd / mapped_receipt_tokens (/v1/market-health) — Bicora’s secondary estimate: the summed TVL minus the mapped StackingDAO receipt tokens held by other tracked protocols, that overlap, and the token symbols it covers. Not a complete de-duplication. Null when no token breakdown is available.
  • tx_7d / unique_senders_7d — confirmed transactions on the registered contracts in the last 7 days and the distinct sender principals. Raw counts over the covered period; see sampled activity.
  • score_delta_7d — overall score minus the score recorded 7 days earlier (null until history exists).
  • components[].factors[] — the exact inputs behind each component score: label, observed value, mapped 0–100 score and weight within the component.
  • effective_weights — the weights actually applied after redistributing non-applicable components.
  • dataQuality (/v1/snapshot only) — excluded TVL outlier points with a note, whether activity was sampled, and fetch warnings.
  • staking (/v1/snapshot only) — informational Bitcoin Staking block; see Bitcoin Staking.

Integration example

const res = await fetch(`${API}/v1/protocol-risk?protocol=stackingdao`);
const { protocols: [p] } = await res.json();

if (p.band === 'High' || p.band === 'Elevated') {
  showWarning(`${p.name}: risk score ${p.overall_score} (${p.band})`);
}

Source, methodology and the protocol registry live in the public repository at github.com/zkzora/Bicora. Contributions that add a protocol must cite public sources for every transparency field.

Planned

Not implemented. None of these exist in the API or the pipeline today.

  • Planned Bicora-calculated protocol TVL from on-chain balances, as a parallel comparison to DefiLlama (not a scoring input).
  • Planned Hosted public API at api.bicora.xyz, with API keys and rate limits.
  • Planned Alert delivery by webhook and Telegram.
  • Planned Protocol-level and wallet-level exposure metrics.