Zecnero

JSON API

Testnet

A public, read-only JSON API over the chain this explorer has indexed. Every answer is the explorer's own JSON, built from its index: nothing is passed through from the node, and no request reaches the node. Amounts are integers in nero (1 ZMR = 100,000,000 nero), with a _zat suffix; hashes are lowercase hex. The machine-readable description is /api/openapi.json (OpenAPI 3).

Rules

GET /api/v1/tip

curl https://explorer.zecnero.org/api/v1/tip

{
  "network": "testnet",
  "height": 7359,
  "hash": "…",
  "time": 1790828614,
  "upgrade": { "name": "Genesis", "branch_id": "01524d5a", "activation_height": 1 },
  "node_height": 7359,
  "node_seen_at": 1790828620
}

node_height is the node's own height at the indexer's last pass; when it is ahead of height, the explorer is catching up.

GET /api/v1/block/{height|hash}

curl https://explorer.zecnero.org/api/v1/block/822

{
  "height": 822,
  "hash": "…",
  "time": 1790290000,
  "size": 314,
  "difficulty": 1.0,
  "bits": "1e100000",
  "tx_count": 1,
  "subsidy_zat": 625000000,
  "fees_zat": 0,
  "miner": { "address": "nm…", "amount_zat": 606250000 },
  "founder": { "address": "n2…", "amount_zat": 18750000 },
  "upgrade": { "name": "Genesis", "branch_id": "01524d5a", "activation_height": 1 },
  "finalized": true,
  "previous_hash": "…",
  "next_hash": "…",
  "target": "0000100000…",
  "coinbase": { "subsidy_zat": 625000000, "miner": { … }, "fees_zat": 0, "founder": { … }, "founder_required_zat": 18750000 },
  "coinbase_outputs": [
    { "n": 0, "address": "nm…", "value_zat": 606250000, "role": "miner" },
    { "n": 1, "address": "n2…", "value_zat": 18750000, "role": "founder" }
  ],
  "txids": ["…"]
}

upgrade is the network upgrade the block was mined under (Genesis, NU1, NU2) with its consensus branch id; null for the genesis block. miner is the coinbase's first output that is not the founder stream's, with the total of all such outputs; its address is null when the miner was paid to a shielded address.

GET /api/v1/blocks/latest?limit=N

curl https://explorer.zecnero.org/api/v1/blocks/latest?limit=20

{ "tip_height": 7359, "blocks": [ { "height": 7359, … }, { "height": 7358, … }, … ] }

The newest limit blocks (1 to 100, default 10), highest first, each in the list form above (without previous_hash, next_hash, target, coinbase, coinbase_outputs and txids).

GET /api/v1/blocks?from=A&to=B&limit=N

curl "https://explorer.zecnero.org/api/v1/blocks?from=1000&to=2151&limit=100"

{ "from": 1000, "to": 2151, "blocks": [ { "height": 1000, … }, …, { "height": 1099, … } ], "next_from": 1100 }

Blocks from from to to inclusive, lowest first, limit (1 to 100, default 100) per page. Ask again with from=next_from until next_from is null. to defaults to from + limit − 1. A page whose blocks are all final is immutable.

GET /api/v1/tx/{txid}

curl https://explorer.zecnero.org/api/v1/tx/<64 hex digits>

{
  "txid": "…",
  "kind": "shielded",
  "version": 5,
  "block_height": 1210,
  "block_hash": "…",
  "block_time": 1790300000,
  "position": 1,
  "finalized": true,
  "size": 2377,
  "fee_zat": 10000,
  "transparent": { "input_count": 0, "output_count": 0, "inputs": null, "outputs": null, "value_out_zat": null },
  "shielded": {
    "sapling": { "spends": 1, "outputs": 2, "nullifier_count": 1, "anchors": ["…"], "value_balance_zat": 10000 },
    "orchard": { "actions": 0, "nullifier_count": 0, "anchor": null, "value_balance_zat": 0 }
  }
}

kind is coinbase, shielded (any use of Sapling or Orchard) or transparent. fee_zat is transparent in minus transparent out plus both value balances, all public; it is null for a coinbase, and where an input's value is not known. A value balance is the net value leaving its pool: positive when value leaves it, negative when value enters it. For coinbase and transparent transactions inputs and outputs are listed, and a coinbase's outputs carry a role of miner or founder.

