openapi: 3.0.3

info:
  title: Startmining API
  version: 1.0.0
  description: |
    Bitcoin mining live data sourced from a self-hosted Bitcoin Core full node.
    Free public REST API powering pro.startmining.io. All blockchain state comes
    from a self-hosted Bitcoin Core node — no third-party blockchain provider
    in the chain.

    **Authentication.** Free tier is anonymous — no API key required.
    Per-IP rate limit applies (see Rate limits below). Enterprise tier (custom
    rate limit, SLA, support) is available on request: contact@startmining.io.

    **Rate limits.** ~60 requests / minute / IP on Free tier. The widget embed
    surface (`/embed/*`, NOT documented here as an API) is rate-limited at
    60 req/min per (IP, embedding domain) pair.

    **Versioning.** Semver. Breaking changes bump the major version, get a
    6-month deprecation window, and are announced on https://pro.startmining.io/developers.

    **Data licence.** CC BY 4.0 — attribution required:
    `Startmining (https://pro.startmining.io)`.
  contact:
    email: contact@startmining.io
  license:
    name: CC BY 4.0
    url: https://creativecommons.org/licenses/by/4.0/

servers:
  - url: https://pro.startmining.io
    description: Production — Next.js app routes (this spec)
  - url: https://mining-api.startmining.io
    description: Internal upstream node — not part of this spec, key required

tags:
  - name: system
    description: Healthcheck and operational endpoints
  - name: market
    description: BTC price, hashprice, difficulty — aggregated views
  - name: network
    description: Bitcoin network state from a self-hosted Bitcoin Core node
  - name: mining
    description: Halving countdown, mempool, mining pools
  - name: asics
    description: ASIC hardware market prices

