{
  "openapi": "3.1.1",
  "info": {
    "title": "Chartroom API",
    "version": "1.0.0",
    "summary": "Deterministic tools for people and AI agents.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://chartroom.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/tools": {
      "get": {
        "operationId": "listTools",
        "summary": "Catalog of all tools",
        "responses": {
          "200": {
            "description": "Tool list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/{id}": {
      "get": {
        "operationId": "getTool",
        "summary": "Definition of one tool",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "csv-excel-chart-studio",
                "time-series-explorer",
                "geo-data-visualizer",
                "diagram-flowchart-maker",
                "embeddable-chart-builder",
                "probability-statistics-studio",
                "datafresh",
                "unitproof",
                "localekit",
                "energy-grid-explorer",
                "public-spending-explorer",
                "software-adoption-explorer",
                "internet-archive-change-explorer",
                "satellite-change-explorer"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/csv-excel-chart-studio/calculate": {
      "post": {
        "operationId": "calculateCsvExcelChartStudio",
        "summary": "Turn CSV, TSV or Excel data into line, bar, pie, scatter or histogram charts with SVG/PNG export.",
        "description": "Upload a CSV, TSV or XLSX file (up to 20 MB) or paste a table. The studio detects numbers, dates and categories, lets you pick the chart type, X/Y columns, a grouping column, aggregation (sum, average, count …), sorting and top-N, and returns an accessible SVG chart with SVG and PNG downloads plus the data table behind it.\n\nMethodology:\n- The upload is identified by its content: XLSX (a ZIP container) is unpacked with a built-in reader (shared strings, number formats for dates, cached formula values of the chosen sheet); everything else is read as UTF-8 text (Windows-1252 as fallback) and split with the delimiter that gives the most consistent column count.\n- Each column is classified as number, date or text when at least 90 % of its non-empty cells parse that way. Numbers may use thousands separators, a decimal comma (detected per column), currency signs, percent signs and (123) for negatives. Day/month order of dates like 03/04/2026 is detected per column; when the data never disambiguates it, day-first is assumed and stated.\n- For bar, stacked, pie, line and area charts, rows with the same X value are combined with the chosen aggregation (automatic = sum). With a group column, the first Y column is split into one series per group value (at most 8; the rest become \"Other\"). Top N keeps the categories with the largest totals.\n- Charts are drawn by the site’s own SVG library: colour-blind-safe Okabe–Ito colours plus dash patterns or marker shapes, a text alternative, and the data table below. PNG images are rendered from the same SVG at 2× resolution with ImageMagick.\n- Very large inputs are reduced for drawing only: lines with more than 2,000 points show bucket averages, scatter plots with more than 5,000 points show every n-th point; the table and CSV keep all values.\n\nCheck that the detected column types and the aggregation match your data before publishing a chart.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "csv_excel_chart_studio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CsvExcelChartStudioInput"
              },
              "examples": {
                "example1": {
                  "summary": "Revenue by month, stacked by region",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "stacked",
                    "x": "Month",
                    "y": "Revenue",
                    "group": "Region",
                    "png": false
                  }
                },
                "example2": {
                  "summary": "Monthly orders as a line (repeated months summed)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "line",
                    "x": "Month",
                    "y": "Orders",
                    "png": true
                  }
                },
                "example3": {
                  "summary": "Share of revenue by region (pie)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "pie",
                    "x": "Region",
                    "y": "Revenue",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsvExcelChartStudioResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/time-series-explorer/calculate": {
      "post": {
        "operationId": "calculateTimeSeriesExplorer",
        "summary": "Resample, smooth and decompose date/value data: trend, R², seasonality, YoY change and anomalies.",
        "description": "Upload or paste dated values (one or several series, wide or long format). The explorer resamples to days, weeks, months, quarters or years, adds moving averages (simple, exponential or centred), fits a linear trend with R², estimates weekday or month-of-year seasonality, computes period and year-over-year change and flags anomalies by z-score or IQR, with charts, tables and a CSV export.\n\nMethodology:\n- Dates are parsed per column (ISO, European and US formats, month names, YYYY-MM, YYYY-Qn); rows without a date or number are skipped and counted. Values with the same timestamp are combined with the chosen method.\n- Resampling groups values into calendar periods in UTC (weeks start on Monday, ISO 8601) and combines them by average, sum, first, last, minimum, maximum or median. Empty periods are left out rather than filled.\n- Moving averages: simple = mean of the last w points; exponential = α·value + (1−α)·previous with α = 2/(w+1); centred = mean of w points around each point (2×w for even windows, as in classical decomposition).\n- Trend: ordinary least squares of value on time in days; R² is the share of variance the straight line explains. The slope is also shown per year (× 365.25).\n- Seasonality (an \"STL-lite\" classical additive decomposition): trend = centred moving average over one period (7 weekdays, 12 months or 4 quarters); seasonal index = average detrended value per weekday/month/quarter, shifted to sum to zero; strength = 1 − var(remainder) / var(detrended), reported once the detrended values cover at least two full periods. The centred trend loses half a period at each end, so that takes 20 days, 36 months (three years) or 12 quarters of data. With less, the seasonal averages are still shown and a note explains why there is no index or strength. It is a simplification of STL (no LOESS, fixed seasonal pattern).\n- Anomalies are judged on residuals: the decomposition remainder when seasonality is estimated, otherwise the deviation from a centred moving average. z-score flags |z| above the threshold; IQR flags values outside Q1 − k·IQR … Q3 + k·IQR. Anomalies are statistical outliers, not proof of errors.\n- Year-over-year compares the last point with the point on the same calendar date (± a few days, depending on spacing) one year earlier.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "time_series_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TimeSeriesExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Daily visits: weekday pattern, trend and two anomalies",
                  "value": {
                    "data": "date,visits\n2026-01-05,98\n2026-01-06,104.5\n2026-01-07,109\n2026-01-08,105.5\n2026-01-09,106\n2026-01-10,92.5\n2026-01-11,91\n2026-01-12,105.5\n2026-01-13,107\n2026-01-14,111.5\n2026-01-15,108\n2026-01-16,108.5\n2026-01-17,100\n2026-01-18,93.5\n2026-01-19,108\n2026-01-20,109.5\n2026-01-21,114\n2026-01-22,115.5\n2026-01-23,111\n2026-01-24,102.5\n2026-01-25,96\n2026-01-26,110.5\n2026-01-27,117\n2026-01-28,161.5\n2026-01-29,118\n2026-01-30,113.5\n2026-01-31,105\n2026-02-01,103.5\n2026-02-02,113\n2026-02-03,119.5\n2026-02-04,119\n2026-02-05,120.5\n2026-02-06,121\n2026-02-07,107.5\n2026-02-08,106\n2026-02-09,115.5\n2026-02-10,122\n2026-02-11,126.5\n2026-02-12,123\n2026-02-13,123.5\n2026-02-14,110\n2026-02-15,108.5\n2026-02-16,123\n2026-02-17,124.5\n2026-02-18,129\n2026-02-19,125.5\n2026-02-20,126\n2026-02-21,117.5\n2026-02-22,111\n2026-02-23,125.5\n2026-02-24,127\n2026-02-25,93.5\n2026-02-26,133\n2026-02-27,128.5\n2026-02-28,120\n2026-03-01,113.5\n2026-03-02,128\n2026-03-03,134.5\n2026-03-04,134\n2026-03-05,135.5\n2026-03-06,131\n2026-03-07,122.5\n2026-03-08,121\n2026-03-09,130.5\n2026-03-10,137\n2026-03-11,136.5\n2026-03-12,138\n2026-03-13,138.5\n2026-03-14,125\n2026-03-15,123.5",
                    "smoothing": "sma",
                    "window": 7,
                    "png": false
                  }
                },
                "example2": {
                  "summary": "Two products, 3 years monthly: seasonality and year-over-year",
                  "value": {
                    "data": "month,Product A,Product B\n2024-01,120,80\n2024-02,115,82\n2024-03,130,85\n2024-04,142,90\n2024-05,150,94\n2024-06,170,99\n2024-07,182,101\n2024-08,176,104\n2024-09,150,108\n2024-10,138,110\n2024-11,125,115\n2024-12,160,121\n2025-01,131,124\n2025-02,126,126\n2025-03,143,131\n2025-04,151,133\n2025-05,166,138\n2025-06,188,141\n2025-07,197,147\n2025-08,190,150\n2025-09,163,152\n2025-10,150,158\n2025-11,139,161\n2025-12,176,169\n2026-01,139,172\n2026-02,136,174\n2026-03,150,179\n2026-04,161,182\n2026-05,174,186\n2026-06,201,190\n2026-07,206,195\n2026-08,203,198\n2026-09,171,201\n2026-10,160,206\n2026-11,145,209\n2026-12,190,215",
                    "smoothing": "centred",
                    "window": 12,
                    "seasonality": "month",
                    "anomalyMethod": "iqr",
                    "png": true
                  }
                },
                "example3": {
                  "summary": "Daily data resampled to weekly sums",
                  "value": {
                    "data": "date,visits\n2026-01-05,98\n2026-01-06,104.5\n2026-01-07,109\n2026-01-08,105.5\n2026-01-09,106\n2026-01-10,92.5\n2026-01-11,91\n2026-01-12,105.5\n2026-01-13,107\n2026-01-14,111.5\n2026-01-15,108\n2026-01-16,108.5\n2026-01-17,100\n2026-01-18,93.5\n2026-01-19,108\n2026-01-20,109.5\n2026-01-21,114\n2026-01-22,115.5\n2026-01-23,111\n2026-01-24,102.5\n2026-01-25,96\n2026-01-26,110.5\n2026-01-27,117\n2026-01-28,161.5\n2026-01-29,118\n2026-01-30,113.5\n2026-01-31,105\n2026-02-01,103.5\n2026-02-02,113\n2026-02-03,119.5\n2026-02-04,119\n2026-02-05,120.5\n2026-02-06,121\n2026-02-07,107.5\n2026-02-08,106\n2026-02-09,115.5\n2026-02-10,122\n2026-02-11,126.5\n2026-02-12,123\n2026-02-13,123.5\n2026-02-14,110\n2026-02-15,108.5\n2026-02-16,123\n2026-02-17,124.5\n2026-02-18,129\n2026-02-19,125.5\n2026-02-20,126\n2026-02-21,117.5\n2026-02-22,111\n2026-02-23,125.5\n2026-02-24,127\n2026-02-25,93.5\n2026-02-26,133\n2026-02-27,128.5\n2026-02-28,120\n2026-03-01,113.5\n2026-03-02,128\n2026-03-03,134.5\n2026-03-04,134\n2026-03-05,135.5\n2026-03-06,131\n2026-03-07,122.5\n2026-03-08,121\n2026-03-09,130.5\n2026-03-10,137\n2026-03-11,136.5\n2026-03-12,138\n2026-03-13,138.5\n2026-03-14,125\n2026-03-15,123.5",
                    "resample": "week",
                    "resampleAgg": "sum",
                    "smoothing": "ema",
                    "window": 3,
                    "seasonality": "none",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimeSeriesExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/geo-data-visualizer/calculate": {
      "post": {
        "operationId": "calculateGeoDataVisualizer",
        "summary": "Map CSV coordinates or GeoJSON as points, proportional circles, hex-bin heatmaps or choropleths.",
        "description": "Upload a CSV/XLSX with latitude/longitude (plus optional value and label) or a country-code column, or a GeoJSON file with points, lines and polygons. Get an SVG map over bundled Natural Earth country outlines in the Equal Earth, Mercator or equirectangular projection – as points, proportional symbols, a hexagonal-bin heatmap or a choropleth – zoomed to your data, with SVG/PNG downloads.\n\nMethodology:\n- Input detection: text starting with \"{\" is read as GeoJSON (FeatureCollection, Feature or bare geometry; Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection). Anything else is a table (CSV/TSV/XLSX); lat/lon and country columns are found by name unless you name them.\n- Coordinates must be WGS 84 decimal degrees (longitude −180…180, latitude −90…90); rows outside the range or without numbers are skipped and counted.\n- Projections: equirectangular x = λ, y = φ; Mercator y = ln tan(π/4 + φ/2) (clipped at ±85°); Equal Earth (Šavrič, Patterson & Jenny 2018), an equal-area projection suitable for world maps and for comparing densities.\n- Auto zoom fits the bounding box of the data plus 20 % margin (at least 4° × 3°); views wider than 300° of longitude show the whole world.\n- Hex-bin heatmap: points are projected, assigned to pointy-top hexagons of the chosen pixel size (cube-coordinate rounding) and coloured by count, or by the sum of the value column, on a colour-blind-safe viridis-like ramp.\n- Proportional circles: circle area is proportional to |value| (radius ∝ √value, largest 26 px); larger circles are drawn first so small ones stay visible. Choropleth: country codes/names are matched to the bundled outlines and shaded in up to five quantile classes; unmatched entries are listed.\n- Country outlines are Natural Earth 1:110m (public domain): small countries and islands such as Singapore, Malta or Andorra are not part of this scale and cannot be shaded. Borders follow Natural Earth’s de facto conventions and are not a statement on disputed territories.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "geo_data_visualizer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GeoDataVisualizerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Offices as proportional circles (staff, example data)",
                  "value": {
                    "data": "office,lat,lon,staff\nTokyo,35.68,139.69,42\nDelhi,28.61,77.21,18\nShanghai,31.23,121.47,25\nSão Paulo,-23.55,-46.63,12\nMexico City,19.43,-99.13,9\nCairo,30.04,31.24,6\nMumbai,19.08,72.88,21\nNairobi,-1.29,36.82,7\nNew York,40.71,-74.01,55\nLagos,6.52,3.38,8\nParis,48.86,2.35,31\nLondon,51.51,-0.13,47\nBerlin,52.52,13.40,26\nToronto,43.65,-79.38,14\nSydney,-33.87,151.21,11",
                    "mode": "proportional",
                    "valueColumn": "staff",
                    "labelColumn": "office",
                    "zoom": "world",
                    "title": "Staff per office (example data)"
                  }
                },
                "example2": {
                  "summary": "Choropleth by ISO code or country name",
                  "value": {
                    "data": "country,customers\nUS,420\nDE,310\nFR,180\nGB,220\nES,95\nIT,120\nNL,85\nPL,60\nSE,45\nBR,70\nMX,40\nCA,110\nJP,130\nIN,75\nAU,65\nZA,20\nKE,12\nNorway,30\nCzechia,25\nPRT,33",
                    "mode": "choropleth",
                    "title": "Customers by country (example data)",
                    "png": false
                  }
                },
                "example3": {
                  "summary": "GeoJSON points, a route and an area (Mercator)",
                  "value": {
                    "data": "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"name\":\"Lisbon\"},\"geometry\":{\"type\":\"Point\",\"coordinates\":[-9.14,38.72]}},{\"type\":\"Feature\",\"properties\":{\"name\":\"Madrid\"},\"geometry\":{\"type\":\"Point\",\"coordinates\":[-3.7,40.42]}},{\"type\":\"Feature\",\"properties\":{\"name\":\"Barcelona\"},\"geometry\":{\"type\":\"Point\",\"coordinates\":[2.17,41.39]}},{\"type\":\"Feature\",\"properties\":{\"name\":\"Route\"},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[-9.14,38.72],[-3.7,40.42],[2.17,41.39]]}},{\"type\":\"Feature\",\"properties\":{\"name\":\"Study area\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-6,37],[-2,37],[-2,39.5],[-6,39.5],[-6,37]]]}}]}",
                    "projection": "mercator",
                    "png": false
                  }
                },
                "example4": {
                  "summary": "Hex-bin density of the same offices",
                  "value": {
                    "data": "office,lat,lon,staff\nTokyo,35.68,139.69,42\nDelhi,28.61,77.21,18\nShanghai,31.23,121.47,25\nSão Paulo,-23.55,-46.63,12\nMexico City,19.43,-99.13,9\nCairo,30.04,31.24,6\nMumbai,19.08,72.88,21\nNairobi,-1.29,36.82,7\nNew York,40.71,-74.01,55\nLagos,6.52,3.38,8\nParis,48.86,2.35,31\nLondon,51.51,-0.13,47\nBerlin,52.52,13.40,26\nToronto,43.65,-79.38,14\nSydney,-33.87,151.21,11",
                    "mode": "hexbin",
                    "hexRadius": 20,
                    "zoom": "world",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeoDataVisualizerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/diagram-flowchart-maker/calculate": {
      "post": {
        "operationId": "calculateDiagramFlowchartMaker",
        "summary": "Write flowcharts, sequence diagrams and mind maps as text and get a laid-out SVG/PNG diagram.",
        "description": "Type a diagram in a Mermaid-like text syntax – flowcharts (top-down or left-right, node shapes, labelled arrows), sequence diagrams (participants, messages, notes, loop/alt blocks) or indented mind maps – and get an automatically laid-out, accessible SVG with SVG/PNG downloads. Syntax errors are reported with line numbers.\n\nMethodology:\n- The text is parsed line by line; every error is reported with its line (and column for flowcharts). Supported: flowchart/graph TD|TB|BT|LR|RL with shapes [rect] (round) ([stadium]) [[subroutine]] [(database)] ((circle)) {diamond} {{hexagon}} [/parallelogram/] [/trapezoid\\] >flag], arrows --> --- -.-> ==> <-->, labels -->|text| or -- text -->, chains A --> B --> C and groups A & B --> C; sequenceDiagram with participant/actor (… as Alias), ->> -->> -> --> -x --x -) --), Note left of/right of/over, loop/alt/else/opt/par/critical/break … end, autonumber; mindmap with indentation and the usual node shapes.\n- Flowcharts are laid out with a layered (Sugiyama-style) algorithm: cycles are broken by reversing DFS back edges; nodes get the longest-path layer (edges with labels span two layers so the label gets its own slot); long edges get dummy nodes; crossings are reduced with 24 alternating barycentre sweeps plus adjacent swaps, keeping the best ordering; positions are assigned by order-preserving least squares (isotonic regression) toward the neighbours, which keeps long edges straight.\n- Sequence diagrams place participants in order of appearance, widen gaps to fit message texts and stack messages, notes and blocks top-down. Mind maps are drawn as a two-sided tree, balancing first-level branches by their number of leaves.\n- Styling statements (style, classDef, class, linkStyle, click) and subgraph frames are accepted but not drawn; they are listed as ignored lines. The output is plain SVG (no scripts, no external references) that passes the site’s strict sanitiser; arrowheads are drawn as shapes so PNG export keeps them.\n\nA Mermaid-like subset, not full Mermaid compatibility: complex features (subgraph frames, styling, class diagrams, Gantt charts) are not supported.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "diagram_flowchart_maker",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiagramFlowchartMakerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Order flowchart (top-down, shapes, labelled edges, a loop)",
                  "value": {
                    "source": "flowchart TD\n  start([Order received]) --> pay{Paid?}\n  pay -->|Yes| pick[Pick items]\n  pay -->|No| remind[/Send reminder/]\n  remind --> pay\n  pick --> stock{In stock?}\n  stock -->|Yes| ship[[Ship parcel]]\n  stock -->|No| back[(Backorder list)]\n  back -.-> pick\n  ship --> done((Done))",
                    "title": "Order handling"
                  }
                },
                "example2": {
                  "summary": "Login sequence diagram",
                  "value": {
                    "source": "sequenceDiagram\n  autonumber\n  actor U as User\n  participant B as Browser\n  participant S as Server\n  U->>B: Click \"Log in\"\n  B->>S: POST /login\n  alt credentials valid\n    S-->>B: 303 + session cookie\n    B-->>U: Dashboard\n  else invalid\n    S-->>B: 401 error\n    Note right of B: show message\n  end",
                    "title": "Login",
                    "png": false
                  }
                },
                "example3": {
                  "summary": "Trip mind map",
                  "value": {
                    "source": "mindmap\n  root((Trip to Lisbon))\n    Travel\n      Flights\n      Airport transfer\n    Stay\n      Hotel near Baixa\n    See\n      Belém tower\n      Tram 28\n      Sintra day trip\n    Eat\n      Pastéis de nata",
                    "png": false
                  }
                },
                "example4": {
                  "summary": "Left-to-right pipeline",
                  "value": {
                    "source": "flowchart LR\n  A[Commit] --> B[Build] --> C{Tests pass?}\n  C -- yes --> D[Deploy]\n  C -- no --> E[Notify] --> A",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiagramFlowchartMakerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/embeddable-chart-builder/calculate": {
      "post": {
        "operationId": "calculateEmbeddableChartBuilder",
        "summary": "Make a self-contained chart to embed anywhere: inline SVG, standalone HTML, accessible snippet.",
        "description": "Paste a small table and get a chart you can host yourself: inline SVG markup, a <figure> snippet with an accessible data-table fallback, a standalone .svg file and a standalone .html file with no external scripts (optionally with a tiny inline script for tooltips and keyboard focus).\n\nMethodology:\n- The data is parsed like the CSV/Excel Chart Studio (delimiter, number formats and dates detected automatically) and drawn with the site’s deterministic SVG chart library: Okabe–Ito colours, dash patterns, a <title>/<desc> text alternative and role=\"img\".\n- The SVG is passed through a strict allow-list sanitiser, so the markup contains no scripts, event handlers, external links or style attributes and can be pasted into most CMSs.\n- The <figure> snippet keeps the data accessible: the SVG is labelled by its title and description, the caption carries the source line, and a <details> element holds the full data table as a fallback for screen readers, text browsers and copy-paste.\n- The standalone HTML file contains everything inline (a few lines of CSS; with the interactive option a ~1 KB vanilla script that makes data marks focusable and shows their values). It loads nothing from other servers.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "embeddable_chart_builder",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmbeddableChartBuilderInput"
              },
              "examples": {
                "example1": {
                  "summary": "Grouped bars with a source line",
                  "value": {
                    "data": "Fruit,2025,2026\nApples,12,15\nPears,9,11\nPlums,4,7",
                    "chartType": "bar",
                    "title": "Fruit sold (tonnes)",
                    "yLabel": "tonnes",
                    "sourceNote": "Source: example data"
                  }
                },
                "example2": {
                  "summary": "Interactive donut",
                  "value": {
                    "data": "Channel,Visits\nSearch,5200\nDirect,2100\nSocial,1300\nEmail,600",
                    "chartType": "donut",
                    "title": "Visits by channel",
                    "interactive": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbeddableChartBuilderResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/probability-statistics-studio/calculate": {
      "post": {
        "operationId": "calculateProbabilityStatisticsStudio",
        "summary": "Distributions, descriptive stats, confidence intervals and t, chi-square and z tests with p-values.",
        "description": "Probabilities, densities and quantiles for the normal, t, chi-square, F, binomial, Poisson, exponential and uniform distributions with plots; descriptive statistics of a data set; confidence intervals for a mean or a proportion; and one-sample, two-sample and paired t-tests, chi-square goodness-of-fit and independence tests and z-tests for proportions, each with a p-value and a plain-language interpretation.\n\nMethodology:\n- Special functions are implemented directly: log-gamma (Lanczos), the regularised incomplete gamma function (series and continued fraction) and the regularised incomplete beta function (continued fraction). The normal CDF uses erfc via the incomplete gamma function; its quantile uses Acklam’s approximation refined by Halley steps.\n- CDFs: t and F via the incomplete beta function, chi-square and Poisson via the incomplete gamma function, binomial via the incomplete beta function. Quantiles of continuous distributions are found by bisection with a Newton polish; discrete quantiles are the smallest k with P(X ≤ k) ≥ p.\n- Values are checked in the test suite against published tables (e.g. Φ(1.96) = 0.975002, t₀.₉₇₅ with 10 df = 2.228139, χ²₀.₉₅ with 5 df = 11.0705, F₀.₉₅(5, 10) = 3.3258).\n- Descriptive statistics use the sample (n − 1) variance, quartiles by linear interpolation (the R/Excel default), the adjusted skewness and excess kurtosis, and the 1.5 × IQR outlier rule.\n- Tests: one-sample, Welch or pooled two-sample and paired t-tests; chi-square goodness-of-fit and independence (without continuity correction); one- and two-proportion z-tests (pooled for the test, unpooled for the interval). The interpretation compares p with α = 1 − confidence.\n\nA p-value is not the probability that H0 is true, and “not significant” does not prove H0. Check the assumptions listed with each test.",
        "tags": [
          "math"
        ],
        "x-mcp-tool": "probability_statistics_studio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProbabilityStatisticsStudioInput"
              },
              "examples": {
                "example1": {
                  "summary": "Normal: P(Z ≤ 1.96) and the 97.5% quantile",
                  "value": {
                    "analysis": "distribution",
                    "distribution": "normal",
                    "param1": 0,
                    "param2": 1,
                    "x": 1.96,
                    "probability": 0.975
                  }
                },
                "example2": {
                  "summary": "Binomial: exactly / at most 5 heads in 10 flips",
                  "value": {
                    "analysis": "distribution",
                    "distribution": "binomial",
                    "param1": 10,
                    "param2": 0.5,
                    "x": 5,
                    "x2": 7
                  }
                },
                "example3": {
                  "summary": "Descriptive statistics",
                  "value": {
                    "analysis": "describe",
                    "data": "12, 15, 11, 18, 14, 15, 22, 13, 16, 15, 40"
                  }
                },
                "example4": {
                  "summary": "One-sample t-test",
                  "value": {
                    "analysis": "t-one",
                    "data": "5.1 4.9 5.6 5.8 6.0 5.3 5.5 5.7",
                    "mu0": 5
                  }
                },
                "example5": {
                  "summary": "Welch two-sample t-test",
                  "value": {
                    "analysis": "t-two",
                    "data": "20.1 22.3 19.8 21.5 23.0 20.7",
                    "data2": "18.2 19.5 17.9 18.8 20.1 19.0 18.4"
                  }
                },
                "example6": {
                  "summary": "Chi-square test of independence",
                  "value": {
                    "analysis": "chisq-indep",
                    "data": "30 10\n20 40"
                  }
                },
                "example7": {
                  "summary": "Confidence interval for a proportion",
                  "value": {
                    "analysis": "ci-proportion",
                    "successes": 42,
                    "trials": 120,
                    "confidence": 0.95
                  }
                },
                "example8": {
                  "summary": "Two-proportion z-test",
                  "value": {
                    "analysis": "z-two-prop",
                    "successes": 45,
                    "trials": 100,
                    "successes2": 30,
                    "trials2": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProbabilityStatisticsStudioResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/datafresh/calculate": {
      "post": {
        "operationId": "calculateDatafresh",
        "summary": "Is this dataset or API still fresh? Newest record, update cadence check and schema drift.",
        "description": "Point DataFresh at a public JSON or CSV endpoint (or paste the content). It finds the records, infers a schema with a stable fingerprint, finds the newest timestamp, compares its age with the update cadence you expect, and reports schema changes since the last check – as one of: healthy, stale, schema_changed, unavailable, no_timestamp.\n\nMethodology:\n- Records: a JSON root array, or the largest array of objects within 3 levels; CSV uses the first row as header (comma or semicolon).\n- Schema: every field (one nesting level flattened as parent.child) with its observed value types and presence ratio; the fingerprint is the first 16 hex chars of SHA-256 over sorted \"field:types\" lines.\n- Timestamp: the field you name, otherwise the first field named like updated/modified/timestamp/date/time/year where ≥ 80% of values parse as dates (ISO 8601, epoch s/ms, YYYY, YYYY-Qn, DD.MM.YYYY). Years count as 31 Dec, quarters as their last day.\n- Freshness: age = now − newest timestamp. healthy if age ≤ 1.5 × expected interval, otherwise stale. Without a timestamp field the HTTP Last-Modified header is used if present.\n- Drift: compared with the previous schema you paste or, with \"remember\", the schema stored for the same URL (key = SHA-256 of the URL). Any added/removed field or type change → schema_changed (takes precedence over healthy, not over unavailable).",
        "tags": [
          "developer"
        ],
        "x-mcp-tool": "datafresh",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DatafreshInput"
              },
              "examples": {
                "example1": {
                  "summary": "Stale daily feed",
                  "value": {
                    "content": "{\"meta\":{\"source\":\"example\"},\"items\":[{\"id\":1,\"value\":3.2,\"updated_at\":\"2026-10-01T06:00:00Z\"},{\"id\":2,\"value\":4.1,\"updated_at\":\"2026-10-03T06:00:00Z\"}]}",
                    "expectedCadenceHours": 24
                  }
                },
                "example2": {
                  "summary": "Yearly CSV with schema change",
                  "value": {
                    "content": "country;year;value\nDE;2024;2.5\nFR;2025;2.1",
                    "expectedCadenceHours": 8760,
                    "previousSchema": "{\"country\":{\"types\":[\"string\"],\"presence\":1},\"year\":{\"types\":[\"number\"],\"presence\":1},\"value\":{\"types\":[\"number\"],\"presence\":1},\"unit\":{\"types\":[\"string\"],\"presence\":1}}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatafreshResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/unitproof/calculate": {
      "post": {
        "operationId": "calculateUnitproof",
        "summary": "Unit maths you can audit: dimension check, exact factors and a full derivation tree.",
        "description": "Type an expression such as \"3.5 km/h * 2 h to m\", \"72 F to C\" or \"1500 W * 3 h to kWh\". UnitProof parses it, checks dimensions over the SI base units, applies exact NIST/SI conversion factors and shows every step as a derivation tree, including correct absolute-vs-difference temperature handling.\n\nMethodology:\n- A tokenizer and recursive-descent parser read numbers (incl. scientific notation), units with SI prefixes (q…Q, incl. µ/u) and binary prefixes (Ki…Ei for bit/B), ^ powers (also ² ³ and \"m2\"), × ÷ + − and parentheses. Juxtaposition (\"2 h\", \"kg m\") binds tighter than explicit * and /, so \"60 km / 2 h\" = 30 km/h.\n- Every quantity is a value in coherent SI units plus a dimension vector over m, kg, s, A, K, mol, cd and bit; ISO 4217 currency codes are carried as opaque dimensions (never converted). The table has 144 named units.\n- Multiplication adds dimension exponents, division subtracts them, powers scale them; addition, subtraction and conversion require identical dimensions, otherwise the calculation stops with an explanation of the mismatch.\n- Temperatures: \"72 F\" or \"-40 C\" (a number directly followed by °C/°F) is an absolute temperature converted with its offset; absolute − absolute gives a difference; absolute ± difference stays absolute; multiplying, dividing or powering °C/°F is refused as ambiguous (use K or deltaC/deltaF). Converting a difference to °C/°F applies only the scale factor.\n- Exact factors follow the SI Brochure (9th ed.) and NIST SP 811 Appendix B (international foot/pound, US liquid gallon = 231 in³, Btu_IT, thermochemical calorie, etc.); conventional or measured values (mmHg, inHg, dalton) are flagged as not exact.\n- The derivation graph lists literals, unit definitions (with factor), operations and the final conversion; values are IEEE-754 doubles, shown unrounded and rounded to the requested significant digits.",
        "tags": [
          "developer"
        ],
        "x-mcp-tool": "unitproof",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnitproofInput"
              },
              "examples": {
                "example1": {
                  "summary": "Distance: 3.5 km/h for 2 h in metres",
                  "value": {
                    "expression": "3.5 km/h * 2 h to m"
                  }
                },
                "example2": {
                  "summary": "Temperature: 72 °F in °C",
                  "value": {
                    "expression": "72 F to C"
                  }
                },
                "example3": {
                  "summary": "Energy: 1500 W for 3 h in kWh",
                  "value": {
                    "expression": "1500 W * 3 h to kWh"
                  }
                },
                "example4": {
                  "summary": "Force: 75 kg at 9.81 m/s²",
                  "value": {
                    "expression": "9.81 m/s^2 * 75 kg to N"
                  }
                },
                "example5": {
                  "summary": "Mixed lengths: 1 mi + 200 m in km",
                  "value": {
                    "expression": "1 mi + 200 m to km",
                    "significantDigits": 4
                  }
                },
                "example6": {
                  "summary": "Opaque currency: 5 USD/kg × 2.5 kg",
                  "value": {
                    "expression": "5 USD/kg * 2.5 kg"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnitproofResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/localekit/calculate": {
      "post": {
        "operationId": "calculateLocalekit",
        "summary": "Address form fields, postal-code regex, calling code and date formats for any country.",
        "description": "Pick a country to get its address form as an ordered field schema (with required flags and local labels like PIN code or Prefecture), the postal-code pattern with examples and validation, the calling code with basic E.164 normalisation, and date/number formatting examples for the country’s likely locale.\n\nMethodology:\n- Address rules come from Google’s Address Data Service (the libaddressinput metadata used by Chromium and Android): fmt gives field order and line breaks (%N name, %O organisation, %A street, %D dependent locality, %C city, %S state/province, %Z postal code, %X sorting code), require/upper list required and upper-cased fields; missing keys fall back to the ZZ defaults.\n- Field labels use the country’s zip/state/locality/sublocality name types (e.g. PIN code, Eircode, Prefecture). Tokens not documented in the public metadata (e.g. %T, %F, %L for India) are reported as unmapped rather than guessed.\n- Postal-code validation trims, upper-cases and collapses whitespace, then tests the full string against the anchored data pattern ^(?:zip)$.\n- Phone: calling code, international and national (trunk) prefixes and possible lengths come from libphonenumber’s PhoneNumberMetadata.xml. Normalisation removes punctuation, handles \"+\" or the international prefix, otherwise strips the trunk prefix only if libphonenumber defines one (so Italy keeps its leading 0) and prepends the calling code. This is basic: carrier codes, national-prefix-for-parsing rules and number-type validation are not applied.\n- Locale: the country’s likely locale is derived with Intl.Locale(\"und-CC\").maximize() (CLDR likely subtags) and used with Intl.DateTimeFormat/NumberFormat on the fixed date 2026-12-31 13:45 UTC so day/month order is unambiguous.\n\nAddress and phone metadata change; always accept free-form input as a fallback and never reject an order solely because a postal code or phone number fails a pattern.",
        "tags": [
          "developer"
        ],
        "x-mcp-tool": "localekit",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalekitInput"
              },
              "examples": {
                "example1": {
                  "summary": "Germany: postal code + phone",
                  "value": {
                    "country": "DE",
                    "postalCode": "10115",
                    "phone": "030 901820"
                  }
                },
                "example2": {
                  "summary": "India: PIN code and state field",
                  "value": {
                    "country": "IN",
                    "postalCode": "110001",
                    "phone": "+91 98765 43210"
                  }
                },
                "example3": {
                  "summary": "Japan: big-to-small address order",
                  "value": {
                    "country": "JP",
                    "postalCode": "154-0023"
                  }
                },
                "example4": {
                  "summary": "United Kingdom: invalid postcode",
                  "value": {
                    "country": "GB",
                    "postalCode": "SW1A 1AAA",
                    "phone": "020 7946 0018"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalekitResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/energy-grid-explorer/calculate": {
      "post": {
        "operationId": "calculateEnergyGridExplorer",
        "summary": "Generation mix, load, renewable share, cross-border flows and power prices for European grids.",
        "description": "Pulls public net electricity generation per source, load, cross-border physical flows and day-ahead prices from the Energy-Charts API by Fraunhofer ISE for a country and date range, then computes energy per source, renewable share, peak and minimum load, net imports per neighbour and price statistics. Paste saved Energy-Charts JSON to analyse offline.\n\nMethodology:\n- Live data: GET https://api.energy-charts.info/public_power?country=…&start=…&end=… (net public generation per source in MW, usually 15-minute steps), /cbpf (cross-border physical flows in GW, positive = import) and /price?bzn=… (day-ahead price, EUR/MWh). Dates are local (Central European) calendar days, end inclusive.\n- Energy per source = Σ(MW × step) using the median sampling step; load, residual load, share series, scheduled trading and pumped-storage charging are excluded from generation.\n- Renewable share = renewable energy ÷ total generation, counting hydro run-of-river, reservoir, biomass, geothermal, wind and solar fully and waste at 50 % (biogenic share). This reproduces Energy-Charts' own \"Renewable share of generation\" series, whose plain mean is shown for comparison.\n- Peak / minimum load are the highest and lowest samples of the \"Load\" series with their UTC timestamps; prices report mean, extremes and the number of negative-price intervals.\n- Prices are only requested for bidding zones Energy-Charts publishes under CC BY 4.0 (SMARD.de data: DE-LU, AT, BE, CH, CZ, DK1, FR, HU, IT-North, NL, NO2, PL, SE4, SI); other zones are marked private/internal use by the API terms.\n- Outages: no keyless public outage API was verified (ENTSO-E Transparency requires a registered security token), so outage data is not provided.",
        "tags": [
          "public-data"
        ],
        "x-mcp-tool": "energy_grid_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnergyGridExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Germany, 1 Oct 2026 midday (pasted Energy-Charts JSON)",
                  "value": {
                    "source": "pasted",
                    "country": "de",
                    "pastedPower": "{\"unix_seconds\":[1790848800,1790849700,1790850600,1790851500,1790852400,1790853300,1790854200,1790855100,1790856000,1790856900,1790857800,1790858700,1790859600],\"production_types\":[{\"name\":\"Hydro pumped storage consumption\",\"data\":[-1589.9,-2220.2,-2488.5,-3176.3,-3006.0,-2738.7,-3014.6,-2900.1,-2477.4,-1063.5,-530.4,-436.8,-732.1]},{\"name\":\"Cross border electricity trading\",\"data\":[2048.2,1843.7,2148.2,2703.1,3983.9,4178.4,4904.4,5045.5,5272.9,5347.4,5075.1,5226.4,7183.6]},{\"name\":\"Hydro Run-of-River\",\"data\":[1122.5,1111.9,1109.8,1113.8,1111.1,1118.2,1104.1,1101.1,1102.8,1097.9,1078.9,1060.1,1056.6]},{\"name\":\"Biomass\",\"data\":[3721.5,3715.5,3698.3,3688.7,3663.6,3667.1,3659.5,3660.0,3653.3,3659.2,3658.9,3668.0,3667.5]},{\"name\":\"Fossil brown coal / lignite\",\"data\":[8913.6,8918.4,8918.4,8930.0,8926.5,8968.8,9014.4,9023.2,9052.5,9012.6,9053.1,9093.8,9086.2]},{\"name\":\"Fossil hard coal\",\"data\":[3481.9,3383.1,3203.2,2974.7,2894.4,2888.0,2931.5,2946.8,3034.8,3173.1,3322.9,3343.2,3170.0]},{\"name\":\"Fossil oil\",\"data\":[230.7,230.8,230.9,230.3,230.2,230.0,230.1,230.7,232.0,231.7,231.2,222.9,119.1]},{\"name\":\"Fossil coal-derived gas\",\"data\":[347.7,347.4,338.8,342.7,340.4,333.4,332.6,388.4,423.9,426.2,430.7,435.8,440.1]},{\"name\":\"Fossil gas\",\"data\":[5622.5,5602.2,5592.2,5562.9,5511.9,5499.8,5456.2,5462.9,5560.2,5708.7,5675.1,5708.7,5645.4]},{\"name\":\"Geothermal\",\"data\":[13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2,13.2]},{\"name\":\"Hydro water reservoir\",\"data\":[4.7,3.5,3.8,4.8,4.7,5.1,5.3,7.4,6.9,6.7,4.4,5.0,4.7]},{\"name\":\"Hydro pumped storage\",\"data\":[11.8,9.5,9.5,9.5,9.6,9.9,14.7,58.9,130.9,34.6,153.7,94.6,38.2]},{\"name\":\"Others\",\"data\":[132.7,132.4,132.4,132.4,132.4,132.4,132.4,132.4,132.4,132.4,132.7,132.4,132.4]},{\"name\":\"Waste\",\"data\":[1267.3,1269.8,1271.7,1275.2,1275.0,1270.6,1270.0,1267.8,1268.1,1263.0,1261.6,1264.2,1261.1]},{\"name\":\"Wind offshore\",\"data\":[2587.1,2725.8,2791.7,2695.3,2342.7,2244.7,2341.6,2251.5,2478.8,2584.7,2668.5,2657.9,3229.2]},{\"name\":\"Wind onshore\",\"data\":[5458.9,5368.5,5325.4,5267.3,5132.2,4930.4,4911.5,4796.6,4735.9,4691.6,4583.5,4598.6,4485.3]},{\"name\":\"Solar\",\"data\":[26884.6,27149.8,27194.6,26952.3,26494.0,25820.4,24943.3,24151.8,23060.4,22124.0,20922.8,19650.5,18329.3]},{\"name\":\"Load\",\"data\":[64505.5,64119.0,63860.0,63954.7,64183.1,63568.0,63056.5,63155.2,62686.6,63541.9,62723.3,61936.9,62818.8]},{\"name\":\"Residual load\",\"data\":[29574.8,28874.8,28548.3,29039.8,30214.1,30572.6,30860.1,31955.3,32411.5,34141.7,34548.5,35030.0,36775.0]},{\"name\":\"Renewable share of load\",\"data\":[62.6,63.5,63.8,63.1,61.3,60.4,59.6,57.9,56.9,54.7,53.5,52.1,50.0]},{\"name\":\"Renewable share of generation\",\"data\":[67.6,67.8,68.1,68.2,67.8,67.2,66.7,66.0,65.1,64.2,63.2,62.2,62.0]}],\"deprecated\":false}",
                    "pastedPrice": "{\"license_info\":\"CC BY 4.0 (creativecommons.org/licenses/by/4.0) from Bundesnetzagentur | SMARD.de\",\"unix_seconds\":[1790848800,1790849700,1790850600,1790851500,1790852400,1790853300,1790854200,1790855100,1790856000,1790856900,1790857800,1790858700,1790859600],\"price\":[160.89,164.01,160.45,163.41,153.31,152.45,151.37,150.96,152.14,147.09,150.64,151.47,150.03],\"unit\":\"EUR / MWh\",\"deprecated\":false}",
                    "pastedFlows": "{\"unix_seconds\":[1790848800,1790849700,1790850600,1790851500,1790852400,1790853300,1790854200,1790855100,1790856000,1790856900,1790857800,1790858700,1790859600],\"countries\":[{\"name\":\"Austria\",\"data\":[-0.936,-1.08,-1.037,-0.885,-0.44,-0.402,-0.366,-0.332,-0.105,-0.031,-0.002,-0.044,0.012]},{\"name\":\"Belgium\",\"data\":[0.548,0.428,0.228,0.312,-0.094,-0.348,-0.106,-0.366,-0.552,-0.46,-0.654,-0.426,-0.313]},{\"name\":\"Czech Republic\",\"data\":[0.97,0.904,0.968,1.078,1.617,1.753,1.781,1.874,2.088,2.146,2.145,2.353,2.605]},{\"name\":\"Denmark\",\"data\":[2.692,2.751,2.584,2.48,2.429,2.377,2.279,2.298,1.73,1.533,1.123,1.115,2.533]},{\"name\":\"France\",\"data\":[-0.914,-0.901,-0.93,-0.553,-0.579,-0.582,-0.378,-0.292,-0.484,-0.554,-0.529,-0.393,-0.464]},{\"name\":\"Luxembourg\",\"data\":[-0.53,-0.546,-0.512,-0.487,-0.481,-0.461,-0.459,-0.428,-0.412,-0.421,-0.382,-0.386,-0.416]},{\"name\":\"Netherlands\",\"data\":[0.522,0.881,1.218,1.201,1.407,1.709,1.63,1.625,1.951,1.885,2.026,1.96,1.958]},{\"name\":\"Norway\",\"data\":[0.925,0.965,1.006,1.002,0.953,0.874,0.826,0.852,0.819,0.872,1.063,1.191,1.195]},{\"name\":\"Poland\",\"data\":[0.581,0.549,0.648,0.697,1.152,1.286,1.34,1.442,1.599,1.516,1.408,1.644,1.828]},{\"name\":\"Sweden\",\"data\":[0.413,0.414,0.413,0.414,0.421,0.421,0.421,0.422,0.431,0.431,0.431,0.432,0.432]},{\"name\":\"Switzerland\",\"data\":[-1.446,-1.607,-1.417,-1.096,-0.88,-0.981,-0.782,-0.665,-0.975,-0.938,-0.955,-0.933,-0.98]},{\"name\":\"sum\",\"data\":[2.825,2.757,3.17,4.162,5.505,5.646,6.187,6.43,6.089,5.98,5.674,6.512,8.388]}],\"deprecated\":false}",
                    "includePrices": true,
                    "includeFlows": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnergyGridExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/public-spending-explorer/calculate": {
      "post": {
        "operationId": "calculatePublicSpendingExplorer",
        "summary": "Search government contracts and grants: who pays whom, totals per agency and vendor.",
        "description": "Searches US federal awards on USAspending.gov (contracts, IDVs, grants, other assistance) or EU contract award notices on TED, then totals the results per agency/buyer and per recipient and draws the agency → recipient relationship graph. Paste a saved API response to analyse it offline.\n\nMethodology:\n- USAspending: POST https://api.usaspending.gov/api/v2/search/spending_by_award/ with filters {keywords, recipient_search_text, award_type_codes (one group), time_period}, sorted by \"Award Amount\" descending. \"Award Amount\" is the award's total obligated value, not only the money obligated inside the period.\n- For live USAspending searches the tool also calls spending_by_category/awarding_agency and /recipient (obligations of all matching transactions inside the period) and spending_by_award_count (counts per award group), so the totals are not limited to the listed page.\n- TED: POST https://api.ted.europa.eu/v3/notices/search (anonymous, no key) with an expert query restricted to contract award notices (can-standard, can-social, can-desg, can-tran) and the publication-date range. Multilingual names prefer English. Notice values are not split between several winners and are summed per currency — currencies are never converted.\n- Per-buyer and per-recipient totals sum only the awards listed (top N by amount for USAspending, newest N for TED). The graph links each buyer/agency to its recipients (edge = summed listed value), keeping the largest relationships up to 60 nodes.\n\nAward data is reported by agencies and may be revised; amounts are nominal and unconverted.",
        "tags": [
          "public-data"
        ],
        "x-mcp-tool": "public_spending_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSpendingExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Pasted USAspending response: largest \"wildfire\" grants FY2026",
                  "value": {
                    "source": "pasted",
                    "pastedJson": "{\"limit\":8,\"results\":[{\"Award ID\":\"06D01725\",\"Recipient Name\":\"FLORIDA DEPARTMENT OF ENVIRONMENTAL PROTECTION\",\"Award Amount\":844671000.0,\"Awarding Agency\":\"Environmental Protection Agency\",\"Awarding Sub Agency\":\"Environmental Protection Agency\",\"Start Date\":\"2025-07-01\",\"End Date\":\"2032-06-30\",\"Description\":\"DESCRIPTION:THIS ACTION PROVIDES FUNDING IN THE AMOUNT OF $844,671,000 TO FLORIDA DEPARTME\",\"generated_internal_id\":\"ASST_NON_06D01725_068\"},{\"Award ID\":\"06D01826\",\"Recipient Name\":\"FLORIDA DEPARTMENT OF ENVIRONMENTAL PROTECTION\",\"Award Amount\":806392000.0,\"Awarding Agency\":\"Environmental Protection Agency\",\"Awarding Sub Agency\":\"Environmental Protection Agency\",\"Start Date\":\"2025-07-01\",\"End Date\":\"2032-06-30\",\"Description\":\"DESCRIPTION:THIS ACTION PROVIDES FUNDING IN THE AMOUNT OF $806,392,000 TO THE FLORIDA DEPA\",\"generated_internal_id\":\"ASST_NON_06D01826_068\"},{\"Award ID\":\"06D08726\",\"Recipient Name\":\"GEORGIA ENVIRONMENTAL FINANCE AUTHORITY\",\"Award Amount\":359487000.0,\"Awarding Agency\":\"Environmental Protection Agency\",\"Awarding Sub Agency\":\"Environmental Protection Agency\",\"Start Date\":\"2026-07-01\",\"End Date\":\"2033-06-30\",\"Description\":\"DESCRIPTION:THIS ACTION PROVIDES FUNDING IN THE AMOUNT OF $359,487,000 TO THE GEORGIA ENVI\",\"generated_internal_id\":\"ASST_NON_06D08726_068\"},{\"Award ID\":\"05D51125\",\"Recipient Name\":\"NORTH CAROLINA DEPARTMENT OF ENVIRONMENTAL QUALITY\",\"Award Amount\":253681000.0,\"Awarding Agency\":\"Environmental Protection Agency\",\"Awarding Sub Agency\":\"Environmental Protection Agency\",\"Start Date\":\"2025-07-01\",\"End Date\":\"2032-06-30\",\"Description\":\"DESCRIPTION:THIS ACTION APPROVES AN AWARD IN THE AMOUNT OF $253,681,000 TO PROVIDE FUNDING\",\"generated_internal_id\":\"ASST_NON_05D51125_068\"},{\"Award ID\":\"06D08526\",\"Recipient Name\":\"GEORGIA ENVIRONMENTAL FINANCE AUTHORITY\",\"Award Amount\":124892000.0,\"Awarding Agency\":\"Environmental Protection Agency\",\"Awarding Sub Agency\":\"Environmental Protection Agency\",\"Start Date\":\"2026-07-01\",\"End Date\":\"2033-06-30\",\"Description\":\"DESCRIPTION:THIS ACTION APPROVES FUNDING IN THE AMOUNT OF $124,892,000 TO THE GEORGIA ENVI\",\"generated_internal_id\":\"ASST_NON_06D08526_068\"},{\"Award ID\":\"DEGD0000892\",\"Recipient Name\":\"MIDWEST ENERGY, INC\",\"Award Amount\":96922280.0,\"Awarding Agency\":\"Department of Energy\",\"Awarding Sub Agency\":\"Department of Energy\",\"Start Date\":\"2024-10-01\",\"End Date\":\"2029-09-30\",\"Description\":\"BIPARTISAN INFRASTRUCTURE LAW (BIL) - TRANSMISSION LINE REBUILD/REPLACEMENT FOR WILDFIRE M\",\"generated_internal_id\":\"ASST_NON_DEGD0000892_089\"},{\"Award ID\":\"DEGD0000885\",\"Recipient Name\":\"HOLY CROSS ELECTRIC ASSOCIATION, INC\",\"Award Amount\":96746446.0,\"Awarding Agency\":\"Department of Energy\",\"Awarding Sub Agency\":\"Department of Energy\",\"Start Date\":\"2024-08-21\",\"End Date\":\"2029-08-20\",\"Description\":\"BIPARTISAN INFRASTRUCTURE LAW (BIL) - WILDFIRE ASSESSMENT AND RESILIENCE FOR NETWORKS (WAR\",\"generated_internal_id\":\"ASST_NON_DEGD0000885_089\"},{\"Award ID\":\"DEGD0000884\",\"Recipient Name\":\"XCEL ENERGY SERVICES INC.\",\"Award Amount\":95876582.0,\"Awarding Agency\":\"Department of Energy\",\"Awarding Sub Agency\":\"Department of Energy\",\"Start Date\":\"2024-10-01\",\"End Date\":\"2029-09-30\",\"Description\":\"BIPARTISAN INFRASTRUCTURE LAW (BIL) - WILDFIRE MITIGATION AND EXTREME WEATHER RESILIENCE F\",\"generated_internal_id\":\"ASST_NON_DEGD0000884_089\"}],\"page_metadata\":{\"page\":1,\"hasNext\":true}}",
                    "limit": 50
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicSpendingExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/software-adoption-explorer/calculate": {
      "post": {
        "operationId": "calculateSoftwareAdoptionExplorer",
        "summary": "Open-source usage signals: weekly downloads, growth and version adoption for npm, PyPI, crates.",
        "description": "Fetches public download statistics for an npm, PyPI or crates.io package, aggregates them into weekly totals with 4-week growth and long-run change, shows which versions are actually downloaded (npm last week, crates.io last 90 days) and adds dependent counts from deps.dev. Paste saved API JSON to analyse offline.\n\nMethodology:\n- npm: GET https://api.npmjs.org/downloads/range/last-year/<pkg> (daily downloads) and /versions/<pkg>/last-week (downloads per version over the last 7 days).\n- PyPI: GET https://pypistats.org/api/packages/<pkg>/overall?mirrors=false (daily downloads without mirrors, ~180 days) and /recent. pypistats has no per-version endpoint, so version adoption is not available for PyPI.\n- crates.io: GET https://crates.io/api/v1/crates/<name> (metadata, version ids, all-time downloads) and /crates/<name>/downloads (last 90 days per version plus \"extra\" downloads of older versions); the platform fetcher sends an identifying User-Agent, which crates.io requires.\n- Daily values are summed into Monday-start weeks; weeks with fewer than 7 days of data are marked partial and excluded from growth. Growth = last 4 complete weeks vs the 4 before; long-run change = last 4 vs first 4 complete weeks.\n- Version shares = downloads of a version ÷ all version downloads in the same window; majors group 1.x, 2.x … (0.y releases are grouped per minor). \"Highest stable\" is the largest non-prerelease semver.\n- Dependents: deps.dev v3 package lookup → default version → v3alpha …:dependents, i.e. packages in the same ecosystem whose resolved dependency graph contains exactly that version (direct + indirect). Older versions' dependents are not included.\n- Downloads include CI systems, mirrors and bots; they are a usage signal, not a user count.",
        "tags": [
          "public-data"
        ],
        "x-mcp-tool": "software_adoption_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SoftwareAdoptionExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "left-pad on npm, 1 June – 27 September 2026 (pasted API JSON)",
                  "value": {
                    "ecosystem": "npm",
                    "package": "left-pad",
                    "includeDependents": false,
                    "pastedDownloads": "{\"start\":\"2026-06-01\",\"end\":\"2026-09-27\",\"package\":\"left-pad\",\"downloads\":[{\"downloads\":175000,\"day\":\"2026-06-01\"},{\"downloads\":232816,\"day\":\"2026-06-02\"},{\"downloads\":0,\"day\":\"2026-06-03\"},{\"downloads\":194864,\"day\":\"2026-06-04\"},{\"downloads\":216877,\"day\":\"2026-06-05\"},{\"downloads\":143672,\"day\":\"2026-06-06\"},{\"downloads\":185145,\"day\":\"2026-06-07\"},{\"downloads\":239294,\"day\":\"2026-06-08\"},{\"downloads\":230969,\"day\":\"2026-06-09\"},{\"downloads\":234152,\"day\":\"2026-06-10\"},{\"downloads\":221639,\"day\":\"2026-06-11\"},{\"downloads\":211916,\"day\":\"2026-06-12\"},{\"downloads\":119920,\"day\":\"2026-06-13\"},{\"downloads\":85689,\"day\":\"2026-06-14\"},{\"downloads\":203347,\"day\":\"2026-06-15\"},{\"downloads\":216032,\"day\":\"2026-06-16\"},{\"downloads\":238580,\"day\":\"2026-06-17\"},{\"downloads\":227656,\"day\":\"2026-06-18\"},{\"downloads\":199703,\"day\":\"2026-06-19\"},{\"downloads\":158151,\"day\":\"2026-06-20\"},{\"downloads\":145207,\"day\":\"2026-06-21\"},{\"downloads\":213758,\"day\":\"2026-06-22\"},{\"downloads\":217567,\"day\":\"2026-06-23\"},{\"downloads\":207146,\"day\":\"2026-06-24\"},{\"downloads\":198848,\"day\":\"2026-06-25\"},{\"downloads\":198730,\"day\":\"2026-06-26\"},{\"downloads\":122444,\"day\":\"2026-06-27\"},{\"downloads\":129394,\"day\":\"2026-06-28\"},{\"downloads\":208940,\"day\":\"2026-06-29\"},{\"downloads\":227003,\"day\":\"2026-06-30\"},{\"downloads\":199514,\"day\":\"2026-07-01\"},{\"downloads\":201960,\"day\":\"2026-07-02\"},{\"downloads\":158513,\"day\":\"2026-07-03\"},{\"downloads\":95683,\"day\":\"2026-07-04\"},{\"downloads\":91011,\"day\":\"2026-07-05\"},{\"downloads\":213751,\"day\":\"2026-07-06\"},{\"downloads\":223647,\"day\":\"2026-07-07\"},{\"downloads\":218838,\"day\":\"2026-07-08\"},{\"downloads\":206701,\"day\":\"2026-07-09\"},{\"downloads\":188725,\"day\":\"2026-07-10\"},{\"downloads\":112585,\"day\":\"2026-07-11\"},{\"downloads\":0,\"day\":\"2026-07-12\"},{\"downloads\":197758,\"day\":\"2026-07-13\"},{\"downloads\":219483,\"day\":\"2026-07-14\"},{\"downloads\":204443,\"day\":\"2026-07-15\"},{\"downloads\":220701,\"day\":\"2026-07-16\"},{\"downloads\":203782,\"day\":\"2026-07-17\"},{\"downloads\":135474,\"day\":\"2026-07-18\"},{\"downloads\":133764,\"day\":\"2026-07-19\"},{\"downloads\":209041,\"day\":\"2026-07-20\"},{\"downloads\":222618,\"day\":\"2026-07-21\"},{\"downloads\":232408,\"day\":\"2026-07-22\"},{\"downloads\":246014,\"day\":\"2026-07-23\"},{\"downloads\":232139,\"day\":\"2026-07-24\"},{\"downloads\":133414,\"day\":\"2026-07-25\"},{\"downloads\":140608,\"day\":\"2026-07-26\"},{\"downloads\":222134,\"day\":\"2026-07-27\"},{\"downloads\":337501,\"day\":\"2026-07-28\"},{\"downloads\":244182,\"day\":\"2026-07-29\"},{\"downloads\":212975,\"day\":\"2026-07-30\"},{\"downloads\":196545,\"day\":\"2026-07-31\"},{\"downloads\":138423,\"day\":\"2026-08-01\"},{\"downloads\":128097,\"day\":\"2026-08-02\"},{\"downloads\":230019,\"day\":\"2026-08-03\"},{\"downloads\":241200,\"day\":\"2026-08-04\"},{\"downloads\":237078,\"day\":\"2026-08-05\"},{\"downloads\":225288,\"day\":\"2026-08-06\"},{\"downloads\":217107,\"day\":\"2026-08-07\"},{\"downloads\":138038,\"day\":\"2026-08-08\"},{\"downloads\":128615,\"day\":\"2026-08-09\"},{\"downloads\":232606,\"day\":\"2026-08-10\"},{\"downloads\":240670,\"day\":\"2026-08-11\"},{\"downloads\":257056,\"day\":\"2026-08-12\"},{\"downloads\":263563,\"day\":\"2026-08-13\"},{\"downloads\":0,\"day\":\"2026-08-14\"},{\"downloads\":218302,\"day\":\"2026-08-15\"},{\"downloads\":145375,\"day\":\"2026-08-16\"},{\"downloads\":219779,\"day\":\"2026-08-17\"},{\"downloads\":234519,\"day\":\"2026-08-18\"},{\"downloads\":241463,\"day\":\"2026-08-19\"},{\"downloads\":237126,\"day\":\"2026-08-20\"},{\"downloads\":262372,\"day\":\"2026-08-21\"},{\"downloads\":182718,\"day\":\"2026-08-22\"},{\"downloads\":183373,\"day\":\"2026-08-23\"},{\"downloads\":302721,\"day\":\"2026-08-24\"},{\"downloads\":299137,\"day\":\"2026-08-25\"},{\"downloads\":294024,\"day\":\"2026-08-26\"},{\"downloads\":299028,\"day\":\"2026-08-27\"},{\"downloads\":301719,\"day\":\"2026-08-28\"},{\"downloads\":175288,\"day\":\"2026-08-29\"},{\"downloads\":159943,\"day\":\"2026-08-30\"},{\"downloads\":265975,\"day\":\"2026-08-31\"},{\"downloads\":271782,\"day\":\"2026-09-01\"},{\"downloads\":287623,\"day\":\"2026-09-02\"},{\"downloads\":0,\"day\":\"2026-09-03\"},{\"downloads\":236542,\"day\":\"2026-09-04\"},{\"downloads\":163525,\"day\":\"2026-09-05\"},{\"downloads\":211090,\"day\":\"2026-09-06\"},{\"downloads\":0,\"day\":\"2026-09-07\"},{\"downloads\":0,\"day\":\"2026-09-08\"},{\"downloads\":261183,\"day\":\"2026-09-09\"},{\"downloads\":268443,\"day\":\"2026-09-10\"},{\"downloads\":250050,\"day\":\"2026-09-11\"},{\"downloads\":164059,\"day\":\"2026-09-12\"},{\"downloads\":188684,\"day\":\"2026-09-13\"},{\"downloads\":339737,\"day\":\"2026-09-14\"},{\"downloads\":0,\"day\":\"2026-09-15\"},{\"downloads\":278779,\"day\":\"2026-09-16\"},{\"downloads\":280612,\"day\":\"2026-09-17\"},{\"downloads\":306045,\"day\":\"2026-09-18\"},{\"downloads\":387373,\"day\":\"2026-09-19\"},{\"downloads\":499412,\"day\":\"2026-09-20\"},{\"downloads\":395535,\"day\":\"2026-09-21\"},{\"downloads\":314788,\"day\":\"2026-09-22\"},{\"downloads\":316863,\"day\":\"2026-09-23\"},{\"downloads\":327024,\"day\":\"2026-09-24\"},{\"downloads\":334942,\"day\":\"2026-09-25\"},{\"downloads\":251678,\"day\":\"2026-09-26\"},{\"downloads\":298333,\"day\":\"2026-09-27\"}]}",
                    "pastedVersions": "{\"package\":\"left-pad\",\"downloads\":{\"0.0.2\":63,\"1.1.3\":5454,\"1.1.0\":4578,\"0.0.0\":322,\"0.0.4\":115,\"1.3.0\":4110106,\"0.0.9\":965,\"1.1.1\":266,\"0.0.3\":17604,\"1.0.2\":172,\"1.1.2\":395,\"1.0.0\":520,\"1.0.1\":138,\"1.2.0\":101325,\"0.0.1\":70}}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SoftwareAdoptionExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/internet-archive-change-explorer/calculate": {
      "post": {
        "operationId": "calculateInternetArchiveChangeExplorer",
        "summary": "See how a web page changed in the Wayback Machine: capture timeline plus the changes that matter.",
        "description": "Lists the distinct Wayback Machine captures of a URL, picks the captures closest to two dates (or exact timestamps), fetches both raw archived versions and diffs them, ranking meaningful changes — prices, headings, legal/policy terms, dates, contacts, links — above noise. Paste CDX rows and two HTML versions to analyse offline.\n\nMethodology:\n- Capture list: Wayback CDX API GET https://web.archive.org/cdx/search/cdx?url=…&output=json&fl=timestamp,original,statuscode,digest,length,mimetype&filter=statuscode:200&filter=mimetype:text/html, one capture per day (collapse=timestamp:8) — or per month for spans over 900 days. A new \"version\" starts whenever the content digest (SHA-1) changes.\n- Capture selection: exact 14-digit timestamps if given, otherwise the successful HTML capture closest to each date, taken from the timeline query (from = before − 30 days, to = after + 30 days); only if that is empty does the tool fall back to CDX closest=…&sort=closest&limit=1.\n- Archived pages are fetched raw (without the Wayback toolbar or URL rewriting) from https://web.archive.org/web/<timestamp>id_/<original URL>. Identical digests skip the fetch.\n- The two versions are compared with the Website Change Explainer engine: block-level LCS diff, word diffs, and rule-based categories (price, legal/policy terms, contact, link target, title, date, heading, number) ranked above trivial noise (whitespace, timestamps, copyright years, tracking parameters).\n- Similarity is the Dice coefficient over the words of the extracted page text (htmlToText).\n- Caveats: digests also change for http/https/www variants, embedded tokens or ads; the archive may miss periods; content loaded by JavaScript after page load is usually not in the raw HTML.",
        "tags": [
          "public-data"
        ],
        "x-mcp-tool": "internet_archive_change_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InternetArchiveChangeExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "example.com: Aug 2025 vs Sep 2026 (pasted CDX rows + archived HTML)",
                  "value": {
                    "url": "https://example.com/",
                    "beforeTimestamp": "20250801002042",
                    "afterTimestamp": "20260901000146",
                    "maxCaptures": 40,
                    "maxChanges": 25,
                    "pastedCdx": "[[\"timestamp\",\"original\",\"statuscode\",\"digest\",\"length\",\"mimetype\"],[\"20240701002435\",\"http://www.example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"699\",\"text/html\"],[\"20240801010121\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"751\",\"text/html\"],[\"20240901000219\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"1074\",\"text/html\"],[\"20241001000436\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"713\",\"text/html\"],[\"20241101002130\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"711\",\"text/html\"],[\"20241201001928\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"1263\",\"text/html\"],[\"20250101004557\",\"https://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"1232\",\"text/html\"],[\"20250201012603\",\"http://user:pass@example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"1202\",\"text/html\"],[\"20250301003025\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"1211\",\"text/html\"],[\"20250401000301\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"745\",\"text/html\"],[\"20250501001414\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"740\",\"text/html\"],[\"20250601000522\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"743\",\"text/html\"],[\"20250701005008\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"746\",\"text/html\"],[\"20250801002042\",\"http://example.com/\",\"200\",\"JI6OR3QR4CI526JD6TMMNZNV4QPMPQCH\",\"737\",\"text/html\"],[\"20250901000034\",\"https://example.com/\",\"200\",\"YXWQ7LLPPIZ7CVO6DVQ4U3Y2IO5M42AG\",\"1345\",\"text/html\"],[\"20251001001217\",\"https://example.com/\",\"200\",\"YXWQ7LLPPIZ7CVO6DVQ4U3Y2IO5M42AG\",\"1375\",\"text/html\"],[\"20251101000454\",\"https://www.example.com/\",\"200\",\"JUWMXAQNHPTRTHYQWT3EJILYCL7YC3PQ\",\"961\",\"text/html\"],[\"20251201000848\",\"http://www.example.com/\",\"200\",\"JUWMXAQNHPTRTHYQWT3EJILYCL7YC3PQ\",\"937\",\"text/html\"],[\"20260101000936\",\"http://www.example.com/\",\"200\",\"JUWMXAQNHPTRTHYQWT3EJILYCL7YC3PQ\",\"1009\",\"text/html\"],[\"20260201000022\",\"https://example.com/\",\"200\",\"4N5T7URO6PDNDBFG3V3AAQ45MXR3EXWK\",\"1040\",\"text/html\"],[\"20260301000114\",\"https://example.com/\",\"200\",\"UB6ILJGAIGCZBRVPWK2UVEWKHOYWSIYT\",\"1054\",\"text/html\"],[\"20260401000016\",\"https://example.com/\",\"200\",\"M7CPWPJVRUMERYFUWXWAHQRA4HOEEEXZ\",\"1042\",\"text/html\"],[\"20260501000121\",\"https://example.com/\",\"200\",\"M7CPWPJVRUMERYFUWXWAHQRA4HOEEEXZ\",\"1041\",\"text/html\"],[\"20260601000130\",\"https://example.com/\",\"200\",\"M7CPWPJVRUMERYFUWXWAHQRA4HOEEEXZ\",\"1041\",\"text/html\"],[\"20260701000143\",\"https://example.com/\",\"200\",\"PKUMGV5XIIUJG5CKD4HZMCRWKUMVP5S6\",\"1050\",\"text/html\"],[\"20260801000202\",\"https://example.com/\",\"200\",\"PKUMGV5XIIUJG5CKD4HZMCRWKUMVP5S6\",\"1049\",\"text/html\"],[\"20260901000146\",\"https://example.com/\",\"200\",\"PKUMGV5XIIUJG5CKD4HZMCRWKUMVP5S6\",\"1050\",\"text/html\"]]",
                    "pastedBefore": "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 2em;\n        background-color: #fdfdff;\n        border-radius: 0.5em;\n        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        div {\n            margin: 0 auto;\n            width: auto;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is for use in illustrative examples in documents. You may use this\n    domain in literature without prior coordination or asking for permission.</p>\n    <p><a href=\"https://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n",
                    "pastedAfter": "<!doctype html><html lang=\"en\"><head><title>Example Domain</title><link rel=\"icon\" href=\"data:,\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><style>body{background:#eee;width:60vw;margin:15vh auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style></head><body><div><h1>Example Domain</h1><p>This domain is for use in documentation examples without needing permission. Avoid use in operations.</p><p><a href=\"https://iana.org/domains/example\">Learn more</a></p></div></body></html>\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InternetArchiveChangeExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/satellite-change-explorer/calculate": {
      "post": {
        "operationId": "calculateSatelliteChangeExplorer",
        "summary": "Compare NASA satellite images of any place on two dates: true colour, NDVI, night lights.",
        "description": "Pick a place (latitude/longitude + radius, or a bounding box) and two dates. The tool builds side-by-side NASA GIBS images for each chosen layer — MODIS/VIIRS true colour, 7-2-1 false colour, 30 m Harmonized Landsat Sentinel-2, NDVI composites and VIIRS night lights — with the resolution, revisit and cloud caveats you need to read them correctly.\n\nMethodology:\n- The area is a lat/lon box: from a centre, half-width r km gives ±r/111.32° latitude and ±r/(111.32·cos φ)° longitude. Image height follows the box aspect in degrees (plate carrée, EPSG:4326).\n- Images come from NASA GIBS via the Worldview Snapshot API (https://wvs.earthdata.nasa.gov/api/v1/snapshot, REQUEST=GetSnapshot, CRS=EPSG:4326, BBOX=south,west,north,east, TIME=YYYY-MM-DD); an equivalent GIBS WMS 1.3.0 GetMap URL is returned too.\n- Layer identifiers, maximum resolutions (tile-matrix sets), formats and first available dates were taken from the GIBS EPSG:4326 \"best\" WMTS capabilities. Composite layers are requested at the start of their period (16-day periods begin on day-of-year 1, 17, 33, …; monthly on day 1).\n- If one image pixel is smaller than half the layer resolution the result flags \"upsampled\": detail finer than the native resolution is interpolation, not information.\n- No automated change detection: the tool cannot download image pixels, so it does not compute change statistics. Compare visually and mind clouds, season, sun angle and sensor differences.\n\nImagery courtesy of NASA EOSDIS GIBS. Visual comparison only; not suitable for legal or insurance evidence without the source data.",
        "tags": [
          "public-data"
        ],
        "x-mcp-tool": "satellite_change_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SatelliteChangeExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Nile Delta, summer 2025 vs summer 2026: true colour + NDVI",
                  "value": {
                    "lat": 30.6,
                    "lon": 31.2,
                    "radiusKm": 80,
                    "dateBefore": "2025-07-20",
                    "dateAfter": "2026-07-20",
                    "layers": [
                      "modis-terra-truecolor",
                      "ndvi-16day"
                    ],
                    "width": 512
                  }
                },
                "example2": {
                  "summary": "Berlin at 30 m (HLS Sentinel-2), August 2025 vs August 2026",
                  "value": {
                    "bbox": "13.2,52.4,13.6,52.6",
                    "dateBefore": "2025-08-13",
                    "dateAfter": "2026-08-05",
                    "layers": [
                      "hls-sentinel2"
                    ],
                    "width": 640
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SatelliteChangeExplorerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows": {
      "get": {
        "operationId": "listWorkflows",
        "summary": "Multi-tool workflows",
        "responses": {
          "200": {
            "description": "Workflow list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CsvExcelChartStudioInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "CSV, TSV or Excel file",
            "description": "CSV/TSV/TXT or .xlsx, max 20 MB. The format is detected from the content. Old .xls files: save as .xlsx first. Upload as {filename, contentType?, contentBase64}. Max 20480 KiB. Accepts .csv,.tsv,.txt,.xlsx,text/csv,text/tab-separated-values,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "data": {
            "title": "Or paste data",
            "description": "Comma-, semicolon-, tab- or pipe-separated, first row = headers. Used when no file is uploaded.",
            "type": "string",
            "maxLength": 2000000
          },
          "sheet": {
            "title": "Excel sheet",
            "description": "Sheet name or number; default: the first sheet.",
            "type": "string",
            "maxLength": 120
          },
          "hasHeader": {
            "title": "First row contains column names",
            "type": "boolean",
            "default": true
          },
          "chartType": {
            "title": "Chart type",
            "type": "string",
            "enum": [
              "auto",
              "line",
              "area",
              "bar",
              "stacked",
              "scatter",
              "pie",
              "donut",
              "histogram"
            ],
            "default": "auto"
          },
          "x": {
            "title": "X column (categories or dates)",
            "description": "Column name, letter (A, B …) or number. Empty: first date or text column.",
            "type": "string",
            "maxLength": 200
          },
          "y": {
            "title": "Y columns (values)",
            "description": "One or more column names, comma-separated. Empty: the numeric columns. No numeric column: rows are counted.",
            "type": "string",
            "maxLength": 1000
          },
          "group": {
            "title": "Group / series column",
            "description": "Optional: split the first Y column into one series per value of this column (e.g. Region) – ideal for stacked bars.",
            "type": "string",
            "maxLength": 200
          },
          "aggregation": {
            "title": "Combine repeated X values",
            "type": "string",
            "enum": [
              "auto",
              "sum",
              "avg",
              "count",
              "min",
              "max",
              "median",
              "none"
            ],
            "default": "auto"
          },
          "sort": {
            "title": "Sort",
            "type": "string",
            "enum": [
              "auto",
              "none",
              "x",
              "value-desc",
              "value-asc"
            ],
            "default": "auto"
          },
          "topN": {
            "title": "Top N categories",
            "description": "0 = all (very long category lists are cut automatically).",
            "type": "integer",
            "minimum": 0,
            "maximum": 200,
            "default": 0
          },
          "otherBucket": {
            "title": "Combine the rest into \"Other\"",
            "type": "boolean",
            "default": true
          },
          "bins": {
            "title": "Histogram bins",
            "description": "0 = automatic (Sturges’ rule).",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 0
          },
          "title": {
            "title": "Chart title",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "CsvExcelChartStudioResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "source",
              "columns",
              "chart",
              "table",
              "svg",
              "png"
            ],
            "properties": {
              "source": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "format",
                  "rows",
                  "columns",
                  "sheet",
                  "truncated"
                ],
                "properties": {
                  "format": {
                    "type": "string"
                  },
                  "rows": {
                    "type": "integer"
                  },
                  "columns": {
                    "type": "integer"
                  },
                  "sheet": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "sheets": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "delimiter": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "truncated": {
                    "type": "boolean"
                  }
                }
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "type",
                    "nonEmpty",
                    "distinct"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "number",
                        "date",
                        "category",
                        "empty"
                      ]
                    },
                    "nonEmpty": {
                      "type": "integer"
                    },
                    "distinct": {
                      "type": "integer"
                    }
                  }
                }
              },
              "chart": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "type",
                  "title",
                  "x",
                  "y",
                  "group",
                  "aggregation",
                  "sort",
                  "topN",
                  "categories",
                  "series",
                  "points"
                ],
                "properties": {
                  "type": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "x": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "y": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "group": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "aggregation": {
                    "type": "string"
                  },
                  "sort": {
                    "type": "string"
                  },
                  "topN": {
                    "type": "integer"
                  },
                  "categories": {
                    "type": "integer"
                  },
                  "series": {
                    "type": "integer"
                  },
                  "points": {
                    "type": "integer"
                  }
                }
              },
              "table": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "header",
                  "rows",
                  "totalRows"
                ],
                "properties": {
                  "header": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "rows": {
                    "type": "array",
                    "items": {
                      "type": "array"
                    }
                  },
                  "totalRows": {
                    "type": "integer"
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "TimeSeriesExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "CSV, TSV or Excel file",
            "description": "Max 20 MB. One date column plus one or more value columns (wide), or date, series and value columns (long). Upload as {filename, contentType?, contentBase64}. Max 20480 KiB. Accepts .csv,.tsv,.txt,.xlsx,text/csv,text/tab-separated-values,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "data": {
            "title": "Or paste data",
            "description": "First row = headers. Dates like 2026-03-01, 01.03.2026, 03/01/2026, 2026-03 or Mar 2026.",
            "type": "string",
            "maxLength": 2000000
          },
          "sheet": {
            "title": "Excel sheet",
            "type": "string",
            "maxLength": 120
          },
          "dateColumn": {
            "title": "Date column",
            "description": "Empty: the first date column.",
            "type": "string",
            "maxLength": 200
          },
          "valueColumns": {
            "title": "Value columns",
            "description": "Comma-separated; empty: all numeric columns (max 8).",
            "type": "string",
            "maxLength": 1000
          },
          "seriesColumn": {
            "title": "Series column (long format)",
            "description": "Optional: a column naming the series of each row; then the first value column holds the values.",
            "type": "string",
            "maxLength": 200
          },
          "resample": {
            "title": "Resample to",
            "type": "string",
            "enum": [
              "auto",
              "day",
              "week",
              "month",
              "quarter",
              "year"
            ],
            "default": "auto"
          },
          "resampleAgg": {
            "title": "Combine values in a period by",
            "type": "string",
            "enum": [
              "mean",
              "sum",
              "last",
              "first",
              "min",
              "max",
              "median"
            ],
            "default": "mean"
          },
          "smoothing": {
            "title": "Moving average",
            "type": "string",
            "enum": [
              "sma",
              "ema",
              "centred",
              "none"
            ],
            "default": "sma"
          },
          "window": {
            "title": "Moving-average window",
            "type": "integer",
            "minimum": 2,
            "maximum": 400,
            "default": 7,
            "x-unit": "points"
          },
          "seasonality": {
            "title": "Seasonality",
            "type": "string",
            "enum": [
              "auto",
              "weekday",
              "month",
              "quarter",
              "none"
            ],
            "default": "auto"
          },
          "anomalyMethod": {
            "title": "Anomaly detection",
            "type": "string",
            "enum": [
              "zscore",
              "iqr",
              "none"
            ],
            "default": "zscore"
          },
          "threshold": {
            "title": "Anomaly threshold",
            "description": "z-score: flag |z| above this (default 3). IQR: fences at k × IQR (default 1.5).",
            "type": "number",
            "minimum": 0.5,
            "maximum": 10
          },
          "png": {
            "title": "Also create a PNG of the main chart",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "TimeSeriesExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "dateColumn",
              "unit",
              "resampled",
              "smoothing",
              "window",
              "anomalyMethod",
              "threshold",
              "series",
              "svg",
              "png"
            ],
            "properties": {
              "dateColumn": {
                "type": "string"
              },
              "unit": {
                "type": "string",
                "description": "Spacing of the analysed series."
              },
              "resampled": {
                "type": "boolean"
              },
              "smoothing": {
                "type": "string"
              },
              "window": {
                "type": "integer"
              },
              "anomalyMethod": {
                "type": "string"
              },
              "threshold": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "series": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "points",
                    "start",
                    "end",
                    "first",
                    "last",
                    "min",
                    "max",
                    "mean",
                    "totalChangePercent",
                    "lastPeriodChangePercent",
                    "yoyChangePercent",
                    "trend",
                    "seasonality",
                    "anomalies"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "points": {
                      "type": "integer"
                    },
                    "start": {
                      "type": "string"
                    },
                    "end": {
                      "type": "string"
                    },
                    "first": {
                      "type": "number"
                    },
                    "last": {
                      "type": "number"
                    },
                    "min": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "date",
                        "value"
                      ],
                      "properties": {
                        "date": {
                          "type": "string"
                        },
                        "value": {
                          "type": "number"
                        }
                      }
                    },
                    "max": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "date",
                        "value"
                      ],
                      "properties": {
                        "date": {
                          "type": "string"
                        },
                        "value": {
                          "type": "number"
                        }
                      }
                    },
                    "mean": {
                      "type": "number"
                    },
                    "totalChangePercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "lastPeriodChangePercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "yoyChangePercent": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Last value vs the value one year earlier (null when the series is shorter than a year)."
                    },
                    "trend": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "slopePerDay",
                        "slopePerYear",
                        "r2",
                        "startValue",
                        "endValue"
                      ],
                      "properties": {
                        "slopePerDay": {
                          "type": "number"
                        },
                        "slopePerYear": {
                          "type": "number"
                        },
                        "r2": {
                          "type": "number"
                        },
                        "startValue": {
                          "type": "number"
                        },
                        "endValue": {
                          "type": "number"
                        }
                      }
                    },
                    "seasonality": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "kind",
                        "strength",
                        "phases"
                      ],
                      "properties": {
                        "kind": {
                          "type": "string"
                        },
                        "strength": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "phases": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "phase",
                              "index",
                              "average",
                              "count"
                            ],
                            "properties": {
                              "phase": {
                                "type": "string"
                              },
                              "index": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "average": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "count": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    },
                    "anomalies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "date",
                          "value",
                          "expected",
                          "score"
                        ],
                        "properties": {
                          "date": {
                            "type": "string"
                          },
                          "value": {
                            "type": "number"
                          },
                          "expected": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "score": {
                            "type": "number"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "GeoDataVisualizerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "CSV, Excel or GeoJSON file",
            "description": "Max 20 MB. CSV/XLSX: lat/lon columns or a country column (ISO code or English name). GeoJSON: Point, LineString, Polygon (and Multi-) geometries. Upload as {filename, contentType?, contentBase64}. Max 20480 KiB. Accepts .csv,.tsv,.txt,.xlsx,.geojson,.json,text/csv,application/geo+json,application/json,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "data": {
            "title": "Or paste data",
            "description": "CSV with a header row, or GeoJSON.",
            "type": "string",
            "maxLength": 2000000
          },
          "mode": {
            "title": "Map type",
            "type": "string",
            "enum": [
              "auto",
              "points",
              "proportional",
              "hexbin",
              "choropleth"
            ],
            "default": "auto"
          },
          "projection": {
            "title": "Projection",
            "type": "string",
            "enum": [
              "equal-earth",
              "mercator",
              "equirectangular"
            ],
            "default": "equal-earth"
          },
          "latColumn": {
            "title": "Latitude column",
            "description": "Empty: a column named lat/latitude.",
            "type": "string",
            "maxLength": 200
          },
          "lonColumn": {
            "title": "Longitude column",
            "description": "Empty: a column named lon/lng/longitude.",
            "type": "string",
            "maxLength": 200
          },
          "valueColumn": {
            "title": "Value column / property",
            "description": "Numbers for circle size, hex sums or choropleth shading. Empty: the first numeric column (or a \"value\" property in GeoJSON).",
            "type": "string",
            "maxLength": 200
          },
          "labelColumn": {
            "title": "Label column / property",
            "type": "string",
            "maxLength": 200
          },
          "countryColumn": {
            "title": "Country column (choropleth)",
            "description": "ISO 3166 alpha-2/alpha-3 codes or English country names.",
            "type": "string",
            "maxLength": 200
          },
          "zoom": {
            "title": "Extent",
            "type": "string",
            "enum": [
              "auto",
              "world"
            ],
            "default": "auto"
          },
          "hexRadius": {
            "title": "Hexagon size",
            "type": "integer",
            "minimum": 4,
            "maximum": 60,
            "default": 14,
            "x-unit": "px"
          },
          "title": {
            "title": "Map title",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "GeoDataVisualizerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "mode",
              "projection",
              "view",
              "points",
              "lines",
              "polygons",
              "countriesMatched",
              "unmatched",
              "invalidRows",
              "hexbins",
              "classes",
              "width",
              "height",
              "svg",
              "png"
            ],
            "properties": {
              "mode": {
                "type": "string"
              },
              "projection": {
                "type": "string"
              },
              "view": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "west",
                  "south",
                  "east",
                  "north"
                ],
                "properties": {
                  "west": {
                    "type": "number"
                  },
                  "south": {
                    "type": "number"
                  },
                  "east": {
                    "type": "number"
                  },
                  "north": {
                    "type": "number"
                  }
                }
              },
              "points": {
                "type": "integer"
              },
              "lines": {
                "type": "integer"
              },
              "polygons": {
                "type": "integer"
              },
              "countriesMatched": {
                "type": "integer"
              },
              "unmatched": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "invalidRows": {
                "type": "integer"
              },
              "hexbins": {
                "type": "integer"
              },
              "classes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "from",
                    "to",
                    "color",
                    "countries"
                  ],
                  "properties": {
                    "from": {
                      "type": "number"
                    },
                    "to": {
                      "type": "number"
                    },
                    "color": {
                      "type": "string"
                    },
                    "countries": {
                      "type": "integer"
                    }
                  }
                }
              },
              "width": {
                "type": "integer"
              },
              "height": {
                "type": "integer"
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "DiagramFlowchartMakerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "title": "Diagram text",
            "description": "First line: \"flowchart TD\" (or LR, BT, RL), \"sequenceDiagram\" or \"mindmap\". See the examples.",
            "type": "string",
            "maxLength": 50000,
            "default": "flowchart TD\n  start([Order received]) --> pay{Paid?}\n  pay -->|Yes| pick[Pick items]\n  pay -->|No| remind[/Send reminder/]\n  remind --> pay\n  pick --> stock{In stock?}\n  stock -->|Yes| ship[[Ship parcel]]\n  stock -->|No| back[(Backorder list)]\n  back -.-> pick\n  ship --> done((Done))"
          },
          "title": {
            "title": "Title",
            "description": "Shown above the diagram and used as its accessible name.",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "source"
        ]
      },
      "DiagramFlowchartMakerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "title",
              "width",
              "height",
              "nodes",
              "edges",
              "ignoredLines",
              "layout",
              "svg",
              "png"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "flowchart",
                  "sequence",
                  "mindmap"
                ]
              },
              "title": {
                "type": "string"
              },
              "direction": {
                "type": "string"
              },
              "width": {
                "type": "integer"
              },
              "height": {
                "type": "integer"
              },
              "nodes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "label"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "shape": {
                      "type": "string"
                    },
                    "depth": {
                      "type": "integer"
                    }
                  }
                }
              },
              "edges": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "from",
                    "to",
                    "label"
                  ],
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "style": {
                      "type": "string"
                    }
                  }
                }
              },
              "ignoredLines": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "line",
                    "text"
                  ],
                  "properties": {
                    "line": {
                      "type": "integer"
                    },
                    "text": {
                      "type": "string"
                    }
                  }
                }
              },
              "layout": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "layers": {
                    "type": "integer"
                  },
                  "crossings": {
                    "type": "integer"
                  },
                  "reversedEdges": {
                    "type": "integer"
                  },
                  "dummyNodes": {
                    "type": "integer"
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "EmbeddableChartBuilderInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "title": "Data",
            "description": "First row = headers. First column = labels (or dates/numbers for line and scatter charts); every further numeric column becomes a series.",
            "type": "string",
            "maxLength": 200000
          },
          "file": {
            "title": "Or upload CSV/XLSX",
            "description": "Max 5 MB; the first sheet is used. Upload as {filename, contentType?, contentBase64}. Max 5120 KiB. Accepts .csv,.tsv,.txt,.xlsx,text/csv,text/tab-separated-values,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "chartType": {
            "title": "Chart type",
            "type": "string",
            "enum": [
              "line",
              "area",
              "bar",
              "stacked",
              "scatter",
              "pie",
              "donut"
            ],
            "default": "bar"
          },
          "title": {
            "title": "Title",
            "type": "string",
            "maxLength": 140,
            "default": "My chart"
          },
          "description": {
            "title": "Text alternative (description)",
            "description": "What the chart shows, for screen readers and as the image alt text. Empty: generated from the data.",
            "type": "string",
            "maxLength": 1000
          },
          "xLabel": {
            "title": "X axis label",
            "type": "string",
            "maxLength": 80
          },
          "yLabel": {
            "title": "Y axis label",
            "type": "string",
            "maxLength": 80
          },
          "sourceNote": {
            "title": "Source / credit line",
            "description": "Shown under the chart, e.g. \"Source: Eurostat, 2026\".",
            "type": "string",
            "maxLength": 200
          },
          "width": {
            "title": "Width",
            "description": "The SVG scales to its container; this sets the aspect ratio and text size.",
            "type": "integer",
            "minimum": 320,
            "maximum": 1600,
            "default": 640,
            "x-unit": "px"
          },
          "height": {
            "title": "Height",
            "type": "integer",
            "minimum": 200,
            "maximum": 1200,
            "default": 360,
            "x-unit": "px"
          },
          "interactive": {
            "title": "Add hover/keyboard tooltips to the standalone HTML file",
            "type": "boolean",
            "default": false
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "title"
        ]
      },
      "EmbeddableChartBuilderResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "chartType",
              "title",
              "categories",
              "series",
              "svgMarkup",
              "figureSnippet",
              "imgSnippet",
              "standaloneHtml",
              "interactive",
              "png"
            ],
            "properties": {
              "chartType": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "categories": {
                "type": "integer"
              },
              "series": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "svgMarkup": {
                "type": "string",
                "description": "Standalone SVG (sanitised, no scripts or external references)."
              },
              "figureSnippet": {
                "type": "string",
                "description": "HTML <figure> with the inline SVG, caption and a data-table fallback."
              },
              "imgSnippet": {
                "type": "string",
                "description": "<img> tag for a self-hosted copy of the SVG file."
              },
              "standaloneHtml": {
                "type": "string",
                "description": "Complete HTML document (no external resources)."
              },
              "interactive": {
                "type": "boolean"
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "ProbabilityStatisticsStudioInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "analysis": {
            "title": "Analysis",
            "type": "string",
            "enum": [
              "distribution",
              "describe",
              "ci-mean",
              "ci-proportion",
              "t-one",
              "t-two",
              "t-paired",
              "chisq-gof",
              "chisq-indep",
              "z-one-prop",
              "z-two-prop"
            ],
            "default": "distribution"
          },
          "distribution": {
            "title": "Distribution",
            "type": "string",
            "enum": [
              "normal",
              "t",
              "chisq",
              "f",
              "binomial",
              "poisson",
              "exponential",
              "uniform"
            ],
            "default": "normal"
          },
          "param1": {
            "title": "Parameter 1",
            "description": "Defaults: normal μ = 0, t df = 10, chi-square df = 1, F d1 = 5, binomial n = 10, Poisson λ = 1, exponential λ = 1, uniform a = 0.",
            "type": "number"
          },
          "param2": {
            "title": "Parameter 2",
            "description": "Defaults: normal σ = 1, F d2 = 10, binomial p = 0.5, uniform b = 1.",
            "type": "number"
          },
          "x": {
            "title": "Value x",
            "description": "Distribution: compute pdf/pmf and P(X ≤ x).",
            "type": "number"
          },
          "x2": {
            "title": "Second value x₂",
            "description": "Optional: also compute P(x ≤ X ≤ x₂).",
            "type": "number"
          },
          "probability": {
            "title": "Probability p (for a quantile)",
            "description": "Distribution: the x with P(X ≤ x) = p (e.g. 0.975).",
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "data": {
            "title": "Data / sample 1 / observed counts / table",
            "description": "Numbers separated by spaces, commas or new lines. For the independence test: one row of counts per line.",
            "type": "string",
            "maxLength": 200000
          },
          "data2": {
            "title": "Sample 2 / expected counts",
            "description": "Two-sample and paired tests: the second sample. Goodness of fit: expected counts or proportions (optional; equal by default).",
            "type": "string",
            "maxLength": 200000
          },
          "mu0": {
            "title": "Hypothesised mean μ0",
            "type": "number",
            "default": 0
          },
          "sigma": {
            "title": "Known population SD σ",
            "description": "Optional, for a z interval for the mean.",
            "type": "number",
            "minimum": 0
          },
          "successes": {
            "title": "Successes x (group 1)",
            "type": "integer",
            "minimum": 0
          },
          "trials": {
            "title": "Trials n (group 1)",
            "type": "integer",
            "minimum": 1
          },
          "successes2": {
            "title": "Successes x (group 2)",
            "type": "integer",
            "minimum": 0
          },
          "trials2": {
            "title": "Trials n (group 2)",
            "type": "integer",
            "minimum": 1
          },
          "p0": {
            "title": "Hypothesised proportion p0",
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0.5
          },
          "confidence": {
            "title": "Confidence level",
            "description": "Also sets α = 1 − confidence for the tests.",
            "type": "number",
            "minimum": 0.5,
            "maximum": 0.9999,
            "default": 0.95
          },
          "alternative": {
            "title": "Alternative hypothesis",
            "type": "string",
            "enum": [
              "two-sided",
              "less",
              "greater"
            ],
            "default": "two-sided"
          },
          "equalVariances": {
            "title": "Assume equal variances (pooled two-sample t-test)",
            "type": "boolean",
            "default": false
          }
        },
        "required": []
      },
      "ProbabilityStatisticsStudioResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "analysis",
              "distribution",
              "descriptive",
              "interval",
              "test",
              "warnings"
            ],
            "properties": {
              "analysis": {
                "type": "string",
                "enum": [
                  "distribution",
                  "describe",
                  "ci-mean",
                  "ci-proportion",
                  "t-one",
                  "t-two",
                  "t-paired",
                  "chisq-gof",
                  "chisq-indep",
                  "z-one-prop",
                  "z-two-prop"
                ]
              },
              "distribution": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  },
                  "discrete": {
                    "type": "boolean"
                  },
                  "mean": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "variance": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "sd": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "pdfAtX": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "cdfAtX": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "survivalAtX": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "P(X > x)"
                  },
                  "between": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "P(x ≤ X ≤ x₂)"
                  },
                  "quantile": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "x": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "x2": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "probability": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "descriptive": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "n": {
                    "type": "integer"
                  },
                  "mean": {
                    "type": "number"
                  },
                  "median": {
                    "type": "number"
                  },
                  "modes": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  },
                  "sd": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "variance": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "min": {
                    "type": "number"
                  },
                  "max": {
                    "type": "number"
                  },
                  "q1": {
                    "type": "number"
                  },
                  "q3": {
                    "type": "number"
                  },
                  "iqr": {
                    "type": "number"
                  },
                  "se": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "skewness": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "kurtosis": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "sum": {
                    "type": "number"
                  },
                  "outliers": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              "interval": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "method": {
                    "type": "string"
                  },
                  "confidence": {
                    "type": "number"
                  },
                  "estimate": {
                    "type": "number"
                  },
                  "lower": {
                    "type": "number"
                  },
                  "upper": {
                    "type": "number"
                  },
                  "margin": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "alternatives": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "lower": {
                          "type": "number"
                        },
                        "upper": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              },
              "test": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "h0": {
                    "type": "string"
                  },
                  "h1": {
                    "type": "string"
                  },
                  "statistic": {
                    "type": "number"
                  },
                  "statisticName": {
                    "type": "string"
                  },
                  "df": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "pValue": {
                    "type": "number"
                  },
                  "alpha": {
                    "type": "number"
                  },
                  "reject": {
                    "type": "boolean"
                  },
                  "estimate": {
                    "type": "number"
                  },
                  "ciLower": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "ciUpper": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "effectName": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "effectSize": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "interpretation": {
                    "type": "string"
                  },
                  "details": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "value": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "DatafreshInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "title": "Dataset or API URL",
            "description": "Public http(s) JSON or CSV, max 2 MiB.",
            "type": "string",
            "format": "uri"
          },
          "content": {
            "title": "Or paste JSON/CSV content",
            "type": "string",
            "maxLength": 2000000
          },
          "format": {
            "title": "Format",
            "type": "string",
            "enum": [
              "auto",
              "json",
              "csv"
            ],
            "default": "auto"
          },
          "timestampField": {
            "title": "Timestamp field (optional)",
            "description": "Leave empty to detect (updated_at, date, …). Nested: parent.child",
            "type": "string",
            "maxLength": 120
          },
          "expectedCadenceHours": {
            "title": "Expected update interval",
            "description": "24 = daily, 168 = weekly, 720 ≈ monthly, 8760 = yearly.",
            "type": "number",
            "minimum": 0.1,
            "maximum": 87600,
            "default": 24,
            "x-unit": "hours"
          },
          "previousSchema": {
            "title": "Previous schema (optional, JSON from an earlier result)",
            "type": "string",
            "maxLength": 200000
          },
          "remember": {
            "title": "Remember this URL's schema for the next check",
            "description": "Stores only a hash of the URL plus the field list.",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "DatafreshResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "status",
              "source",
              "records",
              "recordPath",
              "timestampField",
              "newestRecordAt",
              "ageHours",
              "expectedCadenceHours",
              "schema",
              "schemaFingerprint",
              "previousFingerprint",
              "drift",
              "httpLastModified"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "healthy",
                  "stale",
                  "schema_changed",
                  "unavailable",
                  "no_timestamp"
                ]
              },
              "source": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "kind",
                  "url",
                  "httpStatus",
                  "fetchedAt",
                  "format"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "url",
                      "pasted"
                    ]
                  },
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "httpStatus": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "fetchedAt": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "csv"
                    ]
                  }
                }
              },
              "records": {
                "type": "integer"
              },
              "recordPath": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "timestampField": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "newestRecordAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "ageHours": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "expectedCadenceHours": {
                "type": "number"
              },
              "httpLastModified": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "schema": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "types",
                    "presence"
                  ],
                  "properties": {
                    "types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "presence": {
                      "type": "number"
                    }
                  }
                }
              },
              "schemaFingerprint": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "previousFingerprint": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "drift": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "added",
                  "removed",
                  "typeChanged"
                ],
                "properties": {
                  "added": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "removed": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "typeChanged": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "field",
                        "before",
                        "after"
                      ],
                      "properties": {
                        "field": {
                          "type": "string"
                        },
                        "before": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "after": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "UnitproofInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "expression": {
            "title": "Expression",
            "description": "Numbers, units with SI prefixes, ^ powers, * / + − and parentheses; optional \"to\"/\"in\" target. Juxtaposition (e.g. \"2 h\") binds tighter than * and /. Bare C/F mean °C/°F.",
            "type": "string",
            "maxLength": 300
          },
          "significantDigits": {
            "title": "Significant digits (rounded value)",
            "type": "integer",
            "minimum": 1,
            "maximum": 15,
            "default": 6
          }
        },
        "required": [
          "expression"
        ]
      },
      "UnitproofResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "expression",
              "value",
              "valueRounded",
              "significantDigits",
              "unit",
              "target",
              "valueSI",
              "unitSI",
              "dimension",
              "quantity",
              "dimensionCheck",
              "temperature",
              "alternatives",
              "derivation",
              "unitsUsed"
            ],
            "properties": {
              "expression": {
                "type": "string"
              },
              "value": {
                "type": "number",
                "description": "Unrounded IEEE-754 double result in the output unit."
              },
              "valueRounded": {
                "type": "number"
              },
              "significantDigits": {
                "type": "integer",
                "minimum": 1,
                "maximum": 15
              },
              "unit": {
                "type": "string"
              },
              "target": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "valueSI": {
                "type": "number",
                "description": "Value in coherent SI units (kelvin for temperatures)."
              },
              "unitSI": {
                "type": "string"
              },
              "dimension": {
                "type": "string"
              },
              "quantity": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "dimensionCheck": {
                "type": "string",
                "enum": [
                  "ok"
                ]
              },
              "temperature": {
                "type": "string",
                "enum": [
                  "absolute",
                  "interval",
                  "none"
                ]
              },
              "alternatives": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "unit",
                    "value"
                  ],
                  "properties": {
                    "unit": {
                      "type": "string"
                    },
                    "value": {
                      "type": "number"
                    }
                  }
                }
              },
              "derivation": {
                "type": "array",
                "minItems": 2,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "kind",
                    "label",
                    "value",
                    "unit",
                    "dimension",
                    "children",
                    "note"
                  ],
                  "properties": {
                    "id": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "literal",
                        "unit",
                        "operation",
                        "conversion",
                        "result"
                      ]
                    },
                    "label": {
                      "type": "string"
                    },
                    "value": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "unit": {
                      "type": "string"
                    },
                    "dimension": {
                      "type": "string"
                    },
                    "children": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 0
                      }
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              },
              "unitsUsed": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "symbol",
                    "name",
                    "definition",
                    "exact",
                    "source"
                  ],
                  "properties": {
                    "symbol": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "definition": {
                      "type": "string"
                    },
                    "exact": {
                      "type": "boolean"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "SI",
                        "NIST811",
                        "definition"
                      ]
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "LocalekitInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "country": {
            "title": "Country",
            "type": "string",
            "enum": [
              "AC",
              "AD",
              "AE",
              "AF",
              "AG",
              "AI",
              "AL",
              "AM",
              "AO",
              "AQ",
              "AR",
              "AS",
              "AT",
              "AU",
              "AW",
              "AX",
              "AZ",
              "BA",
              "BB",
              "BD",
              "BE",
              "BF",
              "BG",
              "BH",
              "BI",
              "BJ",
              "BL",
              "BM",
              "BN",
              "BO",
              "BQ",
              "BR",
              "BS",
              "BT",
              "BV",
              "BW",
              "BY",
              "BZ",
              "CA",
              "CC",
              "CD",
              "CF",
              "CG",
              "CH",
              "CI",
              "CK",
              "CL",
              "CM",
              "CN",
              "CO",
              "CR",
              "CU",
              "CV",
              "CW",
              "CX",
              "CY",
              "CZ",
              "DE",
              "DJ",
              "DK",
              "DM",
              "DO",
              "DZ",
              "EC",
              "EE",
              "EG",
              "EH",
              "ER",
              "ES",
              "ET",
              "FI",
              "FJ",
              "FK",
              "FM",
              "FO",
              "FR",
              "GA",
              "GB",
              "GD",
              "GE",
              "GF",
              "GG",
              "GH",
              "GI",
              "GL",
              "GM",
              "GN",
              "GP",
              "GQ",
              "GR",
              "GS",
              "GT",
              "GU",
              "GW",
              "GY",
              "HK",
              "HM",
              "HN",
              "HR",
              "HT",
              "HU",
              "ID",
              "IE",
              "IL",
              "IM",
              "IN",
              "IO",
              "IQ",
              "IR",
              "IS",
              "IT",
              "JE",
              "JM",
              "JO",
              "JP",
              "KE",
              "KG",
              "KH",
              "KI",
              "KM",
              "KN",
              "KP",
              "KR",
              "KW",
              "KY",
              "KZ",
              "LA",
              "LB",
              "LC",
              "LI",
              "LK",
              "LR",
              "LS",
              "LT",
              "LU",
              "LV",
              "LY",
              "MA",
              "MC",
              "MD",
              "ME",
              "MF",
              "MG",
              "MH",
              "MK",
              "ML",
              "MM",
              "MN",
              "MO",
              "MP",
              "MQ",
              "MR",
              "MS",
              "MT",
              "MU",
              "MV",
              "MW",
              "MX",
              "MY",
              "MZ",
              "NA",
              "NC",
              "NE",
              "NF",
              "NG",
              "NI",
              "NL",
              "NO",
              "NP",
              "NR",
              "NU",
              "NZ",
              "OM",
              "PA",
              "PE",
              "PF",
              "PG",
              "PH",
              "PK",
              "PL",
              "PM",
              "PN",
              "PR",
              "PS",
              "PT",
              "PW",
              "PY",
              "QA",
              "RE",
              "RO",
              "RS",
              "RU",
              "RW",
              "SA",
              "SB",
              "SC",
              "SD",
              "SE",
              "SG",
              "SH",
              "SI",
              "SJ",
              "SK",
              "SL",
              "SM",
              "SN",
              "SO",
              "SR",
              "SS",
              "ST",
              "SV",
              "SX",
              "SY",
              "SZ",
              "TA",
              "TC",
              "TD",
              "TF",
              "TG",
              "TH",
              "TJ",
              "TK",
              "TL",
              "TM",
              "TN",
              "TO",
              "TR",
              "TT",
              "TV",
              "TW",
              "TZ",
              "UA",
              "UG",
              "UM",
              "US",
              "UY",
              "UZ",
              "VA",
              "VC",
              "VE",
              "VG",
              "VI",
              "VN",
              "VU",
              "WF",
              "WS",
              "XK",
              "YE",
              "YT",
              "ZA",
              "ZM",
              "ZW"
            ],
            "default": "DE"
          },
          "postalCode": {
            "title": "Postal code to validate (optional)",
            "type": "string",
            "maxLength": 20
          },
          "phone": {
            "title": "Phone number to normalise (optional)",
            "description": "National or international format; extensions (ext. 12) are dropped.",
            "type": "string",
            "maxLength": 40
          }
        },
        "required": [
          "country"
        ]
      },
      "LocalekitResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "country",
              "countryName",
              "form",
              "postal",
              "subdivisions",
              "phone",
              "locale"
            ],
            "properties": {
              "country": {
                "type": "string",
                "pattern": "^[A-Z]{2}$"
              },
              "countryName": {
                "type": "string"
              },
              "form": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "format",
                  "latinFormat",
                  "fields",
                  "unmappedTokens"
                ],
                "properties": {
                  "format": {
                    "type": "string"
                  },
                  "latinFormat": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "unmappedTokens": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "key",
                        "token",
                        "label",
                        "required",
                        "uppercase",
                        "line"
                      ],
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "token": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        },
                        "required": {
                          "type": "boolean"
                        },
                        "uppercase": {
                          "type": "boolean"
                        },
                        "line": {
                          "type": "integer",
                          "minimum": 1
                        }
                      }
                    }
                  }
                }
              },
              "postal": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "used",
                  "label",
                  "pattern",
                  "examples",
                  "input",
                  "normalisedInput",
                  "valid",
                  "lookupUrl"
                ],
                "properties": {
                  "used": {
                    "type": "boolean"
                  },
                  "label": {
                    "type": "string"
                  },
                  "pattern": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "examples": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "input": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "normalisedInput": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "valid": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "lookupUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "subdivisions": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "label",
                  "count",
                  "items"
                ],
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "count": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "key",
                        "name",
                        "isoCode"
                      ],
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "isoCode": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              },
              "phone": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "callingCode",
                  "internationalPrefix",
                  "nationalPrefix",
                  "possibleNationalLengths",
                  "input",
                  "e164",
                  "nationalNumber",
                  "plausibleLength",
                  "steps"
                ],
                "properties": {
                  "callingCode": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "internationalPrefix": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "nationalPrefix": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "possibleNationalLengths": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "input": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "e164": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^\\+[1-9]\\d{1,14}$"
                  },
                  "nationalNumber": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "plausibleLength": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "locale": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "assumedLocale",
                  "dateShort",
                  "dateMedium",
                  "dateLong",
                  "time",
                  "number",
                  "firstDayOfWeek",
                  "currency"
                ],
                "properties": {
                  "assumedLocale": {
                    "type": "string"
                  },
                  "dateShort": {
                    "type": "string"
                  },
                  "dateMedium": {
                    "type": "string"
                  },
                  "dateLong": {
                    "type": "string"
                  },
                  "time": {
                    "type": "string"
                  },
                  "number": {
                    "type": "string"
                  },
                  "firstDayOfWeek": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "currency": {
                    "type": "null",
                    "description": "ECMA-402 Intl has no region→currency mapping, so this is never guessed."
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "EnergyGridExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "title": "Data source",
            "type": "string",
            "enum": [
              "live",
              "pasted"
            ],
            "default": "live"
          },
          "country": {
            "title": "Country",
            "type": "string",
            "enum": [
              "de",
              "at",
              "be",
              "bg",
              "ch",
              "cy",
              "cz",
              "dk",
              "ee",
              "es",
              "fi",
              "fr",
              "gr",
              "hr",
              "hu",
              "ie",
              "it",
              "lt",
              "lu",
              "lv",
              "nl",
              "no",
              "pl",
              "pt",
              "ro",
              "se",
              "si",
              "sk",
              "uk",
              "ba",
              "ge",
              "md",
              "me",
              "mk",
              "rs",
              "ua",
              "xk",
              "eu"
            ],
            "default": "de"
          },
          "startDate": {
            "title": "From (local date)",
            "description": "Default: yesterday. Energy-Charts interprets dates in Central European time.",
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "title": "To (local date, inclusive)",
            "description": "Max 31 days per request.",
            "type": "string",
            "format": "date"
          },
          "includePrices": {
            "title": "Day-ahead prices",
            "type": "boolean",
            "default": true
          },
          "includeFlows": {
            "title": "Cross-border physical flows",
            "type": "boolean",
            "default": true
          },
          "pastedPower": {
            "title": "Pasted /public_power JSON",
            "type": "string",
            "maxLength": 3000000
          },
          "pastedPrice": {
            "title": "Pasted /price JSON (optional)",
            "type": "string",
            "maxLength": 1000000
          },
          "pastedFlows": {
            "title": "Pasted /cbpf JSON (optional)",
            "type": "string",
            "maxLength": 2000000
          }
        },
        "required": []
      },
      "EnergyGridExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "country",
              "countryName",
              "period",
              "generation",
              "mix",
              "load",
              "prices",
              "flows",
              "outages"
            ],
            "properties": {
              "country": {
                "type": "string"
              },
              "countryName": {
                "type": "string"
              },
              "period": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "requestedStart",
                  "requestedEnd",
                  "firstSample",
                  "lastSample",
                  "samples",
                  "stepMinutes"
                ],
                "properties": {
                  "requestedStart": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "requestedEnd": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "firstSample": {
                    "type": "string"
                  },
                  "lastSample": {
                    "type": "string"
                  },
                  "samples": {
                    "type": "integer"
                  },
                  "stepMinutes": {
                    "type": "number"
                  }
                }
              },
              "generation": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "totalGWh",
                  "renewableGWh",
                  "renewableSharePct",
                  "apiRenewableShareOfGenerationPct",
                  "apiRenewableShareOfLoadPct",
                  "netTradingGWh",
                  "pumpedStorageChargingGWh",
                  "residualLoadPeakMW"
                ],
                "properties": {
                  "totalGWh": {
                    "type": "number"
                  },
                  "renewableGWh": {
                    "type": "number"
                  },
                  "renewableSharePct": {
                    "type": "number"
                  },
                  "apiRenewableShareOfGenerationPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Unweighted mean of the Energy-Charts series."
                  },
                  "apiRenewableShareOfLoadPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "netTradingGWh": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Scheduled cross-border trading balance (positive = import)."
                  },
                  "pumpedStorageChargingGWh": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "residualLoadPeakMW": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "mix": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "gwh",
                    "sharePct",
                    "peakMW",
                    "renewableWeight"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "gwh": {
                      "type": "number"
                    },
                    "sharePct": {
                      "type": "number"
                    },
                    "peakMW": {
                      "type": "number"
                    },
                    "renewableWeight": {
                      "type": "number"
                    }
                  }
                }
              },
              "load": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "avgMW",
                  "peakMW",
                  "peakAt",
                  "minMW",
                  "minAt",
                  "energyGWh"
                ],
                "properties": {
                  "avgMW": {
                    "type": "number"
                  },
                  "peakMW": {
                    "type": "number"
                  },
                  "peakAt": {
                    "type": "string"
                  },
                  "minMW": {
                    "type": "number"
                  },
                  "minAt": {
                    "type": "string"
                  },
                  "energyGWh": {
                    "type": "number"
                  }
                }
              },
              "prices": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "zone",
                  "unit",
                  "avg",
                  "max",
                  "maxAt",
                  "min",
                  "minAt",
                  "negativeIntervals",
                  "intervals",
                  "license"
                ],
                "properties": {
                  "zone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "unit": {
                    "type": "string"
                  },
                  "avg": {
                    "type": "number"
                  },
                  "max": {
                    "type": "number"
                  },
                  "maxAt": {
                    "type": "string"
                  },
                  "min": {
                    "type": "number"
                  },
                  "minAt": {
                    "type": "string"
                  },
                  "negativeIntervals": {
                    "type": "integer"
                  },
                  "intervals": {
                    "type": "integer"
                  },
                  "license": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "flows": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "netImportGWh",
                  "neighbours"
                ],
                "properties": {
                  "netImportGWh": {
                    "type": "number"
                  },
                  "neighbours": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "name",
                        "netImportGWh",
                        "maxImportGW",
                        "maxExportGW"
                      ],
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "netImportGWh": {
                          "type": "number"
                        },
                        "maxImportGW": {
                          "type": "number"
                        },
                        "maxExportGW": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              },
              "outages": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "available",
                  "note"
                ],
                "properties": {
                  "available": {
                    "type": "boolean"
                  },
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PublicSpendingExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "title": "Data source",
            "type": "string",
            "enum": [
              "usaspending",
              "ted",
              "pasted"
            ],
            "default": "usaspending"
          },
          "keyword": {
            "title": "Keyword",
            "description": "Full-text keyword (award description / notice text).",
            "type": "string",
            "maxLength": 200
          },
          "recipient": {
            "title": "Recipient / vendor name",
            "description": "Optional. USAspending: recipient_search_text; TED: winner-name contains.",
            "type": "string",
            "maxLength": 200
          },
          "awardType": {
            "title": "Award type (USAspending)",
            "type": "string",
            "enum": [
              "contracts",
              "idvs",
              "grants",
              "other_financial_assistance"
            ],
            "default": "contracts"
          },
          "startDate": {
            "title": "From",
            "description": "Default: 365 days before today.",
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "title": "To",
            "description": "Default: today.",
            "type": "string",
            "format": "date"
          },
          "buyerCountry": {
            "title": "Buyer country (TED, ISO 3166 alpha-3)",
            "type": "string",
            "maxLength": 3
          },
          "limit": {
            "title": "Max results",
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 50
          },
          "pastedJson": {
            "title": "Pasted JSON response",
            "description": "Response of USAspending POST /api/v2/search/spending_by_award/ or TED POST /v3/notices/search.",
            "type": "string",
            "maxLength": 2000000
          }
        },
        "required": []
      },
      "PublicSpendingExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "source",
              "query",
              "awards",
              "totals",
              "byBuyer",
              "byRecipient",
              "officialTotals",
              "awardCounts",
              "hasMore"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "usaspending",
                  "ted",
                  "pasted-usaspending",
                  "pasted-ted"
                ]
              },
              "query": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Exact request sent to the API (null for pasted data)."
              },
              "awards": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "buyer",
                    "subBuyer",
                    "recipient",
                    "amount",
                    "currency",
                    "startDate",
                    "endDate",
                    "description",
                    "url"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "buyer": {
                      "type": "string"
                    },
                    "subBuyer": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "recipient": {
                      "type": "string"
                    },
                    "amount": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "currency": {
                      "type": "string"
                    },
                    "startDate": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "endDate": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "totals": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "awards",
                  "withAmount",
                  "currency",
                  "amount",
                  "otherCurrencies"
                ],
                "properties": {
                  "awards": {
                    "type": "integer"
                  },
                  "withAmount": {
                    "type": "integer"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "number"
                  },
                  "otherCurrencies": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "currency",
                        "amount",
                        "count"
                      ],
                      "properties": {
                        "currency": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              },
              "byBuyer": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "amount",
                    "count"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number"
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              },
              "byRecipient": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "amount",
                    "count"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number"
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              },
              "officialTotals": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "USAspending spending_by_category totals over ALL matching transactions in the period (not just the listed awards).",
                "additionalProperties": false,
                "required": [
                  "byAgency",
                  "byRecipient"
                ],
                "properties": {
                  "byAgency": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "name",
                        "amount"
                      ],
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "byRecipient": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "name",
                        "amount"
                      ],
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              },
              "awardCounts": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "hasMore": {
                "type": "boolean"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "SoftwareAdoptionExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "ecosystem": {
            "title": "Registry",
            "type": "string",
            "enum": [
              "npm",
              "pypi",
              "crates"
            ],
            "default": "npm"
          },
          "package": {
            "title": "Package name",
            "type": "string",
            "maxLength": 214
          },
          "includeDependents": {
            "title": "Look up dependents on deps.dev",
            "type": "boolean",
            "default": true
          },
          "pastedDownloads": {
            "title": "Pasted download JSON (offline)",
            "description": "npm /downloads/range/…, pypistats /overall or crates.io /crates/<name>/downloads.",
            "type": "string",
            "maxLength": 3000000
          },
          "pastedVersions": {
            "title": "Pasted version JSON (optional)",
            "description": "npm /versions/<pkg>/last-week, or crates.io /crates/<name> (maps version ids to numbers).",
            "type": "string",
            "maxLength": 3000000
          }
        },
        "required": []
      },
      "SoftwareAdoptionExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "ecosystem",
              "package",
              "period",
              "totals",
              "weekly",
              "trend",
              "recent",
              "versions",
              "dependents",
              "registry"
            ],
            "properties": {
              "ecosystem": {
                "type": "string",
                "enum": [
                  "npm",
                  "pypi",
                  "crates"
                ]
              },
              "package": {
                "type": "string"
              },
              "period": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "start",
                  "end",
                  "days"
                ],
                "properties": {
                  "start": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "end": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "days": {
                    "type": "integer"
                  }
                }
              },
              "totals": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "downloads",
                  "avgDaily",
                  "zeroDays"
                ],
                "properties": {
                  "downloads": {
                    "type": "number"
                  },
                  "avgDaily": {
                    "type": "number"
                  },
                  "zeroDays": {
                    "type": "integer"
                  }
                }
              },
              "weekly": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "weekStart",
                    "downloads",
                    "days",
                    "partial"
                  ],
                  "properties": {
                    "weekStart": {
                      "type": "string"
                    },
                    "downloads": {
                      "type": "number"
                    },
                    "days": {
                      "type": "integer"
                    },
                    "partial": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "trend": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "completeWeeks",
                  "last4Weeks",
                  "previous4Weeks",
                  "growthPct",
                  "first4Weeks",
                  "firstToLastPct",
                  "peakWeek",
                  "peakWeekDownloads"
                ],
                "properties": {
                  "completeWeeks": {
                    "type": "integer"
                  },
                  "last4Weeks": {
                    "type": "number"
                  },
                  "previous4Weeks": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "growthPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "first4Weeks": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "firstToLastPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "peakWeek": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "peakWeekDownloads": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "recent": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "lastDay",
                  "lastWeek",
                  "lastMonth"
                ],
                "properties": {
                  "lastDay": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "lastWeek": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "lastMonth": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "versions": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "window",
                  "total",
                  "items",
                  "byMajor",
                  "highestStable",
                  "highestStableSharePct"
                ],
                "properties": {
                  "window": {
                    "type": "string"
                  },
                  "total": {
                    "type": "number"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "version",
                        "downloads",
                        "sharePct"
                      ],
                      "properties": {
                        "version": {
                          "type": "string"
                        },
                        "downloads": {
                          "type": "number"
                        },
                        "sharePct": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "byMajor": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "major",
                        "downloads",
                        "sharePct"
                      ],
                      "properties": {
                        "major": {
                          "type": "string"
                        },
                        "downloads": {
                          "type": "number"
                        },
                        "sharePct": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "highestStable": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "highestStableSharePct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "dependents": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "version",
                  "dependentCount",
                  "directDependentCount",
                  "indirectDependentCount"
                ],
                "properties": {
                  "version": {
                    "type": "string"
                  },
                  "dependentCount": {
                    "type": "integer"
                  },
                  "directDependentCount": {
                    "type": "integer"
                  },
                  "indirectDependentCount": {
                    "type": "integer"
                  }
                }
              },
              "registry": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "latestVersion",
                  "createdAt",
                  "allTimeDownloads"
                ],
                "properties": {
                  "latestVersion": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "createdAt": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "allTimeDownloads": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "InternetArchiveChangeExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "title": "Page URL",
            "type": "string",
            "format": "uri"
          },
          "beforeDate": {
            "title": "Before date",
            "description": "The capture closest to this date is used. Default: one year ago.",
            "type": "string",
            "format": "date"
          },
          "afterDate": {
            "title": "After date",
            "description": "Default: today (latest capture).",
            "type": "string",
            "format": "date"
          },
          "beforeTimestamp": {
            "title": "Exact \"before\" capture (14-digit timestamp)",
            "type": "string",
            "maxLength": 14
          },
          "afterTimestamp": {
            "title": "Exact \"after\" capture (14-digit timestamp)",
            "type": "string",
            "maxLength": 14
          },
          "maxCaptures": {
            "title": "Captures shown in the timeline",
            "type": "integer",
            "minimum": 5,
            "maximum": 200,
            "default": 40
          },
          "maxChanges": {
            "title": "Max changes listed",
            "type": "integer",
            "minimum": 5,
            "maximum": 200,
            "default": 25
          },
          "pastedCdx": {
            "title": "Pasted CDX output (offline)",
            "description": "output=json rows or default text lines.",
            "type": "string",
            "maxLength": 2000000
          },
          "pastedBefore": {
            "title": "Pasted \"before\" HTML (offline)",
            "type": "string",
            "maxLength": 400000
          },
          "pastedAfter": {
            "title": "Pasted \"after\" HTML (offline)",
            "type": "string",
            "maxLength": 400000
          }
        },
        "required": []
      },
      "InternetArchiveChangeExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "url",
              "before",
              "after",
              "captures",
              "identical",
              "comparison",
              "highlights",
              "unifiedDiff"
            ],
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "before": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "timestamp",
                  "time",
                  "original",
                  "digest",
                  "archiveUrl",
                  "rawUrl",
                  "selectedBy"
                ],
                "properties": {
                  "timestamp": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "time": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "original": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "digest": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "archiveUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "rawUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "selectedBy": {
                    "type": "string",
                    "enum": [
                      "nearest-capture",
                      "explicit-timestamp",
                      "pasted"
                    ]
                  }
                }
              },
              "after": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "timestamp",
                  "time",
                  "original",
                  "digest",
                  "archiveUrl",
                  "rawUrl",
                  "selectedBy"
                ],
                "properties": {
                  "timestamp": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "time": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "original": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "digest": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "archiveUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "rawUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "selectedBy": {
                    "type": "string",
                    "enum": [
                      "nearest-capture",
                      "explicit-timestamp",
                      "pasted"
                    ]
                  }
                }
              },
              "captures": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "total",
                  "distinctVersions",
                  "granularity",
                  "items"
                ],
                "properties": {
                  "total": {
                    "type": "integer"
                  },
                  "distinctVersions": {
                    "type": "integer"
                  },
                  "granularity": {
                    "type": "string"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "timestamp",
                        "time",
                        "original",
                        "statuscode",
                        "digest",
                        "length",
                        "newVersion"
                      ],
                      "properties": {
                        "timestamp": {
                          "type": "string"
                        },
                        "time": {
                          "type": "string"
                        },
                        "original": {
                          "type": "string"
                        },
                        "statuscode": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "digest": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "length": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "newVersion": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              },
              "identical": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "true when both captures have the same content digest (no fetch needed)."
              },
              "comparison": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "similarityPct",
                  "wordsBefore",
                  "wordsAfter",
                  "meaningful",
                  "trivial",
                  "high",
                  "medium",
                  "low"
                ],
                "properties": {
                  "similarityPct": {
                    "type": "number"
                  },
                  "wordsBefore": {
                    "type": "integer"
                  },
                  "wordsAfter": {
                    "type": "integer"
                  },
                  "meaningful": {
                    "type": "integer"
                  },
                  "trivial": {
                    "type": "integer"
                  },
                  "high": {
                    "type": "integer"
                  },
                  "medium": {
                    "type": "integer"
                  },
                  "low": {
                    "type": "integer"
                  }
                }
              },
              "highlights": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "category",
                    "level",
                    "kind",
                    "element",
                    "before",
                    "after",
                    "wordDiff"
                  ],
                  "properties": {
                    "category": {
                      "type": "string"
                    },
                    "level": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string"
                    },
                    "element": {
                      "type": "string"
                    },
                    "before": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "after": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "wordDiff": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "unifiedDiff": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "SatelliteChangeExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "lat": {
            "title": "Latitude",
            "type": "number",
            "minimum": -85,
            "maximum": 85
          },
          "lon": {
            "title": "Longitude",
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "radiusKm": {
            "title": "Half-width of the area",
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "default": 30,
            "x-unit": "km"
          },
          "bbox": {
            "title": "Or bounding box (west,south,east,north)",
            "description": "Overrides latitude/longitude when set.",
            "type": "string",
            "maxLength": 120
          },
          "dateBefore": {
            "title": "Before date",
            "description": "Default: one year before the \"after\" date.",
            "type": "string",
            "format": "date"
          },
          "dateAfter": {
            "title": "After date",
            "description": "Default: yesterday (UTC).",
            "type": "string",
            "format": "date"
          },
          "layers": {
            "title": "Layers",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "modis-terra-truecolor",
                "modis-aqua-truecolor",
                "viirs-snpp-truecolor",
                "viirs-noaa20-truecolor",
                "modis-terra-721",
                "hls-sentinel2",
                "hls-landsat",
                "ndvi-16day",
                "ndvi-monthly",
                "night-lights"
              ]
            },
            "default": [
              "modis-terra-truecolor"
            ]
          },
          "width": {
            "title": "Image width",
            "type": "integer",
            "minimum": 128,
            "maximum": 1024,
            "default": 512,
            "x-unit": "px"
          }
        },
        "required": []
      },
      "SatelliteChangeExplorerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "bbox",
              "center",
              "areaKm",
              "image",
              "dates",
              "layers",
              "changeDetection"
            ],
            "properties": {
              "bbox": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "west",
                  "south",
                  "east",
                  "north"
                ],
                "properties": {
                  "west": {
                    "type": "number"
                  },
                  "south": {
                    "type": "number"
                  },
                  "east": {
                    "type": "number"
                  },
                  "north": {
                    "type": "number"
                  }
                }
              },
              "center": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "lat",
                  "lon"
                ],
                "properties": {
                  "lat": {
                    "type": "number"
                  },
                  "lon": {
                    "type": "number"
                  }
                }
              },
              "areaKm": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "width",
                  "height"
                ],
                "properties": {
                  "width": {
                    "type": "number"
                  },
                  "height": {
                    "type": "number"
                  }
                }
              },
              "image": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "width",
                  "height",
                  "kmPerPixel"
                ],
                "properties": {
                  "width": {
                    "type": "integer"
                  },
                  "height": {
                    "type": "integer"
                  },
                  "kmPerPixel": {
                    "type": "number"
                  }
                }
              },
              "dates": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "before",
                  "after",
                  "daysApart"
                ],
                "properties": {
                  "before": {
                    "type": "string"
                  },
                  "after": {
                    "type": "string"
                  },
                  "daysApart": {
                    "type": "integer"
                  }
                }
              },
              "layers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "key",
                    "gibsLayer",
                    "title",
                    "instrument",
                    "resolution",
                    "temporal",
                    "availableFrom",
                    "format",
                    "upsampled",
                    "before",
                    "after",
                    "notes"
                  ],
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "gibsLayer": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "instrument": {
                      "type": "string"
                    },
                    "resolution": {
                      "type": "string"
                    },
                    "temporal": {
                      "type": "string",
                      "enum": [
                        "daily",
                        "16-day",
                        "monthly"
                      ]
                    },
                    "availableFrom": {
                      "type": "string"
                    },
                    "format": {
                      "type": "string"
                    },
                    "upsampled": {
                      "type": "boolean"
                    },
                    "before": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "requestedDate",
                        "imageDate",
                        "available",
                        "snapshotUrl",
                        "wmsUrl"
                      ],
                      "properties": {
                        "requestedDate": {
                          "type": "string"
                        },
                        "imageDate": {
                          "type": "string"
                        },
                        "available": {
                          "type": "boolean"
                        },
                        "snapshotUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "wmsUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "after": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "requestedDate",
                        "imageDate",
                        "available",
                        "snapshotUrl",
                        "wmsUrl"
                      ],
                      "properties": {
                        "requestedDate": {
                          "type": "string"
                        },
                        "imageDate": {
                          "type": "string"
                        },
                        "available": {
                          "type": "boolean"
                        },
                        "snapshotUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "wmsUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "changeDetection": {
                "type": "string",
                "description": "Always \"visual-only\": no pixel comparison is performed."
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}