GET /api/v1/supply

curl https://explorer.zecnero.org/api/v1/supply

{
  "height": 7359,
  "formula": "Subsidy(h) = floor(625000000 / 2^floor(h / HalvingInterval)) …",
  "halving_interval": 1680000,
  "max_block_subsidy_zat": 625000000,
  "cap_zat": 2099999356520000,
  "cap_zmr": "20999993.5652",
  "emitted_zat": 4599375000000,
  "emitted_zmr": "45993.75",
  "miner_emitted_zat": 4461393750000,
  "founder_emitted_zat": 137981250000,
  "founder_unspent_zat": 137981250000,
  "circulating_zat": 4461393750000,
  "circulating_zmr": "44613.9375",
  "emitted_percent": 0.219,
  "next_block_reward": { "height": 7360, "subsidy_zat": 625000000, "miner_zat": 606250000, "founder_zat": 18750000, "halving": 0 },
  "next_halving": { "height": 1680000, "blocks_remaining": 1672641, "estimated_time": 1916276689, "subsidy_after_zat": 312500000 },
  "subsidy_ends_at_height": 50400000,
  "founder_stream": { "numerator": 3, "denominator": 100, "end_height": 1680000, "active": true, "lifetime_total_zat": 31499981250000 },
  "node": { "height": 7359, "chain_supply_zat": 4599375000000, "transparent_pool_zat": …, "sapling_pool_zat": …, "orchard_pool_zat": …, "expected_supply_zat": 4599375000000, "matches_schedule": true }
}

The schedule as the node computes it: Subsidy(h) = floor(6.25 ZMR / 2^floor(h / 1,680,000)) from height 1, nothing at genesis, no slow start and no tail emission, reaching zero after 30 halvings; the founder stream is floor(Subsidy(h) × 3 / 100) below FSEnd = 1,680,000, the end of the first halving period, and the miner receives the rest plus fees. The cap is 20,999,993.5652 ZMR. estimated_time assumes 75-second blocks from the tip. node is the node's own chain supply and value-pool totals at the indexer's last pass, beside what the schedule says for the node's height.

founder_unspent_zat is the founder multisig's unspent balance at the tip: what the chain paid the founder address less what was spent from it. circulating_zat is emitted_zat less that balance, so coins the founder has spent count as circulating.

GET /api/v1/supply/total and /api/v1/supply/circulating

curl https://explorer.zecnero.org/api/v1/supply/total

45993.75000000

curl https://explorer.zecnero.org/api/v1/supply/circulating

44613.93750000

Two figures of /api/v1/supply as bare numbers of ZMR with eight decimal places, for supply trackers. Total mined is every coin issued up to the indexed tip, the miners' subsidy and the founder stream together (emitted_zat); the genesis block issues nothing. Circulating is total mined less the founder multisig's unspent balance (circulating_zat). Both are cached like the supply.

GET /api/v1/difficulty

curl https://explorer.zecnero.org/api/v1/difficulty

{
  "height": 7359,
  "difficulty": 265.29,
  "unit": "multiple of the minimum difficulty (PoWLimit)",
  "expected_hashes_per_block": 2173222.76,
  "tip_difficulty": 263.1,
  "tip_bits": "1e07c01c",
  "tip_target": "000007c01c00…",
  "target_spacing_seconds": 75,
  "method": "…",
  "hashrate": [
    { "window_blocks": 120, "counted_blocks": 120, "first_height": 7240, "last_height": 7359, "window_seconds": 8533, "hashes_per_second": 29916.3 },
    { "window_blocks": 288, … },
    { "window_blocks": 1152, … }
  ],
  "node_hashes_per_second": 29916.0
}

Each estimate is the window's work (each block's expected hashes, 2256 / (target + 1)) over the time from the earliest to the latest header among the window and the block before it: the node's own getnetworksolps calculation. The windows are 120 blocks (the node's default), 288 (six hours) and 1,152 (one day). Hashrate swings with luck over short windows; the longer ones are steadier.

GET /api/v1/difficulty/history?from=&to=&step=&window=

curl "https://explorer.zecnero.org/api/v1/difficulty/history?step=144&window=288"

