{
 "openapi": "3.1.0",
 "info": {
  "title": "Blueprint Canton Chain API",
  "version": "1.0.0",
  "summary": "Full-history Canton Network chain data over one REST API.",
  "description": "Query every Canton Coin transaction since genesis (June 2024), any party's complete history, live balances and holdings, mining rounds, ANS names, network configuration, and aggregated chain statistics.\n\nThe API is backed by Blueprint's own Canton validator infrastructure: a continuously ingesting index of the global transaction feed (~seconds behind head), normalized per party, plus live pass-through to the Super Validator Scan API for point-in-time state. All endpoints are read-only GETs returning JSON.\n\n**Cursors** \u2014 list endpoints paginate by the monotonic `seq` cursor: pass `before_seq` (newest-first) or `after_seq` (oldest-first, party history only) and chain the `next_before_seq` / `next_after_seq` value from each response. `before_seq=0` means \"start at the newest\".\n\n**Authentication & rate limits** \u2014 browsing is open (anonymous, ~120 req/min per IP). Authenticate with an API key \u2014 `Authorization: Bearer <key>` or `X-API-Key: <key>` \u2014 to unlock a plan: Free (300 req/min), Pro (3,000), Enterprise (30,000). Live tiers at `GET /api/plans`. Every response carries `RateLimit-Limit` / `RateLimit-Remaining` / `RateLimit-Reset` headers; exceeding the limit returns `429` with `Retry-After`, an invalid key returns `401`.\n\n**Access** \u2014 public for evaluation. For a key, production terms, SLAs, or dedicated capacity, contact Blueprint at https://theblueprint.xyz.",
  "contact": {
   "name": "Blueprint",
   "url": "https://theblueprint.xyz"
  }
 },
 "servers": [
  {
   "url": "https://ccscan.xyz"
  }
 ],
 "tags": [
  {
   "name": "Overview",
   "description": "Chain head, totals, and live feed snapshot"
  },
  {
   "name": "Transactions",
   "description": "The global transaction feed from genesis, filterable and cursor-paginated"
  },
  {
   "name": "Parties",
   "description": "Any party's history, balance, and holdings"
  },
  {
   "name": "Rounds",
   "description": "Mining-round activity"
  },
  {
   "name": "Names",
   "description": "Canton Name Service (ANS) directory"
  },
  {
   "name": "Network",
   "description": "DSO, super validators, and CC configuration"
  },
  {
   "name": "Stats",
   "description": "Daily aggregates and market data"
  },
  {
   "name": "Search",
   "description": "Universal query classifier"
  },
  {
   "name": "Meta",
   "description": "Health and machine-readable discovery"
  }
 ],
 "paths": {
  "/api/overview": {
   "get": {
    "tags": [
     "Overview"
    ],
    "operationId": "getOverview",
    "summary": "Chain head snapshot",
    "description": "Head sequence, latest round, indexed totals, 24-hour transaction count, ingest freshness, and the 12 most recent transactions.",
    "responses": {
     "200": {
      "description": "Current chain overview",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "head_seq": {
           "type": "integer",
           "description": "Highest indexed sequence number"
          },
          "latest_round": {
           "type": [
            "integer",
            "null"
           ]
          },
          "latest_tx_date": {
           "type": "string",
           "description": "Timestamp of the newest indexed transaction (UTC)"
          },
          "total_tx_est": {
           "type": [
            "integer",
            "null"
           ],
           "description": "Planner estimate of total indexed transactions"
          },
          "party_count_est": {
           "type": [
            "integer",
            "null"
           ],
           "description": "Planner estimate of distinct parties ever seen"
          },
          "tx_24h": {
           "type": "integer",
           "description": "Transactions indexed in the trailing 24 hours"
          },
          "ingest_cursor_at": {
           "type": [
            "string",
            "null"
           ],
           "description": "Last ingest checkpoint time \u2014 freshness signal"
          },
          "latest_txs": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/TxRow"
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/txs": {
   "get": {
    "tags": [
     "Transactions"
    ],
    "operationId": "listTransactions",
    "summary": "Global transaction feed",
    "description": "Newest-first, cursor-paginated global feed. Combine `type`, `round`, and `day` filters freely. `day` navigation costs ~30 index probes via binary search over the sequence key \u2014 no scan.",
    "parameters": [
     {
      "name": "before_seq",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 0
      },
      "description": "Return rows with seq < this value; 0 or omitted = start at newest. Chain `next_before_seq` to page."
     },
     {
      "name": "type",
      "in": "query",
      "schema": {
       "$ref": "#/components/schemas/TxType"
      },
      "description": "Filter by transaction type"
     },
     {
      "name": "round",
      "in": "query",
      "schema": {
       "type": "integer"
      },
      "description": "Filter to one mining round"
     },
     {
      "name": "day",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date",
       "example": "2025-01-15"
      },
      "description": "Jump to a UTC calendar day (YYYY-MM-DD)"
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 25,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "One page of transactions",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "count": {
           "type": "integer"
          },
          "next_before_seq": {
           "type": "integer",
           "description": "Pass back as before_seq for the next (older) page; 0 when empty"
          },
          "txs": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/TxRow"
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "503": {
      "$ref": "#/components/responses/IndexBuilding"
     }
    }
   }
  },
  "/api/tx/{key}": {
   "get": {
    "tags": [
     "Transactions"
    ],
    "operationId": "getTransaction",
    "summary": "One transaction by seq or event id",
    "parameters": [
     {
      "name": "key",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "Sequence number (digits) or full event id (e.g. `#1220\u2026:0`)"
     }
    ],
    "responses": {
     "200": {
      "description": "The transaction with its full financial body",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Tx"
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     }
    }
   }
  },
  "/api/party/search": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "searchParties",
    "summary": "Substring search over every party ever seen",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "minLength": 2
      },
      "description": "Case-insensitive fragment of a party id"
     }
    ],
    "responses": {
     "200": {
      "description": "Up to 50 matches",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "count": {
           "type": "integer"
          },
          "parties": {
           "type": "array",
           "items": {
            "type": "string"
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/party/{party}/summary": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "getPartySummary",
    "summary": "Party activity summary + ANS name",
    "description": "First/last activity and transaction count (exact up to 100,000, then reported as capped), plus the party's ANS entry when registered.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Party"
     }
    ],
    "responses": {
     "200": {
      "description": "Party summary",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "party": {
           "type": "string"
          },
          "tx_count": {
           "type": "integer",
           "description": "Exact up to 100,000"
          },
          "tx_count_capped": {
           "type": "boolean",
           "description": "true when the party has more than 100,000 transactions"
          },
          "first_seen": {
           "type": [
            "string",
            "null"
           ]
          },
          "first_seq": {
           "type": [
            "integer",
            "null"
           ]
          },
          "last_seen": {
           "type": [
            "string",
            "null"
           ]
          },
          "last_seq": {
           "type": [
            "integer",
            "null"
           ]
          },
          "ans": {
           "type": [
            "object",
            "null"
           ],
           "description": "ANS entry (name, url, description, expires_at) when registered"
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     }
    }
   }
  },
  "/api/party/{party}/balance": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "getPartyBalance",
    "summary": "Live CC balance (point-in-time ACS snapshot)",
    "description": "Balance computed against the most recent valid ACS snapshot from the Scan API: unlocked/locked/total holdings, accrued holding fees, and available coin.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Party"
     }
    ],
    "responses": {
     "200": {
      "description": "Balance summary",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "record_time": {
           "type": "string",
           "description": "Snapshot time the balance is computed as of"
          },
          "computed_as_of_round": {
           "type": "integer"
          },
          "summary": {
           "type": [
            "object",
            "null"
           ],
           "description": "Null when the party holds no CC at the snapshot",
           "properties": {
            "party_id": {
             "type": "string"
            },
            "total_unlocked_coin": {
             "type": "string"
            },
            "total_locked_coin": {
             "type": "string"
            },
            "total_coin_holdings": {
             "type": "string"
            },
            "accumulated_holding_fees_unlocked": {
             "type": "string"
            },
            "accumulated_holding_fees_locked": {
             "type": "string"
            },
            "accumulated_holding_fees_total": {
             "type": "string"
            },
            "total_available_coin": {
             "type": "string",
             "description": "Holdings minus accrued holding fees"
            }
           }
          }
         }
        }
       }
      }
     },
     "502": {
      "$ref": "#/components/responses/UpstreamUnavailable"
     }
    }
   }
  },
  "/api/party/{party}/holdings": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "getPartyHoldings",
    "summary": "Live holding contracts",
    "description": "The party's active Amulet holding contracts at the latest ACS snapshot (Scan API pass-through, page size 200).",
    "parameters": [
     {
      "$ref": "#/components/parameters/Party"
     },
     {
      "name": "after",
      "in": "query",
      "schema": {
       "type": "integer"
      },
      "description": "Scan API pagination token from a previous page"
     }
    ],
    "responses": {
     "200": {
      "description": "Holding contracts (Scan API `created_events` shape)",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "description": "Live ACS snapshot passed through from the Super Validator Scan API \u2014 the party's active Amulet holding contracts.",
         "properties": {
          "record_time": {
           "type": "string",
           "description": "Snapshot record time (UTC)"
          },
          "migration_id": {
           "type": [
            "integer",
            "null"
           ],
           "description": "Synchronizer migration id"
          },
          "created_events": {
           "type": "object",
           "description": "Contract-id \u2192 created-event map; each event's create_arguments carry the holding amount and lock state"
          },
          "next_page_token": {
           "type": [
            "string",
            "integer",
            "null"
           ],
           "description": "Scan pagination token; pass as ?after= for the next page"
          }
         }
        }
       }
      }
     },
     "502": {
      "$ref": "#/components/responses/UpstreamUnavailable"
     }
    }
   }
  },
  "/api/party/{party}/txs": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "listPartyTransactions",
    "summary": "A party's complete transaction history",
    "description": "Every transaction the party appears in, from genesis. Page forward (oldest-first) with `after_seq` or backward (newest-first) with `before_seq` \u2014 mutually exclusive. Each row carries the party's roles in that transaction.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Party"
     },
     {
      "name": "after_seq",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 0
      },
      "description": "Oldest-first: rows with seq > this value"
     },
     {
      "name": "before_seq",
      "in": "query",
      "schema": {
       "type": "integer"
      },
      "description": "Newest-first: rows with seq < this value; 0 = start at newest"
     },
     {
      "name": "type",
      "in": "query",
      "schema": {
       "$ref": "#/components/schemas/TxType"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 25,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "One page of the party's transactions",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "party": {
           "type": "string"
          },
          "count": {
           "type": "integer"
          },
          "next_after_seq": {
           "type": "integer",
           "description": "Present in forward mode"
          },
          "next_before_seq": {
           "type": "integer",
           "description": "Present in backward mode"
          },
          "txs": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/PartyTxRow"
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     },
     "503": {
      "$ref": "#/components/responses/IndexBuilding"
     }
    }
   }
  },
  "/api/round/{round}": {
   "get": {
    "tags": [
     "Rounds"
    ],
    "operationId": "getRound",
    "summary": "One mining round",
    "description": "Transaction count, sequence range, time span, and a newest-first page of the round's transactions.",
    "parameters": [
     {
      "name": "round",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "before_seq",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 0
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 25,
       "maximum": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Round detail",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "round": {
           "type": "integer"
          },
          "tx_count": {
           "type": [
            "integer",
            "null"
           ]
          },
          "first_seq": {
           "type": [
            "integer",
            "null"
           ]
          },
          "last_seq": {
           "type": [
            "integer",
            "null"
           ]
          },
          "started": {
           "type": [
            "string",
            "null"
           ]
          },
          "ended": {
           "type": [
            "string",
            "null"
           ]
          },
          "count": {
           "type": "integer"
          },
          "next_before_seq": {
           "type": "integer"
          },
          "txs": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/TxRow"
           }
          },
          "note": {
           "type": "string",
           "description": "present for round 0 (large automation bucket): explains the omitted exact count"
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     },
     "503": {
      "$ref": "#/components/responses/IndexBuilding"
     }
    }
   }
  },
  "/api/ans": {
   "get": {
    "tags": [
     "Names"
    ],
    "operationId": "listAnsEntries",
    "summary": "ANS name directory",
    "description": "Canton Name Service entries (Scan API pass-through). Filter with a lowercase name prefix.",
    "parameters": [
     {
      "name": "page_size",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 100,
       "maximum": 1000
      }
     },
     {
      "name": "prefix",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "Name prefix, lowercased server-side"
     }
    ],
    "responses": {
     "200": {
      "description": "ANS entries",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "entries": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "name": {
              "type": "string"
             },
             "user": {
              "type": "string",
              "description": "The party id the name resolves to"
             },
             "url": {
              "type": "string"
             },
             "description": {
              "type": "string"
             },
             "expires_at": {
              "type": [
               "string",
               "null"
              ]
             },
             "contract_id": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "502": {
      "$ref": "#/components/responses/UpstreamUnavailable"
     }
    }
   }
  },
  "/api/network": {
   "get": {
    "tags": [
     "Network"
    ],
    "operationId": "getNetwork",
    "summary": "DSO, super validators, CC configuration, versions",
    "description": "Aggregated network metadata: DSO state, the super validator scan directory, Splice instance names, Scan version, and the current Amulet (CC) rules payload.",
    "responses": {
     "200": {
      "description": "Network metadata",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "dso": {
           "type": "object"
          },
          "scans": {
           "type": "object",
           "description": "Super validator scan directory"
          },
          "instance_names": {
           "type": "object"
          },
          "version": {
           "type": "object"
          },
          "amulet_rules": {
           "type": "object",
           "description": "Current AmuletRules contract payload (fees, limits, schedule)"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/stats/daily": {
   "get": {
    "tags": [
     "Stats"
    ],
    "operationId": "getDailyStats",
    "summary": "Per-day aggregates from genesis",
    "description": "Daily transaction counts and CC volume by type, aggregated from the full index by a background job. `complete=false` means the genesis backfill is still filling in (progress = aggregated_to_seq / head_seq); days appear oldest-first as it advances.",
    "responses": {
     "200": {
      "description": "Daily aggregate series",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "days": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "day": {
              "type": "string",
              "format": "date"
             },
             "tx_count": {
              "type": "integer"
             },
             "transfers": {
              "type": "integer"
             },
             "mints": {
              "type": "integer"
             },
             "taps": {
              "type": "integer"
             },
             "aborts": {
              "type": "integer"
             },
             "cc_transferred": {
              "type": "number"
             },
             "cc_minted": {
              "type": "number"
             },
             "cc_tapped": {
              "type": "number"
             }
            }
           }
          },
          "aggregated_to_seq": {
           "type": "integer"
          },
          "head_seq": {
           "type": "integer"
          },
          "complete": {
           "type": "boolean"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/stats/recent": {
   "get": {
    "tags": [
     "Stats"
    ],
    "operationId": "getRecentStats",
    "summary": "Per-day tx counts for the last N days (always current)",
    "description": "Computed live by binary-searching the sequence key at each UTC day boundary \u2014 independent of the background aggregator, cached 10 minutes. The last entry is the current partial day.",
    "parameters": [
     {
      "name": "days",
      "in": "query",
      "schema": {
       "type": "integer",
       "default": 14,
       "minimum": 1,
       "maximum": 30
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Recent daily counts",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "days": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "day": {
              "type": "string",
              "format": "date"
             },
             "tx_count": {
              "type": "integer"
             },
             "partial": {
              "type": "boolean",
              "description": "Present and true on the current (incomplete) day"
             }
            }
           }
          },
          "head_seq": {
           "type": "integer"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/price": {
   "get": {
    "tags": [
     "Stats"
    ],
    "operationId": "getPrice",
    "summary": "Canton Coin market data",
    "description": "USD and BTC price, market cap, and 24h change (CoinGecko, cached 120s). `available=false` when market data cannot be fetched.",
    "responses": {
     "200": {
      "description": "Market data",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "available": {
           "type": "boolean"
          },
          "usd": {
           "type": [
            "number",
            "null"
           ]
          },
          "btc": {
           "type": [
            "number",
            "null"
           ]
          },
          "usd_market_cap": {
           "type": [
            "number",
            "null"
           ]
          },
          "usd_24h_change": {
           "type": [
            "number",
            "null"
           ]
          },
          "as_of": {
           "type": "integer",
           "description": "Unix timestamp the quote was fetched (present when available)"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/search": {
   "get": {
    "tags": [
     "Search"
    ],
    "operationId": "search",
    "summary": "Universal search",
    "description": "Classifies the query and returns typed results: sequence numbers and rounds (digits), event ids, exact party ids (`name::fingerprint`), party-id fragments, and ANS name prefixes.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Up to 20 typed results",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "results": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "kind": {
              "type": "string",
              "enum": [
               "tx",
               "round",
               "party"
              ]
             },
             "key": {
              "type": "string",
              "description": "Seq (tx), round number, or party id \u2014 feed to the matching endpoint"
             },
             "label": {
              "type": "string"
             },
             "ans": {
              "type": "string",
              "description": "Present when matched via an ANS name"
             }
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/plans": {
   "get": {
    "tags": [
     "Meta"
    ],
    "operationId": "getPlans",
    "summary": "Rate-limit tiers & how to authenticate",
    "description": "The anonymous baseline plus the sellable plans (Free / Pro / Enterprise) with their per-minute limits.",
    "responses": {
     "200": {
      "description": "Plans",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "anonymous": {
           "type": "object"
          },
          "plans": {
           "type": "object",
           "additionalProperties": {
            "type": "object",
            "properties": {
             "rpm": {
              "type": "integer"
             },
             "label": {
              "type": "string"
             }
            }
           }
          },
          "auth": {
           "type": "string"
          },
          "note": {
           "type": "string",
           "description": "Human-readable note about where the rate-limit budget is reported"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/healthz": {
   "get": {
    "tags": [
     "Meta"
    ],
    "operationId": "health",
    "summary": "Liveness",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "status": {
           "type": "string",
           "const": "ok"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/party/{party}/validator": {
   "get": {
    "tags": [
     "Parties"
    ],
    "operationId": "getPartyValidator",
    "summary": "Validator / super-validator status + liveness",
    "description": "Whether a party is a validator, super-validator, and/or app-provider \u2014 derived from the reward types it collects \u2014 plus a liveness assessment and recent reward performance. Computed from a bounded scan of the party's most recent transactions, so reward figures are over that recent window (see recent.note), NOT lifetime. Liveness is a reward-claim-recency heuristic: active (\u22646h since last claim), lagging (\u226424h), stale (\u22647d), inactive (>7d), or not_validator.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Party"
     }
    ],
    "responses": {
     "200": {
      "description": "Validator status",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "party": {
           "type": "string"
          },
          "is_validator": {
           "type": "boolean",
           "description": "Collects validator rewards"
          },
          "is_super_validator": {
           "type": "boolean",
           "description": "Collects super-validator (SV) rewards"
          },
          "is_app_provider": {
           "type": "boolean",
           "description": "Collects app-provider rewards"
          },
          "status": {
           "type": "string",
           "enum": [
            "active",
            "inactive",
            "unknown"
           ]
          },
          "liveness": {
           "type": "object",
           "properties": {
            "status": {
             "type": "string",
             "enum": [
              "active",
              "inactive",
              "unknown"
             ]
            },
            "rounds_behind": {
             "type": [
              "integer",
              "null"
             ],
             "description": "network_round - our_round; 0 means fully caught up"
            },
            "network_round": {
             "type": [
              "integer",
              "null"
             ],
             "description": "latest mining round on the network, from the super-validator scan"
            },
            "our_round": {
             "type": [
              "integer",
              "null"
             ],
             "description": "latest round our validator's participant has recorded"
            }
           }
          },
          "recent": {
           "type": "object",
           "description": "Reward performance over the scanned window (recent, not lifetime)",
           "properties": {
            "window_txs": {
             "type": "integer",
             "description": "Transactions scanned (most-recent first)"
            },
            "reward_collections": {
             "type": "integer"
            },
            "rewards_total": {
             "type": "number"
            },
            "sv_rewards": {
             "type": "number"
            },
            "validator_rewards": {
             "type": "number"
            },
            "app_rewards": {
             "type": "number"
            },
            "avg_per_collection": {
             "type": "number"
            },
            "span_rounds": {
             "type": "integer"
            },
            "span_hours": {
             "type": "number"
            },
            "note": {
             "type": "string"
            }
           }
          },
          "lifetime": {
           "type": [
            "object",
            "null"
           ],
           "description": "Exact lifetime reward totals from a cached full-history scan (null if the party is not a validator).",
           "properties": {
            "complete": {
             "type": "boolean",
             "description": "false only when the history was too large to total within the timeout; the recent window still applies"
            },
            "reward_collections": {
             "type": "integer"
            },
            "rewards_total": {
             "type": "number"
            },
            "sv_rewards": {
             "type": "number"
            },
            "validator_rewards": {
             "type": "number"
            },
            "app_rewards": {
             "type": "number"
            },
            "first_reward_round": {
             "type": [
              "integer",
              "null"
             ]
            },
            "last_reward_round": {
             "type": [
              "integer",
              "null"
             ]
            },
            "first_reward_at": {
             "type": [
              "string",
              "null"
             ]
            },
            "last_reward_at": {
             "type": [
              "string",
              "null"
             ]
            },
            "note": {
             "type": "string"
            },
            "pending": {
             "type": "boolean",
             "description": "true while exact totals are still being computed in the background \u2014 refetch shortly"
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     }
    }
   }
  },
  "/api/sync": {
   "get": {
    "tags": [
     "Network"
    ],
    "summary": "Chain-tip sync status",
    "description": "Network head round (from the super-validator scan) vs our validator's recorded height (max round). Powers Active/Inactive.",
    "responses": {
     "200": {
      "description": "sync status",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "network_round": {
           "type": [
            "integer",
            "null"
           ]
          },
          "our_round": {
           "type": [
            "integer",
            "null"
           ]
          },
          "rounds_behind": {
           "type": [
            "integer",
            "null"
           ]
          },
          "synced": {
           "type": "boolean"
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/featured-apps": {
   "get": {
    "tags": [
     "Network"
    ],
    "summary": "Featured apps directory",
    "description": "Featured apps (on-chain FeaturedAppRight, from the SV scan) with per-app app-reward / transaction metrics over 24h and 7d and a 14-day daily reward series. Metrics are aggregated in a background thread and cached.",
    "responses": {
     "200": {
      "description": "featured apps",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "count": {
           "type": "integer"
          },
          "categories": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "name": {
              "type": "string"
             },
             "count": {
              "type": "integer"
             }
            }
           }
          },
          "apps": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "provider": {
              "type": "string"
             },
             "name": {
              "type": "string"
             },
             "handle": {
              "type": "string"
             },
             "category": {
              "type": "string"
             },
             "featured_at": {
              "type": [
               "string",
               "null"
              ]
             },
             "windows": {
              "type": "object",
              "description": "per-window metrics (24h, 7d): txs, app rewards, burns",
              "additionalProperties": {
               "type": "object",
               "properties": {
                "txs": {
                 "type": "integer"
                },
                "rewards": {
                 "type": "number"
                },
                "burns": {
                 "type": "number"
                }
               }
              }
             }
            }
           }
          },
          "windows": {
           "type": "array",
           "items": {
            "type": "string"
           },
           "description": "available metric windows, e.g. [\"24h\",\"7d\"]"
          },
          "metrics_ready": {
           "type": "boolean",
           "description": "false until the first background aggregation pass finishes"
          },
          "metrics_age_seconds": {
           "type": [
            "integer",
            "null"
           ]
          },
          "series": {
           "type": "object",
           "description": "14-day daily app-reward series for the stacked chart",
           "properties": {
            "days": {
             "type": "array",
             "items": {
              "type": "string"
             }
            },
            "apps": {
             "type": "array",
             "items": {
              "type": "object",
              "properties": {
               "name": {
                "type": "string"
               },
               "provider": {
                "type": "string"
               },
               "values": {
                "type": "array",
                "items": {
                 "type": "number"
                }
               }
              }
             }
            },
            "others": {
             "type": "array",
             "items": {
              "type": "number"
             }
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/party/{party}/validator/rewards": {
   "get": {
    "tags": [
     "Parties"
    ],
    "summary": "Validator daily reward history",
    "parameters": [
     {
      "name": "party",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "description": "Weekly reward totals (sv+app+max(validator,faucet)) over the validator's full history, gap-filled. Powers the reward-history chart. Cached 30 min.",
    "responses": {
     "200": {
      "description": "daily series",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "weeks": {
           "type": "array",
           "items": {
            "type": "string"
           }
          },
          "rewards": {
           "type": "array",
           "items": {
            "type": "number"
           }
          },
          "collections": {
           "type": "array",
           "items": {
            "type": "integer"
           }
          },
          "total": {
           "type": "number"
          },
          "incomplete": {
           "type": "boolean"
          }
         }
        }
       }
      }
     }
    }
   }
  }
 },
 "security": [
  {},
  {
   "BearerAuth": []
  },
  {
   "ApiKeyHeader": []
  }
 ],
 "components": {
  "securitySchemes": {
   "BearerAuth": {
    "type": "http",
    "scheme": "bearer",
    "description": "API key as 'Authorization: Bearer <key>'. Omit for anonymous (per-IP) access."
   },
   "ApiKeyHeader": {
    "type": "apiKey",
    "in": "header",
    "name": "X-API-Key",
    "description": "API key as 'X-API-Key: <key>'."
   }
  },
  "parameters": {
   "Party": {
    "name": "party",
    "in": "path",
    "required": true,
    "schema": {
     "type": "string"
    },
    "description": "Full party id: `name::fingerprint` (URL-encode the `::`)",
    "example": "Cumberland-1::12201aa8a23046d5740c9edd58f7e820c83e7f5c58f25551f955f3252d3a04240860"
   }
  },
  "responses": {
   "NotFound": {
    "description": "Not found",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "Unauthorized": {
    "description": "Invalid or inactive API key",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "RateLimited": {
    "description": "Rate limit exceeded \u2014 see the Retry-After header (seconds)",
    "headers": {
     "Retry-After": {
      "schema": {
       "type": "integer"
      },
      "description": "Seconds until the window resets"
     },
     "RateLimit-Remaining": {
      "schema": {
       "type": "integer"
      }
     }
    },
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "BadRequest": {
    "description": "Invalid parameter",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "UpstreamUnavailable": {
    "description": "The Scan API upstream did not respond \u2014 retry shortly",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "IndexBuilding": {
    "description": "A supporting index is still building; the response carries `building: true` \u2014 retry in a few minutes",
    "content": {
     "application/json": {
      "schema": {
       "allOf": [
        {
         "$ref": "#/components/schemas/Error"
        },
        {
         "type": "object",
         "properties": {
          "building": {
           "type": "boolean"
          }
         }
        }
       ]
      }
     }
    }
   }
  },
  "schemas": {
   "TxType": {
    "type": "string",
    "enum": [
     "transfer",
     "mint",
     "tap",
     "abort_transfer_instruction"
    ]
   },
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "string"
     }
    },
    "required": [
     "error"
    ]
   },
   "TxRow": {
    "type": "object",
    "description": "One indexed transaction (list shape).",
    "properties": {
     "seq": {
      "type": "integer",
      "description": "Monotonic index sequence \u2014 the pagination cursor"
     },
     "event_id": {
      "type": "string",
      "description": "Canton event id, globally unique"
     },
     "round": {
      "type": [
       "integer",
       "null"
      ],
      "description": "Mining round (null/0 on some automation records)"
     },
     "tx_type": {
      "$ref": "#/components/schemas/TxType"
     },
     "tx_date": {
      "type": "string",
      "description": "Ledger record time (UTC)"
     },
     "amount": {
      "type": [
       "number",
       "null"
      ],
      "description": "Headline CC amount \u2014 a send: sum of receiver amounts; a reward collection: gross rewards claimed; a self-transfer/merge: the sender's net change (sender_change_amount); mint/tap: their amount. null only for aborts, which move no value."
     },
     "parties": {
      "type": "object",
      "description": "Every party in the transaction, mapped to its roles",
      "additionalProperties": {
       "type": "array",
       "items": {
        "type": "string",
        "enum": [
         "sender",
         "receiver",
         "balance_change",
         "mint",
         "tap"
        ]
       }
      }
     },
     "kind": {
      "type": [
       "string",
       "null"
      ],
      "description": "transfer_kind for transfers (e.g. preapproval_send, transfer_instruction_accept)"
     },
     "nature": {
      "type": "string",
      "enum": [
       "send",
       "reward",
       "self",
       "mint",
       "tap",
       "abort",
       "other"
      ],
      "description": "Economic nature: send (to a distinct receiver), reward (validator/SV/app reward collection), self (self-transfer/merge), mint, tap, abort, or other."
     },
     "rewards": {
      "type": [
       "number",
       "null"
      ],
      "description": "Rewards the sender collected in this transfer (validator + SV + app; the duplicate validator_reward/validator_faucet coupon is de-duplicated via max), or null if none."
     }
    }
   },
   "PartyTxRow": {
    "allOf": [
     {
      "$ref": "#/components/schemas/TxRow"
     },
     {
      "type": "object",
      "properties": {
       "roles": {
        "type": "array",
        "description": "How the requested party appears in this transaction",
        "items": {
         "type": "string",
         "enum": [
          "sender",
          "receiver",
          "balance_change"
         ]
        }
       }
      }
     }
    ]
   },
   "Tx": {
    "allOf": [
     {
      "$ref": "#/components/schemas/TxRow"
     },
     {
      "type": "object",
      "properties": {
       "detail": {
        "type": "object",
        "description": "Full financial body: `type`, ledger `offset`, and the matching `transfer` / `mint` / `tap` / `abort_transfer_instruction` payload with every party, amount, fee, and balance change",
        "properties": {
         "type": {
          "$ref": "#/components/schemas/TxType"
         },
         "offset": {
          "type": "string",
          "description": "Ledger offset"
         },
         "transfer": {
          "type": "object",
          "description": "sender {party, input_amulet_amount, sender_fee, holding_fees, sender_change_amount, \u2026}, receivers [{party, amount, receiver_fee}], balance_changes [{party, change_to_initial_amount_as_of_round_zero, change_to_holding_fees_rate}], transfer_kind, description"
         },
         "mint": {
          "type": "object"
         },
         "tap": {
          "type": "object"
         },
         "abort_transfer_instruction": {
          "type": "object"
         }
        }
       }
      }
     }
    ]
   }
  }
 }
}