{
  "openapi": "3.1.0",
  "info": {
    "title": "Gridcoinstats API",
    "version": "4.2.1",
    "summary": "Read-only Gridcoin chain statistics from the Gridcoinstats cache.",
    "description": "Public, read-only statistics of the Gridcoin chain, from the cache database of Gridcoinstats. It never calls the wallet, so it keeps answering when the wallet is down. For live wallet data there is the wallet API (`/wallet/v3`). Answers are JSON:API documents (`application/vnd.api+json`). Amounts are decimal strings with 8 decimals (GRC); times are Unix seconds with an `_iso` twin (UTC); a value the cache does not have is `null`, never `0`. The API has feeds and snapshots, with a hard cap: there is no lookup of a single older block or transaction by id, and no paged list of a whole table. The path's `v4` is the generation of the cache database it is built for.",
    "license": {
      "name": "Gridcoinstats",
      "url": "https://www.gridcoinstats.eu/about"
    }
  },
  "servers": [
    {
      "url": "https://api.gridcoinstats.eu",
      "description": "The public API"
    }
  ],
  "tags": [
    {
      "name": "Description",
      "description": "What the API is and links to its parts. No database."
    },
    {
      "name": "Status",
      "description": "How current the data is."
    },
    {
      "name": "Chain",
      "description": "Feeds and figures of the chain, for one network."
    },
    {
      "name": "BOINC",
      "description": "How far the BOINC indexer has come. Not about a network."
    }
  ],
  "paths": {
    "/gridcoinstats/v4": {
      "get": {
        "tags": [
          "Description"
        ],
        "summary": "The API",
        "description": "The description of the API with links to the networks and to the BOINC status. It does not touch a database and is outside the rate limit.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The description.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=3600, stale-while-revalidate=86400",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "api",
                    "id": "gridcoinstats",
                    "attributes": {
                      "name": "Gridcoinstats API",
                      "version": "4.2.1",
                      "networks": [
                        "mainnet",
                        "testnet"
                      ]
                    }
                  },
                  "links": {
                    "self": "/gridcoinstats/v4",
                    "mainnet": "/gridcoinstats/v4/mainnet",
                    "testnet": "/gridcoinstats/v4/testnet",
                    "boinc": "/gridcoinstats/v4/boinc"
                  },
                  "meta": {
                    "version": "4.2.1"
                  }
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}": {
      "get": {
        "tags": [
          "Description"
        ],
        "summary": "A network",
        "description": "The description of one network, with the link to its status. No database.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The description of the network.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=3600, stale-while-revalidate=86400",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "api",
                    "id": "gridcoinstats",
                    "attributes": {
                      "name": "Gridcoinstats API",
                      "description": "Gridcoin chain statistics from the Gridcoinstats cache database",
                      "version": "4.2.1",
                      "network": "mainnet"
                    }
                  },
                  "meta": {
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet",
                    "status": "/gridcoinstats/v4/mainnet/status"
                  }
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/status": {
      "get": {
        "tags": [
          "Status"
        ],
        "summary": "Status and lag",
        "description": "The newest indexed block, the heartbeat of the writer scripts and how far the data is behind the chain. A page asks this and decides from `indexed_height` what else to fetch.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The status.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=5, stale-while-revalidate=10",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "status",
                    "id": "gridcoinstats",
                    "attributes": {
                      "server_time": 1793343759,
                      "indexed_height": 4122905,
                      "indexed_block_time": 1793343568,
                      "indexed_block_time_iso": "2026-10-30T06:59:28Z",
                      "sync": {
                        "index": {
                          "state": "ok",
                          "height": 4122905,
                          "updated_time": 1793343735,
                          "updated_time_iso": "2026-10-30T07:02:15Z"
                        },
                        "cache": {
                          "state": "ok",
                          "height": 4122905,
                          "updated_time": 1793343736,
                          "updated_time_iso": "2026-10-30T07:02:16Z"
                        },
                        "mempool": {
                          "state": "ok",
                          "height": null,
                          "updated_time": 1793343756,
                          "updated_time_iso": "2026-10-30T07:02:36Z"
                        },
                        "chain": {
                          "height": 4122905,
                          "updated_time": 1793343735,
                          "updated_time_iso": "2026-10-30T07:02:15Z"
                        },
                        "cache_behind_blocks": 0,
                        "cache_target": 4122905,
                        "behind_blocks": 0,
                        "lag_blocks": 0
                      },
                      "boinc": {
                        "state": "ok",
                        "updated_time": 1793343729,
                        "updated_time_iso": "2026-10-30T07:02:09Z",
                        "snapshot_time": 1793342104
                      },
                      "health": {
                        "level": "good",
                        "words": "everything runs",
                        "wallet": {
                          "level": "good",
                          "height": 4122905,
                          "block_time": 1793343568,
                          "block_age": 191,
                          "asked_age": 24
                        },
                        "cache": {
                          "level": "good",
                          "height": 4122905,
                          "late": 0,
                          "problem": null,
                          "note": "same block"
                        },
                        "boinc": {
                          "level": "good",
                          "snapshot_time": 1793342104,
                          "snapshot_age": 1655,
                          "problem": null,
                          "note": null
                        }
                      }
                    }
                  },
                  "meta": {
                    "indexedHeight": 4122905,
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/status"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/network": {
      "get": {
        "tags": [
          "Chain"
        ],
        "summary": "The network figures",
        "description": "The figures of the front page's status row from the newest block. All null while the cache is empty.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The figures.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=30, stale-while-revalidate=60",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "network",
                    "id": "current",
                    "attributes": {
                      "height": 4122905,
                      "time": 1793343568,
                      "time_iso": "2026-10-30T06:59:28Z",
                      "difficulty": "13.636711672718",
                      "coin_supply": "542067145.65583341",
                      "blocks_24h": 889,
                      "stakers_24h": 411,
                      "researchers_24h": 183,
                      "superblock_height": 4122152,
                      "superblock_time": 1793270064,
                      "superblock_time_iso": "2026-10-29T10:34:24Z"
                    }
                  },
                  "meta": {
                    "indexedHeight": 4122905,
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/network"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/supply": {
      "get": {
        "tags": [
          "Chain"
        ],
        "summary": "The coin supply",
        "description": "The coin supply for the sites that list coins: the total supply as the wallet counts it, what is burnt and the circulating supply. All null while the cache is empty.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The supply.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=30, stale-while-revalidate=60",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/SupplyDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "supply",
                    "id": "current",
                    "attributes": {
                      "height": 4122905,
                      "time": 1793343568,
                      "time_iso": "2026-10-30T06:59:28Z",
                      "total_supply": "542067145.65583341",
                      "burnt_supply": "35263.82439756",
                      "circulating_supply": "542031881.83143585"
                    }
                  },
                  "meta": {
                    "indexedHeight": 4122905,
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/supply"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/blocks": {
      "get": {
        "tags": [
          "Chain"
        ],
        "summary": "The latest blocks",
        "description": "The latest blocks, newest first: a live feed, one query on the primary key. There is no way to read one older block by its height or hash.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          },
          {
            "name": "page[size]",
            "in": "query",
            "required": false,
            "description": "How many items, the newest first. At most 100. A feed has no other page: `page[number]` above 1, a sort order or a filter it does not take is a 400.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The blocks.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=5, stale-while-revalidate=10",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/BlocksDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": [
                    {
                      "type": "block",
                      "id": "4122905",
                      "attributes": {
                        "height": 4122905,
                        "hash": "f200a37af392724d7394f5c2b9f2496b71631c5f1d05e31454beecb0d08ce486",
                        "time": 1793343568,
                        "time_iso": "2026-10-30T06:59:28Z",
                        "version": 14,
                        "size": 538,
                        "difficulty": "13.636711672718",
                        "mint_type": "MINT_POS_RR",
                        "is_superblock": false,
                        "superblock_version": null,
                        "magnitude": 1280,
                        "tx_count": 2,
                        "output_address_count": 1,
                        "coin_supply": "542067145.65583341",
                        "volume_output": "3258.12937539",
                        "volume_transfer": "0.00000000",
                        "volume_fee": "0.00000000",
                        "volume_mint_por": "6.35093333",
                        "volume_mint_block": "82.64466526",
                        "staker_address": "SKCqWjfAygVvATpQudwB9DhQpeoR5L7GyC",
                        "staker_cpid": "bc0621a4ac4610ffa400a0d298c02e23"
                      }
                    }
                  ],
                  "meta": {
                    "indexedHeight": 4122905,
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/blocks"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/transactions": {
      "get": {
        "tags": [
          "Chain"
        ],
        "summary": "The latest transactions",
        "description": "The latest transactions, newest first: a live feed like the blocks. There is no way to read one transaction by its id.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          },
          {
            "name": "page[size]",
            "in": "query",
            "required": false,
            "description": "How many items, the newest first. At most 100. A feed has no other page: `page[number]` above 1, a sort order or a filter it does not take is a 400.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "filter[kind]",
            "in": "query",
            "required": false,
            "description": "Only `transfer` or `contract` transactions.",
            "schema": {
              "type": "string",
              "enum": [
                "transfer",
                "contract"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The transactions.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=30, stale-while-revalidate=60",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionsDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": [
                    {
                      "type": "transaction",
                      "id": "511353f744d4cde5fb8c832a74623ff3305bb353d16787217e9dcada083be13e",
                      "attributes": {
                        "txid": "511353f744d4cde5fb8c832a74623ff3305bb353d16787217e9dcada083be13e",
                        "height": 4122905,
                        "time": 1793343568,
                        "time_iso": "2026-10-30T06:59:28Z",
                        "tx_type": "MINT_POS_RR",
                        "input_count": 1,
                        "output_count": 2,
                        "input_address_count": 1,
                        "output_address_count": 1,
                        "input_volume": "3175.48471013",
                        "output_volume": "3258.12937539",
                        "fee_volume": "0.00000000",
                        "burn_volume": "0.00000000",
                        "transfer_volume": "0.00000000",
                        "stake_volume": "3175.48471013",
                        "coindays_destroyed": "99022.20"
                      }
                    }
                  ],
                  "meta": {
                    "indexedHeight": 4122905,
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/transactions"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/{network}/mempool": {
      "get": {
        "tags": [
          "Chain"
        ],
        "summary": "The transactions waiting for a block",
        "description": "The transactions that wait for a block, newest first (by when our node first saw them), and the pool in figures. Stakes are never in the pool. When the watcher is not running `meta.watch.known` is `false`, `data` is empty and the figures are `null`.",
        "parameters": [
          {
            "name": "network",
            "in": "path",
            "required": true,
            "description": "The network.",
            "schema": {
              "type": "string",
              "enum": [
                "mainnet",
                "testnet"
              ]
            }
          },
          {
            "name": "page[size]",
            "in": "query",
            "required": false,
            "description": "How many items, the newest first. At most 100. A feed has no other page: `page[number]` above 1, a sort order or a filter it does not take is a 400.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The pool.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=5, stale-while-revalidate=10",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/MempoolDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": [
                    {
                      "type": "pool-transaction",
                      "id": "3a1e5a5dc486f561deb33f53019d085b27c217a41c65ac6d1e4555fbbc2f8898",
                      "attributes": {
                        "txid": "3a1e5a5dc486f561deb33f53019d085b27c217a41c65ac6d1e4555fbbc2f8898",
                        "first_seen": 1793343626,
                        "first_seen_iso": "2026-10-30T07:00:26Z",
                        "time": 1793343616,
                        "time_iso": "2026-10-30T07:00:16Z",
                        "tx_type": "TRANSFER",
                        "size": 841,
                        "input_count": 4,
                        "output_count": 7,
                        "output_volume": "36.48016048",
                        "moved_volume": "36.48016048",
                        "fee_volume": "0.00100000",
                        "fee_per_kb": "0.00118906",
                        "from_address": "SK7WASoXZFQrQLwTmabkS3Co8RUq6UevDU",
                        "from_more": 3,
                        "to_address": "SC46xoiGeoYhVnw5YSBTTHMR3kUZNGdSr4",
                        "to_more": 6
                      }
                    }
                  ],
                  "meta": {
                    "watch": {
                      "known": true,
                      "looked_at": 1793343756,
                      "looked_at_iso": "2026-10-30T07:02:36Z"
                    },
                    "count": 2,
                    "output_volume": "45.61807205",
                    "longest_wait": 146,
                    "usual_wait": 77,
                    "fee_histogram": {
                      "unit": "fee per kilobyte, in GRC",
                      "buckets": [
                        {
                          "from": "0.00000000",
                          "to": "0.00100000",
                          "count": 0
                        },
                        {
                          "from": "0.00100000",
                          "to": "0.00200000",
                          "count": 2
                        },
                        {
                          "from": "0.00200000",
                          "to": "0.00500000",
                          "count": 0
                        },
                        {
                          "from": "0.00500000",
                          "to": "0.01000000",
                          "count": 0
                        },
                        {
                          "from": "0.01000000",
                          "to": "0.05000000",
                          "count": 0
                        },
                        {
                          "from": "0.05000000",
                          "to": null,
                          "count": 0
                        }
                      ],
                      "unknown": 0
                    },
                    "recently_taken": [
                      {
                        "txid": "6c0a0731531dedf937c7ffdf118428378b18439521b499898f6bcbe6f20e6c75",
                        "tx_type": "TRANSFER",
                        "height": 4122901,
                        "taken_at": 1793343400,
                        "taken_at_iso": "2026-10-30T06:56:40Z",
                        "waited": 30
                      },
                      {
                        "txid": "c7e9fe0ceb8f5aaccc42039cbddef80f745e8ff216c226b1d0225fcc4fad31fc",
                        "tx_type": "TRANSFER",
                        "height": 4122898,
                        "taken_at": 1793343156,
                        "taken_at_iso": "2026-10-30T06:52:36Z",
                        "waited": 27
                      }
                    ],
                    "network": "mainnet",
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/mainnet/mempool"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/boinc": {
      "get": {
        "tags": [
          "BOINC"
        ],
        "summary": "The BOINC status description",
        "description": "No database; `meta.network` is `null`: the BOINC data belongs to no network.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The description.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=3600, stale-while-revalidate=86400",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "api",
                    "id": "gridcoinstats-boinc",
                    "attributes": {
                      "name": "Gridcoinstats BOINC status",
                      "description": "How far the BOINC indexer has read the statistics of the whitelisted projects",
                      "version": "4.2.1"
                    }
                  },
                  "meta": {
                    "network": null,
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/boinc",
                    "status": "/gridcoinstats/v4/boinc/status"
                  }
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/gridcoinstats/v4/boinc/status": {
      "get": {
        "tags": [
          "BOINC"
        ],
        "summary": "How far the BOINC indexer has come",
        "description": "The indexer's state and, for each project, the newest team, user and host snapshot it read.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The BOINC status.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=15, stale-while-revalidate=30",
                "schema": {
                  "type": "string"
                }
              },
              "ETag": {
                "description": "A weak validator: send it back as `If-None-Match` and an unchanged answer is a 304.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests a minute from one IP, all endpoints together.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "What is left in this minute.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/BoincStatusDocument"
                },
                "example": {
                  "jsonapi": {
                    "version": "1.1"
                  },
                  "data": {
                    "type": "boinc-status",
                    "id": "gridcoinstats",
                    "attributes": {
                      "indexer": {
                        "state": "ok",
                        "updated_time": 1793343729,
                        "updated_time_iso": "2026-10-30T07:02:09Z"
                      },
                      "last_consumed_time": 1793342467,
                      "last_consumed_time_iso": "2026-10-30T06:41:07Z",
                      "projects": [
                        {
                          "name": "asteroids@home",
                          "team": {
                            "consumed_time": 1793332622,
                            "consumed_time_iso": "2026-10-30T03:57:02Z",
                            "snapshot_time": 1793311981,
                            "snapshot_time_iso": "2026-10-29T22:13:01Z",
                            "items": 2223
                          },
                          "user": {
                            "consumed_time": 1793332694,
                            "consumed_time_iso": "2026-10-30T03:58:14Z",
                            "snapshot_time": 1793311817,
                            "snapshot_time_iso": "2026-10-29T22:10:17Z",
                            "items": 165073
                          },
                          "host": {
                            "consumed_time": 1793333023,
                            "consumed_time_iso": "2026-10-30T04:03:43Z",
                            "snapshot_time": 1793311980,
                            "snapshot_time_iso": "2026-10-29T22:13:00Z",
                            "items": 411884
                          }
                        },
                        {
                          "name": "denis@home",
                          "team": {
                            "consumed_time": 1793332618,
                            "consumed_time_iso": "2026-10-30T03:56:58Z",
                            "snapshot_time": 1793265909,
                            "snapshot_time_iso": "2026-10-29T09:25:09Z",
                            "items": 533
                          },
                          "user": {
                            "consumed_time": 1793332659,
                            "consumed_time_iso": "2026-10-30T03:57:39Z",
                            "snapshot_time": 1793265903,
                            "snapshot_time_iso": "2026-10-29T09:25:03Z",
                            "items": 1208
                          },
                          "host": {
                            "consumed_time": 1793332739,
                            "consumed_time_iso": "2026-10-30T03:58:59Z",
                            "snapshot_time": 1793265908,
                            "snapshot_time_iso": "2026-10-29T09:25:08Z",
                            "items": 10895
                          }
                        }
                      ]
                    }
                  },
                  "meta": {
                    "projects": 16,
                    "network": null,
                    "version": "4.2.1"
                  },
                  "links": {
                    "self": "/gridcoinstats/v4/boinc/status"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter the endpoint does not take, or a value out of range or of the wrong kind (`page[number]=2` on a feed, `filter[kind]=x`).",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "405": {
            "description": "Any method but GET, HEAD and OPTIONS: the API only reads. `Allow: GET, HEAD, OPTIONS`.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests a minute from one IP (`Retry-After` says how long to wait).",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          },
          "503": {
            "description": "The cache database cannot be read (the details are in the log, not in the answer), or it is not a v4 database.",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDocument"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonApi": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "description": "The JSON:API version of the document.",
            "enum": [
              "1.1"
            ]
          }
        },
        "required": [
          "version"
        ]
      },
      "Links": {
        "type": "object",
        "properties": {
          "self": {
            "type": "string",
            "description": "The path of this answer."
          }
        },
        "required": [
          "self"
        ]
      },
      "MetaBase": {
        "type": "object",
        "properties": {
          "network": {
            "type": [
              "string",
              "null"
            ],
            "description": "The network of the answer, `mainnet` or `testnet`; `null` for the BOINC status, which belongs to no network.",
            "enum": [
              "mainnet",
              "testnet",
              null
            ]
          },
          "version": {
            "type": "string",
            "description": "The API's own version string."
          }
        },
        "required": [
          "version"
        ]
      },
      "MetaFeed": {
        "allOf": [
          {
            "$ref": "#/components/schemas/MetaBase"
          },
          {
            "type": "object",
            "properties": {
              "indexedHeight": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The height of the newest block the cache has, which every figure of the answer is from."
              }
            },
            "required": [
              "indexedHeight"
            ]
          }
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "The HTTP status, as text."
          },
          "title": {
            "type": "string",
            "description": "A short name of the problem."
          },
          "detail": {
            "type": "string",
            "description": "What is wrong, in a sentence. The details of a server problem are in the log, not here."
          },
          "code": {
            "type": "string",
            "description": "A name for the problem, where there is one (`invalid_query`)."
          },
          "source": {
            "type": "object",
            "properties": {
              "parameter": {
                "type": "string",
                "description": "The query parameter that is wrong."
              }
            },
            "required": [
              "parameter"
            ]
          }
        },
        "required": [
          "status",
          "title",
          "detail"
        ]
      },
      "ErrorDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Error"
            },
            "minItems": 1
          },
          "meta": {
            "$ref": "#/components/schemas/MetaBase"
          }
        },
        "required": [
          "jsonapi",
          "errors",
          "meta"
        ]
      },
      "ApiResource": {
        "type": "object",
        "properties": {
          "type": {
            "const": "api"
          },
          "id": {
            "type": "string",
            "description": "Always `gridcoinstats`."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "description": "The name of the API."
              },
              "version": {
                "type": "string",
                "description": "The API's own version."
              },
              "networks": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "A network."
                },
                "description": "The networks the API has: `mainnet` and `testnet`."
              },
              "description": {
                "type": "string",
                "description": "What the description is of (a network or the BOINC status)."
              },
              "network": {
                "type": "string",
                "description": "The network of a network description."
              }
            },
            "required": [
              "name",
              "version"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "ApiDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "$ref": "#/components/schemas/ApiResource"
          },
          "links": {
            "type": "object",
            "description": "Links to the networks and to the BOINC status.",
            "additionalProperties": {
              "type": "string"
            },
            "properties": {
              "self": {
                "type": "string"
              }
            },
            "required": [
              "self"
            ]
          },
          "meta": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string"
              },
              "network": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "version"
            ]
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "Block": {
        "type": "object",
        "properties": {
          "type": {
            "const": "block"
          },
          "id": {
            "type": "string",
            "description": "The height of the block, as text."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "height": {
                "type": "integer",
                "description": "The height of the block."
              },
              "hash": {
                "type": "string",
                "description": "The hash of the block, 64 hex characters.",
                "pattern": "^[0-9a-f]{64}$"
              },
              "time": {
                "type": "integer",
                "description": "The time of the block, Unix seconds."
              },
              "time_iso": {
                "type": "string",
                "description": "The time of the block, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "version": {
                "type": "integer",
                "description": "The block's version."
              },
              "size": {
                "type": "integer",
                "description": "The size of the block in bytes."
              },
              "difficulty": {
                "type": "string",
                "description": "The block's difficulty, a decimal string (the wallet's number as its shortest plain decimal).",
                "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
              },
              "mint_type": {
                "type": "string",
                "description": "What the block minted: `MINT_POS_RR` (a stake with a research reward), `MINT_POS` (a stake without one), `MINT_POW`, `MINT_GEN` or `COINBASE`."
              },
              "is_superblock": {
                "type": "boolean",
                "description": "Whether the block is a superblock. The old superblocks are counted too: those before block 1,034,768 (testnet 196,562), which the wallet's own `getblock` does not flag, are read from the block's claim (from 4.1.0)."
              },
              "superblock_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "description": "The superblock's version: 1 the legacy form packed in the claim string, 2 and 3 the later formats; null for a block that is not a superblock, or a superblock whose version the cache does not have (from 4.1.0)."
              },
              "magnitude": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The claim's magnitude."
              },
              "tx_count": {
                "type": "integer",
                "description": "The transactions in the block."
              },
              "output_address_count": {
                "type": "integer",
                "description": "The distinct addresses the block's transactions pay."
              },
              "coin_supply": {
                "type": "string",
                "description": "The wallet's money supply at the block, GRC (the wallet counts its unspendable outputs in it).",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "volume_output": {
                "type": "string",
                "description": "Everything the block's transactions pay out, coins staked back included, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "volume_transfer": {
                "type": "string",
                "description": "What was sent as transfers, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "volume_fee": {
                "type": "string",
                "description": "The fees, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "volume_mint_por": {
                "type": "string",
                "description": "The research reward, GRC (0 for a block without one).",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "volume_mint_block": {
                "type": "string",
                "description": "Everything the block minted, the research reward included, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "staker_address": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The address that staked the block."
              },
              "staker_cpid": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The CPID of the claim, 32 hex characters."
              }
            },
            "required": [
              "height",
              "hash",
              "time",
              "time_iso",
              "version",
              "size",
              "difficulty",
              "mint_type",
              "is_superblock",
              "superblock_version",
              "magnitude",
              "tx_count",
              "output_address_count",
              "coin_supply",
              "volume_output",
              "volume_transfer",
              "volume_fee",
              "volume_mint_por",
              "volume_mint_block",
              "staker_address",
              "staker_cpid"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "type": {
            "const": "transaction"
          },
          "id": {
            "type": "string",
            "description": "The transaction id."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "txid": {
                "type": "string",
                "description": "The transaction id, 40 hex characters."
              },
              "height": {
                "type": "integer",
                "description": "The block the transaction is in."
              },
              "time": {
                "type": "integer",
                "description": "The time of the transaction, Unix seconds."
              },
              "time_iso": {
                "type": "string",
                "description": "The time, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "tx_type": {
                "type": "string",
                "description": "Our classification of the transaction: `MINT_POS`, `MINT_POS_RR`, `TRANSFER`, `MULTISIG`, `BURN`, `CONTRACT_*` and so on (`type` is reserved by JSON:API)."
              },
              "input_count": {
                "type": "integer",
                "description": "The inputs."
              },
              "output_count": {
                "type": "integer",
                "description": "The outputs."
              },
              "input_address_count": {
                "type": "integer",
                "description": "The distinct addresses the inputs came from."
              },
              "output_address_count": {
                "type": "integer",
                "description": "The distinct addresses the outputs pay."
              },
              "input_volume": {
                "type": "string",
                "description": "The sum of the inputs, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "output_volume": {
                "type": "string",
                "description": "The sum of the outputs, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "fee_volume": {
                "type": "string",
                "description": "The fee, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "burn_volume": {
                "type": "string",
                "description": "What was burnt, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "transfer_volume": {
                "type": "string",
                "description": "What was sent to other addresses, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "stake_volume": {
                "type": "string",
                "description": "The coins that staked, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "coindays_destroyed": {
                "type": "string",
                "description": "The coin days the transaction destroyed, a decimal string.",
                "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
              }
            },
            "required": [
              "txid",
              "height",
              "time",
              "time_iso",
              "tx_type",
              "input_count",
              "output_count",
              "input_address_count",
              "output_address_count",
              "input_volume",
              "output_volume",
              "fee_volume",
              "burn_volume",
              "transfer_volume",
              "stake_volume",
              "coindays_destroyed"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "PoolTransaction": {
        "type": "object",
        "properties": {
          "type": {
            "const": "pool-transaction"
          },
          "id": {
            "type": "string",
            "description": "The transaction id."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "txid": {
                "type": "string",
                "description": "The transaction id."
              },
              "first_seen": {
                "type": "integer",
                "description": "When our node first saw it, Unix seconds (the wallet does not say when it did; the poller looks every 3 seconds)."
              },
              "first_seen_iso": {
                "type": "string",
                "description": "The same, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "time": {
                "type": "integer",
                "description": "The transaction's own time, Unix seconds."
              },
              "time_iso": {
                "type": "string",
                "description": "The same, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "tx_type": {
                "type": "string",
                "description": "`TRANSFER`, or `CONTRACT_*` as for a confirmed transaction. Stakes are never in the pool."
              },
              "size": {
                "type": "integer",
                "description": "The size in bytes."
              },
              "input_count": {
                "type": "integer",
                "description": "The inputs."
              },
              "output_count": {
                "type": "integer",
                "description": "The outputs."
              },
              "output_volume": {
                "type": "string",
                "description": "The sum of all outputs, change included, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "moved_volume": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "What goes to addresses that are not one of the inputs', the change left out, GRC; `null` when an input could not be read (never a guess).",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "fee_volume": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The fee, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "fee_per_kb": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The fee for each started kilobyte, GRC; `null` when the fee is not known.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "from_address": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The address of the first input; `null` when it could not be found."
              },
              "from_more": {
                "type": "integer",
                "description": "How many inputs more."
              },
              "to_address": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The first output address that is not the sender's; `null` when there is none."
              },
              "to_more": {
                "type": "integer",
                "description": "How many outputs more."
              }
            },
            "required": [
              "txid",
              "first_seen",
              "first_seen_iso",
              "time",
              "time_iso",
              "tx_type",
              "size",
              "input_count",
              "output_count",
              "output_volume",
              "moved_volume",
              "fee_volume",
              "fee_per_kb",
              "from_address",
              "from_more",
              "to_address",
              "to_more"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "Network": {
        "type": "object",
        "properties": {
          "type": {
            "const": "network"
          },
          "id": {
            "type": "string",
            "description": "Always `current`."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "height": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The newest block."
              },
              "time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Its time, Unix seconds."
              },
              "time_iso": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Its time, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "difficulty": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Its difficulty, a decimal string.",
                "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
              },
              "coin_supply": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The wallet's money supply at it, GRC.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "blocks_24h": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The blocks of the 24 hours before the newest block."
              },
              "stakers_24h": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The distinct staker addresses in those 24 hours."
              },
              "researchers_24h": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The distinct CPIDs in those 24 hours."
              },
              "superblock_height": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The newest superblock; `null` before the first."
              },
              "superblock_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Its time, Unix seconds."
              },
              "superblock_time_iso": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Its time, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              }
            },
            "required": [
              "height",
              "time",
              "time_iso",
              "difficulty",
              "coin_supply",
              "blocks_24h",
              "stakers_24h",
              "researchers_24h",
              "superblock_height",
              "superblock_time",
              "superblock_time_iso"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "Supply": {
        "type": "object",
        "properties": {
          "type": {
            "const": "supply"
          },
          "id": {
            "type": "string",
            "description": "Always `current`."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "height": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The newest block."
              },
              "time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Its time, Unix seconds."
              },
              "time_iso": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Its time, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "total_supply": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The wallet's money supply at that block, GRC. The wallet counts the value of its unspendable outputs in it, `OP_RETURN` (burn) outputs included.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "burnt_supply": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The value of every `OP_RETURN` output so far, GRC (none of them is ever spent).",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              },
              "circulating_supply": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`total_supply` less `burnt_supply`, GRC. Gridcoin has no premine and nothing locked, so the burnt coins are the only ones out of circulation. There is no maximum supply.",
                "pattern": "^[0-9]+\\.[0-9]{8}$"
              }
            },
            "required": [
              "height",
              "time",
              "time_iso",
              "total_supply",
              "burnt_supply",
              "circulating_supply"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "Status": {
        "type": "object",
        "properties": {
          "type": {
            "const": "status"
          },
          "id": {
            "type": "string",
            "description": "Always `gridcoinstats`."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "server_time": {
                "type": "integer",
                "description": "The Unix time at which the answer was made (an answer kept at the edge is up to 15 seconds old, which this shows)."
              },
              "indexed_height": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The newest block the cache has."
              },
              "indexed_block_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Its time, Unix seconds."
              },
              "indexed_block_time_iso": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Its time, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "sync": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "What a monitor alerts on: the `index`, `cache` and `mempool` scripts (each `null` until it has reported), and how far behind the chain the data is.",
                "properties": {
                  "index": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "state": {
                            "type": "string",
                            "description": "`ok`, `waiting`, `blocked` or `stopped`.",
                            "enum": [
                              "ok",
                              "waiting",
                              "blocked",
                              "stopped"
                            ]
                          },
                          "height": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "The height it reached; always `null` for the pool watcher."
                          },
                          "updated_time": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "When it last reported, Unix seconds. Compare with `server_time`: a script that says `ok` and has not reported for a few minutes is gone."
                          },
                          "updated_time_iso": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The same, UTC, as text.",
                            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
                          }
                        },
                        "required": [
                          "state",
                          "height",
                          "updated_time",
                          "updated_time_iso"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "cache": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "state": {
                            "type": "string",
                            "description": "`ok`, `waiting`, `blocked` or `stopped`.",
                            "enum": [
                              "ok",
                              "waiting",
                              "blocked",
                              "stopped"
                            ]
                          },
                          "height": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "The height it reached; always `null` for the pool watcher."
                          },
                          "updated_time": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "When it last reported, Unix seconds. Compare with `server_time`: a script that says `ok` and has not reported for a few minutes is gone."
                          },
                          "updated_time_iso": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The same, UTC, as text.",
                            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
                          }
                        },
                        "required": [
                          "state",
                          "height",
                          "updated_time",
                          "updated_time_iso"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mempool": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "state": {
                            "type": "string",
                            "description": "`ok`, `waiting`, `blocked` or `stopped`.",
                            "enum": [
                              "ok",
                              "waiting",
                              "blocked",
                              "stopped"
                            ]
                          },
                          "height": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "The height it reached; always `null` for the pool watcher."
                          },
                          "updated_time": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "When it last reported, Unix seconds. Compare with `server_time`: a script that says `ok` and has not reported for a few minutes is gone."
                          },
                          "updated_time_iso": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The same, UTC, as text.",
                            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
                          }
                        },
                        "required": [
                          "state",
                          "height",
                          "updated_time",
                          "updated_time_iso"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "chain": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "The wallet's height as the index script last saw it, with `height`, `updated_time` and `updated_time_iso`."
                  },
                  "cache_behind_blocks": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Index height less cache height (about 20 while both run: on purpose)."
                  },
                  "cache_target": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "The block the cache script aims at."
                  },
                  "behind_blocks": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "`chain.height` less `indexed_height`."
                  },
                  "lag_blocks": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "What is late, not what is on purpose: the index distance to the chain plus the cache distance to its target. `null` while a part is missing. A page says \"caught up\" at 2 or less."
                  }
                }
              },
              "boinc": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The BOINC indexer's heartbeat: `state`, `updated_time`, `updated_time_iso` and `snapshot_time` (the newest user snapshot it consumed). `null` when it has not reported."
              },
              "health": {
                "type": "object",
                "description": "How the wallet, the cache index and the BOINC index stand, worked out on the server by one set of limits: `level` (`good`, `notice` or `warning`, the worst of the three), `words`, and for `wallet`, `cache` and `boinc` a `level` and what it is at.",
                "properties": {
                  "level": {
                    "type": "string",
                    "description": "The worst of the three.",
                    "enum": [
                      "good",
                      "notice",
                      "warning"
                    ]
                  },
                  "words": {
                    "type": "string",
                    "description": "A few words for it."
                  }
                }
              }
            },
            "required": [
              "server_time",
              "indexed_height",
              "indexed_block_time",
              "indexed_block_time_iso",
              "sync",
              "boinc",
              "health"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "BoincStatus": {
        "type": "object",
        "properties": {
          "type": {
            "const": "boinc-status"
          },
          "id": {
            "type": "string",
            "description": "Always `gridcoinstats`."
          },
          "attributes": {
            "type": "object",
            "properties": {
              "indexer": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The BOINC indexer: `state`, `updated_time`, `updated_time_iso`. `null` on a database that is not a BOINC v4 database."
              },
              "last_consumed_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "When the indexer last read a file, Unix seconds."
              },
              "last_consumed_time_iso": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The same, UTC, as text.",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              },
              "projects": {
                "type": "array",
                "description": "For each project the newest file read of `team`, `user` and `host`: its `snapshot_time` (when the project last changed it) and `consumed_time` (when the indexer read it). A project whose `consumed_time` stands still while the others move has stopped publishing or fails.",
                "items": {
                  "type": "object"
                }
              }
            },
            "required": [
              "indexer",
              "last_consumed_time",
              "last_consumed_time_iso",
              "projects"
            ]
          }
        },
        "required": [
          "type",
          "id",
          "attributes"
        ]
      },
      "BlocksDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Block"
            }
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "$ref": "#/components/schemas/MetaFeed"
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "TransactionsDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "$ref": "#/components/schemas/MetaFeed"
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "NetworkDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "$ref": "#/components/schemas/Network"
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "$ref": "#/components/schemas/MetaFeed"
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "SupplyDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "$ref": "#/components/schemas/Supply"
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "$ref": "#/components/schemas/MetaFeed"
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "StatusDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "$ref": "#/components/schemas/Status"
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "$ref": "#/components/schemas/MetaFeed"
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "MempoolDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PoolTransaction"
            }
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MetaBase"
              },
              {
                "type": "object",
                "properties": {
                  "watch": {
                    "type": "object",
                    "properties": {
                      "known": {
                        "type": "boolean",
                        "description": "`true` when the script that watches the pool reported `ok` in the last 30 seconds. When it is `false`, `data` is empty and the figures of the pool are `null`."
                      },
                      "looked_at": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "description": "The script's last report, Unix seconds; `null` if it never reported."
                      },
                      "looked_at_iso": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "The same, UTC, as text.",
                        "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
                      }
                    },
                    "required": [
                      "known",
                      "looked_at",
                      "looked_at_iso"
                    ]
                  },
                  "count": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "How many transactions wait now (the whole pool, not the page)."
                  },
                  "output_volume": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The sum of their outputs, GRC.",
                    "pattern": "^[0-9]+\\.[0-9]{8}$"
                  },
                  "longest_wait": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Seconds the oldest has waited; `null` when none waits."
                  },
                  "usual_wait": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "The median wait, in seconds, of the transactions a block took in the last 24 hours; `null` when none did."
                  },
                  "fee_histogram": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "The pool by fee per kilobyte in GRC: `buckets` (`from`, `to` (`null` for the last), `count`; from 0, 0.001, 0.002, 0.005, 0.01 and 0.05) and `unknown` (no fee known)."
                  },
                  "recently_taken": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "description": "The last 25 transactions a block took, newest first: `txid`, `tx_type`, `height`, `taken_at`, `taken_at_iso`, `waited` (seconds).",
                    "items": {
                      "type": "object"
                    }
                  }
                },
                "required": [
                  "watch",
                  "count",
                  "output_volume",
                  "longest_wait",
                  "usual_wait",
                  "fee_histogram",
                  "recently_taken"
                ]
              }
            ]
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      },
      "BoincStatusDocument": {
        "type": "object",
        "properties": {
          "jsonapi": {
            "$ref": "#/components/schemas/JsonApi"
          },
          "data": {
            "$ref": "#/components/schemas/BoincStatus"
          },
          "links": {
            "$ref": "#/components/schemas/Links"
          },
          "meta": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MetaBase"
              },
              {
                "type": "object",
                "properties": {
                  "projects": {
                    "type": "integer",
                    "description": "How many projects are in the answer."
                  }
                },
                "required": [
                  "projects"
                ]
              }
            ]
          }
        },
        "required": [
          "jsonapi",
          "data",
          "links",
          "meta"
        ]
      }
    }
  }
}