{ "from": 0, "to": 7359, "step": 144, "window_blocks": 288,
  "points": [ { "height": 63, "time": …, "difficulty": 1.0, "bits": "…", "hashes_per_second": …, "counted_blocks": 63 }, … ] }

A point every step blocks (default 12) from from to to (default: the last 96 points to the tip), each with the block's difficulty and the hashrate over the window blocks ending at it (default 120, at most 16,128). At most 1,000 points.

GET /api/v1/founder-stream?from=&to=&group=&interval=

curl "https://explorer.zecnero.org/api/v1/founder-stream?group=day"

{
  "address": "n2…",
  "script_pub_key": "a914…87",
  "script_type": "p2sh",
  "rule": { "numerator": 3, "denominator": 100, "end_height": 1680000, "active": true, "lifetime_total_zat": 31499981250000 },
  "from": 0, "to": 7359, "group": "day",
  "total": { "first_height": 0, "last_height": 7359, "blocks": 7360, "paying_blocks": 7359, "paid_zat": 137981250000, "required_zat": 137981250000 },
  "periods": [ { "day": "2026-09-23", "first_height": 0, …, "paid_zat": …, "required_zat": … }, … ]
}

What the coinbases paid the founder stream's address, against what the rule requires of the same heights. group is total (the default, one period), blocks (periods of interval blocks, default 1,152) or day (UTC days of the block time). At most 1,000 periods. The range is at most 100000 blocks; without from it is the last 100000 blocks to to, or the whole chain while it is shorter.

GET /api/v1/upgrades

curl https://explorer.zecnero.org/api/v1/upgrades

{
  "height": 7359,
  "current": { "name": "Genesis", "branch_id": "01524d5a", "activation_height": 1 },
  "next_block": { "name": "Genesis", … },
  "node_consensus": { "height": 7359, "chaintip": "01524d5a", "nextblock": "01524d5a" },
  "upgrades": [
    { "name": "Genesis", "branch_id": "01524d5a", "activation_height": 1, "status": "active", "blocks_remaining": null, "estimated_time": null, "node_name": "NU6" },
    { "name": "NU1", "branch_id": "02524d5a", "activation_height": 13982, "status": "pending", "blocks_remaining": 6623, "estimated_time": 1791325339, "node_name": "NU6.2" }
  ]
}

Zecnero's network upgrades as the node reports them, by branch id: Genesis (01524d5a, which takes in Overwinter to NU6), NU1 (02524d5a) and, on a node configured with it, NU2 (03524d5a). node_name is the node's upstream name for each. A pending upgrade's estimated_time assumes 75-second blocks.

GET /api/v1/pool-share?windows=288,1152&address=

curl "https://explorer.zecnero.org/api/v1/pool-share?windows=288,1152"

{
  "tip_height": 7359,
  "windows": [
    { "window_blocks": 288, "first_height": 7072, "last_height": 7359, "counted_blocks": 288,
      "miners": [ { "address": "nm…", "blocks": 136, "share": 0.472222 }, … ] },
    { "window_blocks": 1152, … }
  ]
}

How many of the last N blocks each coinbase miner address found, most first. windows lists one to five window lengths (default 288,1152); each may be up to 100000 blocks, so the share of the last 1,152 blocks, the measure of the pool-dominance policy, comes from the chain with no 500-block cap. With address, each window lists only that address (with 0 blocks if it found none). A coinbase that pays its miner a shielded address counts under "address": null.

GET /api/v1/address/{address}/mined

The same answer as /api/address/{address}/mined, below.

Unversioned endpoints

The first endpoints, kept working with the same answers. New code should use version 1.

GET /api/stats

The indexed tip, the hashrate over the last 120 blocks (with the window it was worked out over), the next block's difficulty and the hashes it takes, the supply mined so far against the total the schedule will ever issue, and the founder stream rule.

curl https://explorer.zecnero.org/api/stats

