api

Public Zexplorer API

Every response carries a normalised freshness envelope plus the live capability set. Errors follow RFC 7807 with a stable machine-readable error_code. Routes that depend on a derive consumer are capability-gated; absent capabilities return 503 capability_unavailable rather than guessing a response.

The {network} path segment is one of mainnet, testnet, or regtest (whichever the deploy serves). It is required on every per-network endpoint; there is no fallback. Process-level endpoints (/api/v1/healthz, /api/v1/openapi.json, /api/v1/stream) omit the segment.

openapi.json/testnet/status/api/v1/testnet/network

Envelope shape

{
  "data": { /* endpoint-specific payload */ },
  "freshness": {
    "network": "mainnet" | "testnet" | "regtest",
    "tip_height": 12345,
    "tip_hash": "00...",
    "derive_lag_blocks": 0,
    "capability_version": "explorer.block.summary_v1",
    "fetched_at_millis": 1750000000000
  },
  "capabilities": ["explorer.server_info_v1", "explorer.transaction.detail_v1", ...]
}

The envelope is mirrored on response headers (X-Network, X-Tip-Height, X-Capability, X-Capabilities) so agents can branch on freshness without parsing the JSON body. X-Network always matches the {network} segment in the request URL.

Endpoints

  • GET
    /api/v1/{network}/networkNetwork identity, tip height, freshness, and capability set
  • GET
    /api/v1/{network}/search?q=...Typed search across blocks, transactions, and address candidates. Shielded inputs always return private_by_design
    explorer.search_v1
  • GET
    /api/v1/{network}/blocks?limit=20Recent block summaries with ZIP-317 fee floor, sizes, and counts
    explorer.block.summary_v1
  • GET
    /api/v1/{network}/blocks/{height_or_hash}Block detail including transaction ids, reorg context, and coinbase reward
    explorer.block.detail_v1
  • GET
    /api/v1/{network}/transactions/{transaction_id}Public facts: status, privacy shape, component counts, ZIP-317 floor, paid fee (transparent only). Raw bytes are not part of any typed read.
    explorer.transaction.detail_v1
  • GET
    /api/v1/{network}/transactions/recent?limit=8Newest-first projection of recently mined transactions
    explorer.transaction.recent_v1
  • GET
    /api/v1/{network}/mempoolMempool snapshot: counts, total bytes, privacy distribution
    explorer.mempool.summary_v1
  • GET
    /api/v1/{network}/mempool/activity?limit=50Recent mempool entries with ZIP-317 floor and paid fee where safe
    explorer.mempool.activity_v1
  • GET
    /api/v1/{network}/mempool/events?window_seconds=300Rolling counts of added / mined / invalidated / suppressed events. Pair with /api/v1/stream for per-event delivery
    explorer.mempool.event_counts_v1
  • GET
    /api/v1/{network}/fees/summary?lookback=50Aggregated ZIP-317 conventional fee floors across recent blocks
    explorer.fee.summary_v1
  • GET
    /api/v1/{network}/value-poolsPer-pool totals (transparent, Sapling, Orchard, Sprout)
    explorer.value_pool.summary_v1
  • GET
    /api/v1/{network}/transparent-addresses/{address}Confirmed balance, mempool delta, and UTXOs for a transparent address
    explorer.transparent_address.balance_v1
  • GET
    /api/v1/{network}/transparent-addresses/{address}/activity?limit=50Newest-first confirmed activity rows with prevout resolution status
    explorer.transparent_address.activity_v1
  • POST
    /api/v1/{network}/broadcastBroadcasts a raw transaction. Body: { raw_transaction_hex, network }. Rate-limited 5/min/source
  • POST
    /api/v1/{network}/payment-disclosures/verifyVerifies a ZIP-311 payment disclosure. Body: { payment_disclosure_hex }. Disclosure payloads are never logged
    explorer.payment_disclosure.verify_v1
  • GET
    /api/v1/healthzProcess-level liveness probe. Lists every configured network and per-network upstream reachability
  • GET
    /api/v1/streamWebSocket multiplexer. Subscribe to topics (chain.committed_v1, mempool.added_v1/invalidated_v1/mined_v1/suppressed_v1/unknown_v1, capability.changed_v1) with a JSON envelope; each event carries its network in the envelope

Error model

Errors are application/problem+json (RFC 7807). Every response carries a stable error_code string drawn from the closed vocabulary documented in docs/reference/error-vocabulary.md. The HTTP status is derived from error_code via a single closed table (e.g. not_found → 404, capability_unavailable → 503, rate_limited → 429). Requesting a network not configured on this deploy returns network_not_configured → 400.

TypeScript example

const network = "mainnet"; // or "testnet" / "regtest"
const response = await fetch(
  `/api/v1/${network}/transactions/${transactionIdHex}`,
  { headers: { accept: "application/json" } }
);
if (!response.ok) {
  const problem = await response.json();
  // problem.error_code is one of the stable codes documented above
  throw new Error(problem.error_code);
}
const { data, freshness, capabilities } = await response.json();
// data.paid_fee_zat is null on any transaction with shielded inputs.
// data.status is one of: mined | pending | conflicting | invalidated |
// suppressed | not_found | unavailable.
zexplorer
  • API
  • Glossary
/
stale#3,272,731
/
  • API
  • Glossary