paths:
  /api/health:
    get:
      tags: [system]
      summary: Healthcheck
      description: Returns 200 with a static status payload when the simulator app is up.
      operationId: getHealth
      responses:
        '200':
          description: Service is up.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
              example:
                status: ok
                service: simulator-pro
                timestamp: '2026-04-30T20:38:28.882Z'

  /api/market-summary:
    get:
      tags: [market]
      summary: Aggregated market snapshot
      description: |
        The single endpoint most consumers want: BTC price, current hashprice,
        difficulty, network hashrate, last block height — everything for a profitability
        widget in one round-trip. Cached for 60 seconds (`s-maxage=60`).
      operationId: getMarketSummary
      responses:
        '200':
          description: Aggregated snapshot.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketSummary'
              example:
                btcPrice: 76439
                hashpriceUsd: 37.55
                difficulty: 135594876535256.6
                difficultyT: '135.59T'
                networkHashrateEH: 938
                blockReward: 3.125
                txFeesPercent: 2.4
                breakevenEfficiency75c: 0
                blockHeight: 947321
                updated: '2026-04-30T20:33:37.240Z'
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/market/price:
    get:
      tags: [market]
      summary: BTC price + hashprice (detailed)
      description: |
        Full market snapshot with provenance fields (which upstream provided each
        value). Includes 24h price change, hashprice in USD and BTC, transaction-fee
        share of the block reward, and effective reward.
      operationId: getMarketPrice
      responses:
        '200':
          description: Detailed market data.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketPrice'
              example:
                price: 76466
                change24h: 1.08
                hashpriceChange24h: 1.08
                difficulty: 135594876535256.6
                networkHashrateEH: 919.95
                hashpriceUsd: 35.75733823168562
                hashpriceBtc: 0.00046762401893240944
                blockReward: 3.125
                effectiveReward: 3.152
                txFeesPercent: 0.9
                avgTxFees: 0.027
                blockHeight: 947321
                source:
                  price: mining-api
                  difficulty: mining-api
                  txFees: mining-api
                  hashprice: calculated
                timestamp: '2026-04-30T20:37:26.445Z'
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/market/difficulty:
    get:
      tags: [market]
      summary: Current network difficulty
      description: Minimal endpoint returning only the live difficulty.
      operationId: getMarketDifficulty
      responses:
        '200':
          description: Current difficulty.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Difficulty'
              example:
                difficulty: 135594876535257
                source: blockchain.info
                timestamp: '2026-04-30T20:38:07.073Z'
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/stats:
    get:
      tags: [network]
      summary: Bitcoin Core full node stats
      description: |
        Chain state (height, size, verification progress), hashrate, difficulty epoch
        progress, transaction throughput, mempool size, recent block-time average.
        Direct passthrough of the upstream Bitcoin Core RPC, normalized.
      operationId: getNetworkStats
      responses:
        '200':
          description: Full node snapshot.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NetworkStats'
              example:
                timestamp: '2026-04-30T20:34:33.617Z'
                blockchain:
                  height: 947321
                  size_gb: 839.9
                  chain: main
                  pruned: false
                  verification_progress: 0.9999949582502852
                hashrate:
                  current_eh: 855.2
                  current_h: 8.552005482771601e+20
                difficulty:
                  current: 135594876535256.6
                  current_formatted: '135.59 T'
                  blocks_until_adjustment: 199
                  blocks_into_epoch: 1817
                transactions:
                  total: 1348575698
                  rate_per_second: 6.578
                  mempool_size: 12910
                blocks:
                  avg_time_seconds: 619
                  avg_time_7d_seconds: 619
                  avg_time_7d_formatted: '10m 19s'
                  target_time_seconds: 600
                  vs_target_pct: 3.21
                source: bitcoin_node
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/blocks:
    get:
      tags: [network]
      summary: Recent blocks with miner attribution
      description: |
        Returns the last 10 blocks with height, hash, timestamp, transaction count,
        size, weight, fees, and the identified mining pool when known.
      operationId: getNetworkBlocks
      responses:
        '200':
          description: Recent blocks.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RecentBlocks'
              example:
                timestamp: '2026-04-30T20:34:33.770Z'
                count: 10
                current_height: 947321
                blocks:
                  - height: 947321
                    hash: '0000000000000000000098f186675233ca1aecffd387ed190ac5886c084cb1de'
                    timestamp: '2026-04-30T20:17:18.000Z'
                    time_ago_seconds: 1035
                    transactions: 3887
                    size_bytes: 1603372
                    size_mb: 1.603
                    weight: 3993406
                    difficulty: 135594876535256.6
                    subsidy_btc: 3.125
                    fees_btc: 0.068
                    total_btc: 3.193
                    avg_fee_sat: 1740
                    avg_fee_rate: 6
                    pool:
                      name: Foundry USA
                      slug: foundry-usa
                      identified: true
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/mempool:
    get:
      tags: [mining]
      summary: Mempool size and fee buckets
      description: Current pending transactions, total fees, and recommended fee rates per priority bucket.
      operationId: getMempool
      responses:
        '200':
          description: Mempool snapshot.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Mempool'
              example:
                timestamp: '2026-04-30T20:34:33.662Z'
                mempool:
                  transactions: 12910
                  size_bytes: 9010630
                  size_mb: 9.01
                  total_fees_btc: 0.23515617
                  memory_usage_mb: 38.18
                fees:
                  fastest:
                    sat_per_vb: 7
                    target_blocks: 2
                    description: Next block
                  medium:
                    sat_per_vb: 5
                    target_blocks: 6
                    description: '~1 hour'
                  slow:
                    sat_per_vb: 1
                    target_blocks: 144
                    description: '~1 day'
                  minimum:
                    sat_per_vb: 1
                    description: Minimum relay fee
                source: bitcoin_node
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/pools:
    get:
      tags: [mining]
      summary: Mining pool distribution
      description: |
        Pool share over the last 144 blocks (~24h), with estimated hashrate per pool.
        Useful for centralization metrics and miner concentration tracking.
      operationId: getNetworkPools
      responses:
        '200':
          description: Pool distribution.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PoolDistribution'
              example:
                timestamp: '2026-04-30T20:34:34.380Z'
                blocks_analyzed: 144
                period_description: 'Last 144 blocks (~24 hours)'
                network_hashrate_eh: 855.2
                pools:
                  - name: Foundry USA
                    slug: foundry-usa
                    blocks: 44
                    percentage: 30.56
                    estimated_hashrate_eh: 261.35
                  - name: AntPool
                    slug: antpool
                    blocks: 19
                    percentage: 13.19
                    estimated_hashrate_eh: 112.8
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/halving:
    get:
      tags: [mining]
      summary: Halving countdown and history
      description: |
        Current halving era, next halving (target block, estimated date, blocks remaining,
        days remaining), total mined supply, and the full historical timeline since genesis.
      operationId: getHalving
      responses:
        '200':
          description: Halving state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Halving'
              example:
                current:
                  era: 5
                  block_reward: 3.125
                  started_block: 840000
                  started_date: '2024-04-20'
                next:
                  era: 6
                  block_reward: 1.5625
                  target_block: 1050000
                  blocks_remaining: 102679
                  days_remaining: 713
                  estimated_date: '2028-04-12'
                supply:
                  total_mined: 20022878.13
                  max_supply: 21000000
                  percent_mined: 95.35
                  remaining: 977121.88
                history:
                  - era: 1
                    block: 0
                    date: '2009-01-03'
                    reward: 50
                  - era: 2
                    block: 210000
                    date: '2012-11-28'
                    reward: 25
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/market:
    get:
      tags: [network]
      summary: Network + market merged snapshot
      description: |
        Combines BTC market data (price, volume, market cap, 24h change) with the live
        network state (difficulty, hashrate, block height, mempool) and mining payouts
        (hashprice in USD and BTC, effective block reward, fee share).
      operationId: getNetworkMarket
      responses:
        '200':
          description: Network + market merged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NetworkMarket'
              example:
                timestamp: '2026-04-30T20:34:33.689Z'
                btc:
                  price_usd: 76442
                  change_24h_pct: 1.09
                  market_cap_usd: 1530543074499.99
                  volume_24h_usd: 32859408466.31
                network:
                  difficulty: 135594876535256.6
                  difficulty_formatted: '135.59 T'
                  hashrate_eh: 919.95
                  block_height: 947321
                  blocks_until_adjustment: 199
                  block_time_sma_seconds: 633
                  block_time_sma_formatted: '10m 33s'
                mining:
                  hashprice_usd_ph_day: 35.74
                  hashprice_btc_ph_day: 0.000467607607543174
                  hashprice_change_24h_pct: 1.09
                  block_subsidy: 3.125
                  effective_reward: 3.152
                  tx_fees_avg_btc: 0.027
                  tx_fees_pct: 0.9
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/network/difficulty-estimate:
    get:
      tags: [network]
      summary: Next difficulty retarget estimate
      description: |
        Projects the difficulty value at the upcoming retarget (every 2016 blocks)
        based on the current epoch's average block time. Includes the previous adjustment
        for context and the estimated retarget date.
      operationId: getDifficultyEstimate
      responses:
        '200':
          description: Retarget projection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DifficultyEstimate'
              example:
                timestamp: '2026-04-30T20:34:25.242Z'
                current:
                  difficulty: 135594876535256.6
                  difficulty_formatted: '135.59 T'
                  height: 947321
                previous_adjustment:
                  change_percent: -2.43
                  date: '2026-04-17'
                  block_height: 945504
                  from_difficulty_formatted: '138.97 T'
                  to_difficulty_formatted: '135.59 T'
                next_adjustment:
                  estimated_difficulty: 130622429774946.53
                  estimated_difficulty_formatted: '130.62 T'
                  change_percent: -3.67
                  blocks_remaining: 199
                  estimated_date: '2026-05-02T07:00:10.455Z'
                  epoch_progress_percent: 90.13
                  epoch_avg_block_time_seconds: 623
                hashrate_eh: 855.2
                source: bitcoin_node
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

  /api/asic-prices:
    get:
      tags: [asics]
      summary: ASIC market prices (latest snapshot)
      description: |
        Current secondary-market prices for SHA-256 ASICs, indexed by `$/TH`.
        Updated periodically from manufacturer datasheets and aggregator scrapes.
        See `/asics` for the full catalogue with hashrate / efficiency / cooling.
      operationId: getAsicPrices
      responses:
        '200':
          description: Latest ASIC prices.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AsicPrices'
              example:
                generated_at: '2026-01-22T16:35:33.700778'
                total_models: 169
                latest_prices:
                  - model: S21 XP
                    hashrate: 270
                    price_per_th: 15
                    unit_price: 4050
                    efficiency_jt: null
                  - model: S23 Hydro
                    hashrate: 580
                    price_per_th: 17.2
                    unit_price: 9976
                    efficiency_jt: 9.5
        '429': { $ref: '#/components/responses/RateLimited' }
        '500': { $ref: '#/components/responses/InternalError' }