{
  "network": "testnet",
  "height": 1200,
  "tip_hash": "…",
  "tip_time": 1790300000,
  "hashrate": {
    "hashes_per_second": 1234.5,
    "window_blocks": 120,
    "first_height": 1081,
    "last_height": 1200,
    "window_seconds": 9000
  },
  "difficulty": {
    "value": 1.0,
    "unit": "multiple of the minimum difficulty (PoWLimit)",
    "expected_hashes_per_block": 1048576.0,
    "tip_bits": "1e100000",
    "tip_target": "0000100000000000000000000000000000000000000000000000000000000000"
  },
  "supply": {
    "mined_zat": 750000000000,
    "total_zat": 2099999356520000,
    "mined_zmr": "7500",
    "total_zmr": "20999993.5652",
    "mined_percent": 0.036,
    "halving_interval": 1680000
  },
  "founder_stream": { "percent_of_subsidy": 3, "end_height": 1680000 }
}

hashrate is null until there are two blocks with different times. Difficulty is how much harder a block is to find than at the network's easiest target, so it is a pure multiple; expected_hashes_per_block is what it means in RandomX hashes.

GET /api/block/{height|hash}

curl https://explorer.zecnero.org/api/block/822
curl https://explorer.zecnero.org/api/block/<64 hex digits>

{
  "height": 822,
  "hash": "…",
  "previous_hash": "…",
  "time": 1790290000,
  "size": 314,
  "difficulty": 1.0,
  "bits": "1e100000",
  "target": "0000100000…",
  "confirmations": 379,
  "coinbase": {
    "subsidy_zat": 625000000,
    "miner": { "address": "nm…", "amount_zat": 606250000 },
    "fees_zat": 0,
    "founder": { "address": "n2…", "amount_zat": 18750000 },
    "founder_required_zat": 18750000
  },
  "txids": ["…"]
}

founder is null where the block pays no founder stream (genesis, and from height 1,680,000 on Mainnet and Testnet). The founder stream is floor(subsidy × 3 / 100); the miner receives the rest of the subsidy plus the block's fees.

GET /api/tx/{txid}

curl https://explorer.zecnero.org/api/tx/<64 hex digits>

{
  "txid": "…",
  "kind": "transparent",
  "block_height": 822,
  "block_hash": "…",
  "time": 1790290000,
  "confirmations": 379,
  "size": 288,
  "fee_zat": 10000,
  "transparent_input_count": 1,
  "transparent_output_count": 2,
  "transparent_inputs": [{ "n": 0, "address": "nm…", "value_zat": 606250000 }],
  "transparent_outputs": [{ "n": 0, "address": "nm…", "value_zat": 500000000 }, …],
  "transparent_value_out_zat": 606240000,
  "sapling_spends": 0,
  "sapling_outputs": 0,
  "orchard_actions": 0
}

kind is coinbase, shielded or transparent. A coinbase's outputs carry a role of miner or founder. A shielded transaction has empty input and output lists, a null value and fee, and its counts.

GET /api/address/{address}/mined

curl https://explorer.zecnero.org/api/address/<address>/mined

{
  "address": "nm…",
  "blocks": 42,
  "first_height": 17,
  "last_height": 1190
}

Whether a transparent address has been paid a block's miner reward: how many indexed blocks paid it the miner's share of the coinbase, and the lowest and highest of them. The founder stream is not counted. An address that never mined is 200 with blocks 0 and null heights, not 404. The address must be 26 to 40 Base58 characters; its checksum is not checked, so a mistyped address reads as one that never mined.

GET /api/nodes-map

curl https://explorer.zecnero.org/api/nodes-map

{
  "generated_at": 1790452800,
  "window_hours": 24,
  "total_nodes": 60,
  "countries": [{ "code": "DE", "name": "Germany", "count": 9, "lat": 50.96, "lon": 9.68 }, …],
  "regions": [{ "name": "Europe", "count": 6 }, { "name": "Elsewhere", "count": 2 }],
  "seeds": [{ "name": "Seed 1 · Toronto, Canada", "country": "CA", "lat": 60.32, "lon": -101.91 }, …],
  "attribution": { "text": "IP geolocation by DB-IP", "url": "https://db-ip.com" }
}

Where the nodes the two seeds saw in the last 24 hours are, by country. total_nodes counts each node once across both seeds. A country appears in countries only with three nodes or more; the rest are counted in their region, and a region below three in Elsewhere. lat and lon are a fixed point for the country, never a node's location, and the seeds are not in any count. The snapshot is at least an hour old (generated_at) and changes at most hourly; generated_at is null until the first one is old enough. No address is kept or published. Browsers may read it from https://zecnero.org.