components:
  schemas:
    Health:
      type: object
      required: [status, service, timestamp]
      properties:
        status: { type: string, example: ok }
        service: { type: string, example: simulator-pro }
        timestamp: { type: string, format: date-time }

    MarketSummary:
      type: object
      required: [btcPrice, hashpriceUsd, difficulty, networkHashrateEH, blockHeight, updated]
      properties:
        btcPrice: { type: number, description: BTC price in USD }
        hashpriceUsd: { type: number, description: Daily revenue per PH/s in USD }
        difficulty: { type: number, description: Current network difficulty }
        difficultyT: { type: string, description: Difficulty formatted (e.g. "135.59T") }
        networkHashrateEH: { type: number, description: Network hashrate in EH/s }
        blockReward: { type: number, description: Current block subsidy in BTC }
        txFeesPercent: { type: number, description: Transaction fees as % of block reward }
        breakevenEfficiency75c: { type: number, description: Break-even J/TH at $0.075/kWh }
        blockHeight: { type: integer }
        updated: { type: string, format: date-time }

    MarketPrice:
      type: object
      required: [price, hashpriceUsd, difficulty, blockHeight, timestamp]
      properties:
        price: { type: number }
        change24h: { type: number, description: BTC price change over 24h, in percent }
        hashpriceChange24h: { type: number }
        difficulty: { type: number }
        networkHashrateEH: { type: number }
        hashpriceUsd: { type: number }
        hashpriceBtc: { type: number }
        blockReward: { type: number }
        effectiveReward: { type: number, description: Block reward + average fees }
        txFeesPercent: { type: number }
        avgTxFees: { type: number, description: Average fees per block in BTC }
        blockHeight: { type: integer }
        source:
          type: object
          additionalProperties: { type: string }
          example:
            price: mining-api
            difficulty: mining-api
            txFees: mining-api
            hashprice: calculated
        timestamp: { type: string, format: date-time }

    Difficulty:
      type: object
      required: [difficulty, source, timestamp]
      properties:
        difficulty: { type: integer, format: int64 }
        source: { type: string, example: blockchain.info }
        timestamp: { type: string, format: date-time }

    NetworkStats:
      type: object
      required: [timestamp, blockchain, hashrate, difficulty, transactions, blocks, source]
      properties:
        timestamp: { type: string, format: date-time }
        blockchain:
          type: object
          properties:
            height: { type: integer }
            size_gb: { type: number }
            chain: { type: string, example: main }
            pruned: { type: boolean }
            verification_progress: { type: number }
        hashrate:
          type: object
          properties:
            current_eh: { type: number }
            current_h: { type: number }
        difficulty:
          type: object
          properties:
            current: { type: number }
            current_formatted: { type: string }
            blocks_until_adjustment: { type: integer }
            blocks_into_epoch: { type: integer }
        transactions:
          type: object
          properties:
            total: { type: integer, format: int64 }
            rate_per_second: { type: number }
            mempool_size: { type: integer }
        blocks:
          type: object
          properties:
            avg_time_seconds: { type: integer }
            avg_time_7d_seconds: { type: integer }
            avg_time_7d_formatted: { type: string }
            target_time_seconds: { type: integer }
            vs_target_pct: { type: number }
        source: { type: string, example: bitcoin_node }

    Block:
      type: object
      required: [height, hash, timestamp, transactions, size_bytes]
      properties:
        height: { type: integer }
        hash: { type: string }
        timestamp: { type: string, format: date-time }
        time_ago_seconds: { type: integer }
        transactions: { type: integer }
        size_bytes: { type: integer }
        size_mb: { type: number }
        weight: { type: integer }
        difficulty: { type: number }
        subsidy_btc: { type: number }
        fees_btc: { type: number }
        total_btc: { type: number }
        avg_fee_sat: { type: integer }
        avg_fee_rate: { type: integer }
        pool:
          type: object
          properties:
            name: { type: string }
            slug: { type: string }
            identified: { type: boolean }

    RecentBlocks:
      type: object
      required: [timestamp, count, blocks]
      properties:
        timestamp: { type: string, format: date-time }
        count: { type: integer }
        current_height: { type: integer }
        blocks:
          type: array
          items: { $ref: '#/components/schemas/Block' }

    Mempool:
      type: object
      required: [timestamp, mempool, fees, source]
      properties:
        timestamp: { type: string, format: date-time }
        mempool:
          type: object
          properties:
            transactions: { type: integer }
            size_bytes: { type: integer }
            size_mb: { type: number }
            total_fees_btc: { type: number }
            memory_usage_mb: { type: number }
        fees:
          type: object
          properties:
            fastest: { $ref: '#/components/schemas/FeeBucket' }
            medium: { $ref: '#/components/schemas/FeeBucket' }
            slow: { $ref: '#/components/schemas/FeeBucket' }
            minimum: { $ref: '#/components/schemas/FeeBucket' }
        source: { type: string, example: bitcoin_node }

    FeeBucket:
      type: object
      required: [sat_per_vb]
      properties:
        sat_per_vb: { type: integer }
        target_blocks: { type: integer }
        description: { type: string }

    Pool:
      type: object
      required: [name, slug, blocks, percentage]
      properties:
        name: { type: string }
        slug: { type: string }
        blocks: { type: integer }
        percentage: { type: number }
        estimated_hashrate_eh: { type: number }

    PoolDistribution:
      type: object
      required: [timestamp, blocks_analyzed, network_hashrate_eh, pools]
      properties:
        timestamp: { type: string, format: date-time }
        blocks_analyzed: { type: integer }
        period_description: { type: string }
        network_hashrate_eh: { type: number }
        pools:
          type: array
          items: { $ref: '#/components/schemas/Pool' }

    Halving:
      type: object
      required: [current, next, supply, history]
      properties:
        current:
          type: object
          properties:
            era: { type: integer }
            block_reward: { type: number }
            started_block: { type: integer }
            started_date: { type: string, format: date }
        next:
          type: object
          properties:
            era: { type: integer }
            block_reward: { type: number }
            target_block: { type: integer }
            blocks_remaining: { type: integer }
            days_remaining: { type: integer }
            estimated_date: { type: string, format: date }
        supply:
          type: object
          properties:
            total_mined: { type: number }
            max_supply: { type: integer }
            percent_mined: { type: number }
            remaining: { type: number }
        history:
          type: array
          items:
            type: object
            properties:
              era: { type: integer }
              block: { type: integer }
              date: { type: string, format: date }
              reward: { type: number }
        block_height: { type: integer }

    NetworkMarket:
      type: object
      required: [timestamp, btc, network, mining]
      properties:
        timestamp: { type: string, format: date-time }
        btc:
          type: object
          properties:
            price_usd: { type: number }
            change_24h_pct: { type: number }
            market_cap_usd: { type: number }
            volume_24h_usd: { type: number }
        network:
          type: object
          properties:
            difficulty: { type: number }
            difficulty_formatted: { type: string }
            hashrate_eh: { type: number }
            block_height: { type: integer }
            blocks_until_adjustment: { type: integer }
            block_time_sma_seconds: { type: integer }
            block_time_sma_formatted: { type: string }
        mining:
          type: object
          properties:
            hashprice_usd_ph_day: { type: number }
            hashprice_btc_ph_day: { type: number }
            hashprice_change_24h_pct: { type: number }
            block_subsidy: { type: number }
            effective_reward: { type: number }
            tx_fees_avg_btc: { type: number }
            tx_fees_pct: { type: number }
        sources:
          type: object
          additionalProperties: { type: string }

    DifficultyEstimate:
      type: object
      required: [timestamp, current, next_adjustment]
      properties:
        timestamp: { type: string, format: date-time }
        current:
          type: object
          properties:
            difficulty: { type: number }
            difficulty_formatted: { type: string }
            height: { type: integer }
        previous_adjustment:
          type: object
          properties:
            change_percent: { type: number }
            date: { type: string, format: date }
            block_height: { type: integer }
            from_difficulty_formatted: { type: string }
            to_difficulty_formatted: { type: string }
        next_adjustment:
          type: object
          properties:
            estimated_difficulty: { type: number }
            estimated_difficulty_formatted: { type: string }
            change_percent: { type: number }
            blocks_remaining: { type: integer }
            estimated_date: { type: string, format: date-time }
            epoch_progress_percent: { type: number }
            epoch_avg_block_time_seconds: { type: integer }
        hashrate_eh: { type: number }
        source: { type: string, example: bitcoin_node }

    AsicPrice:
      type: object
      required: [model, hashrate, price_per_th, unit_price]
      properties:
        model: { type: string, description: ASIC model short name (e.g. "S21 XP") }
        hashrate: { type: number, description: Hashrate in TH/s }
        price_per_th: { type: number, description: Market price normalized in $/TH }
        unit_price: { type: number, description: Market unit price in USD }
        efficiency_jt:
          type: number
          nullable: true
          description: Efficiency in J/TH if known

    AsicPrices:
      type: object
      required: [generated_at, total_models, latest_prices]
      properties:
        generated_at: { type: string, format: date-time }
        total_models: { type: integer }
        latest_prices:
          type: array
          items: { $ref: '#/components/schemas/AsicPrice' }

    Error:
      type: object
      required: [error]
      properties:
        error: { type: string, example: rate_limited }
        message: { type: string }

  responses:
    RateLimited:
      description: Too many requests — slow down.
      headers:
        Retry-After:
          schema: { type: integer }
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example:
            error: rate_limited
            message: Free tier — slow down or contact contact@startmining.io for Enterprise.

    InternalError:
      description: Upstream Bitcoin Core node or aggregator is unreachable.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example:
            error: upstream_unavailable
            message: Bitcoin Core node temporarily unreachable. Retry shortly.

  securitySchemes:
    EnterpriseApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: |
        **Free tier accepts anonymous requests** — no API key required.
        The `x-api-key` header is reserved for Enterprise tier (custom rate
        limits, SLA, support, private deployment). Request access at
        contact@startmining.io.

security:
  - {} # Anonymous access permitted on Free tier
  - EnterpriseApiKey: []
