{
  "openapi": "3.1.1",
  "info": {
    "title": "Ohmforge Serial Log to Capture API",
    "version": "1.0.0",
    "summary": "Paste a serial monitor log: numbers become channels with frequency, Vpp, RMS and rise time.",
    "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://ohmforgeseriallogtocapture.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Paste a serial monitor log: numbers become channels with frequency, Vpp, RMS and rise time.",
        "description": "Turns a saved serial monitor log into a waveform capture and measures it like an oscilloscope recording. Lines with numbers (\"512\", \"1.5 2.0\", \"temp:21.5 hum:40\") become channels, text lines are skipped. Time comes from the log's time stamps (Arduino IDE, Ohmforge Serial monitor, Tera Term style), from a time column the device prints (millis()) or from a fixed sample rate. You get Vpp, mean, RMS, frequency, duty cycle and rise time per channel, a chart and a CSV that opens in the Capture analyzer.\n\nMethodology:\n- Lines and time stamps: the log is split at LF, CR LF or CR. Recognised time stamps are \"[2026-11-02 10:15:30.125] …\" (Ohmforge Serial monitor; also with T, Z or a UTC offset as Tera Term and other terminals write it), \"10:15:30.125 -> …\" (Arduino IDE; midnight wraps are followed) and \"[12.345678] …\" seconds; resolution 1 ms.\n- Numbers: like the Arduino serial plotter, a data line holds up to 16 numbers separated by spaces, tabs, commas or semicolons, each optionally labelled \"name:value\" or \"name=value\". Unlabelled numbers are named by position (Value 1, Value 2 …); nan, inf and ovf count as missing values. Lines with any other word are text and are skipped.\n- Time base: arrival times are the log's time stamps relative to the first data line; lines with the same stamp (one USB packet) are spaced evenly up to the next stamp. A device time column (millis(), micros()) gives exact sample times and must not go backwards. A fixed sample rate gives t = n / fs.\n- Measurements are the Capture analyzer's (ohmforge-capture-analyzer): IEEE 181 state levels, 50 % crossings with hysteresis for frequency and duty, 10–90 % rise time, time-weighted mean and RMS. Lines missing a value of a chosen series are left out. There is no spectrum here: open the capture CSV in the Capture analyzer for FFT, THD and SNR.\n\nA serial log is only as good as its timing: arrival-time stamps carry USB and operating-system jitter of a few milliseconds, so frequencies above a few hertz need a device time column or a fixed sample rate. The tool does not connect to any device; use the Serial monitor in Ohmforge for live data.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "ohmforge_serial_log_to_capture",
        "x-owner-app": "ohmforge",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OhmforgeSerialLogToCaptureInput"
              },
              "examples": {
                "example1": {
                  "summary": "ADC logger with millis() time column, 1 Hz sine",
                  "value": {
                    "log": "[2026-11-02 08:59:59.600] ADC logger v1.2, 50 samples/s\n[2026-11-02 09:00:00.016] 1000,512\n[2026-11-02 09:00:00.032] 1020,562\n[2026-11-02 09:00:00.048] 1040,611\n[2026-11-02 09:00:00.064] 1060,659\n[2026-11-02 09:00:00.096] 1080,705\n[2026-11-02 09:00:00.112] 1100,747\n[2026-11-02 09:00:00.128] 1120,786\n[2026-11-02 09:00:00.144] 1140,820\n[2026-11-02 09:00:00.176] 1160,850\n[2026-11-02 09:00:00.192] 1180,874\n[2026-11-02 09:00:00.208] 1200,892\n[2026-11-02 09:00:00.224] 1220,905\n[2026-11-02 09:00:00.256] 1240,911\n[2026-11-02 09:00:00.272] 1260,911\n[2026-11-02 09:00:00.288] 1280,905\n[2026-11-02 09:00:00.304] 1300,892\n[2026-11-02 09:00:00.336] 1320,874\n[2026-11-02 09:00:00.352] 1340,850\n[2026-11-02 09:00:00.368] 1360,820\n[2026-11-02 09:00:00.384] 1380,786\n[2026-11-02 09:00:00.416] 1400,747\n[2026-11-02 09:00:00.432] 1420,705\n[2026-11-02 09:00:00.448] 1440,659\n[2026-11-02 09:00:00.464] 1460,611\n[2026-11-02 09:00:00.496] 1480,562\n[2026-11-02 09:00:00.512] 1500,512\n[2026-11-02 09:00:00.528] 1520,462\n[2026-11-02 09:00:00.544] 1540,413\n[2026-11-02 09:00:00.576] 1560,365\n[2026-11-02 09:00:00.592] 1580,319\n[2026-11-02 09:00:00.608] 1600,277\n[2026-11-02 09:00:00.624] 1620,238\n[2026-11-02 09:00:00.656] 1640,204\n[2026-11-02 09:00:00.672] 1660,174\n[2026-11-02 09:00:00.688] 1680,150\n[2026-11-02 09:00:00.704] 1700,132\n[2026-11-02 09:00:00.736] 1720,119\n[2026-11-02 09:00:00.752] 1740,113\n[2026-11-02 09:00:00.768] 1760,113\n[2026-11-02 09:00:00.784] 1780,119\n[2026-11-02 09:00:00.816] 1800,132\n[2026-11-02 09:00:00.832] 1820,150\n[2026-11-02 09:00:00.848] 1840,174\n[2026-11-02 09:00:00.864] 1860,204\n[2026-11-02 09:00:00.896] 1880,238\n[2026-11-02 09:00:00.912] 1900,277\n[2026-11-02 09:00:00.928] 1920,319\n[2026-11-02 09:00:00.944] 1940,365\n[2026-11-02 09:00:00.976] 1960,413\n[2026-11-02 09:00:00.992] 1980,462\n[2026-11-02 09:00:01.008] 2000,512\n[2026-11-02 09:00:01.024] 2020,562\n[2026-11-02 09:00:01.056] 2040,611\n[2026-11-02 09:00:01.072] 2060,659\n[2026-11-02 09:00:01.088] 2080,705\n[2026-11-02 09:00:01.104] 2100,747\n[2026-11-02 09:00:01.136] 2120,786\n[2026-11-02 09:00:01.152] 2140,820\n[2026-11-02 09:00:01.168] 2160,850\n[2026-11-02 09:00:01.184] 2180,874\n[2026-11-02 09:00:01.216] 2200,892\n[2026-11-02 09:00:01.232] 2220,905\n[2026-11-02 09:00:01.248] 2240,911\n[2026-11-02 09:00:01.264] 2260,911\n[2026-11-02 09:00:01.296] 2280,905\n[2026-11-02 09:00:01.312] 2300,892\n[2026-11-02 09:00:01.328] 2320,874\n[2026-11-02 09:00:01.344] 2340,850\n[2026-11-02 09:00:01.376] 2360,820\n[2026-11-02 09:00:01.392] 2380,786\n[2026-11-02 09:00:01.408] 2400,747\n[2026-11-02 09:00:01.424] 2420,705\n[2026-11-02 09:00:01.456] 2440,659\n[2026-11-02 09:00:01.472] 2460,611\n[2026-11-02 09:00:01.488] 2480,562\n[2026-11-02 09:00:01.504] 2500,512\n[2026-11-02 09:00:01.536] 2520,462\n[2026-11-02 09:00:01.552] 2540,413\n[2026-11-02 09:00:01.568] 2560,365\n[2026-11-02 09:00:01.584] 2580,319\n[2026-11-02 09:00:01.616] 2600,277\n[2026-11-02 09:00:01.632] 2620,238\n[2026-11-02 09:00:01.648] 2640,204\n[2026-11-02 09:00:01.664] 2660,174\n[2026-11-02 09:00:01.696] 2680,150\n[2026-11-02 09:00:01.712] 2700,132\n[2026-11-02 09:00:01.728] 2720,119\n[2026-11-02 09:00:01.744] 2740,113\n[2026-11-02 09:00:01.776] 2760,113\n[2026-11-02 09:00:01.792] 2780,119\n[2026-11-02 09:00:01.808] 2800,132\n[2026-11-02 09:00:01.824] 2820,150\n[2026-11-02 09:00:01.856] 2840,174\n[2026-11-02 09:00:01.872] 2860,204\n[2026-11-02 09:00:01.888] 2880,238\n[2026-11-02 09:00:01.904] 2900,277\n[2026-11-02 09:00:01.936] 2920,319\n[2026-11-02 09:00:01.952] 2940,365\n[2026-11-02 09:00:01.968] 2960,413\n[2026-11-02 09:00:01.984] 2980,462\n[2026-11-02 09:00:02.016] 3000,512\n[2026-11-02 09:00:02.032] 3020,562\n[2026-11-02 09:00:02.048] 3040,611\n[2026-11-02 09:00:02.064] 3060,659\n[2026-11-02 09:00:02.096] 3080,705\n[2026-11-02 09:00:02.112] 3100,747\n[2026-11-02 09:00:02.128] 3120,786\n[2026-11-02 09:00:02.144] 3140,820\n[2026-11-02 09:00:02.176] 3160,850\n[2026-11-02 09:00:02.192] 3180,874\n[2026-11-02 09:00:02.208] 3200,892\n[2026-11-02 09:00:02.224] 3220,905\n[2026-11-02 09:00:02.256] 3240,911\n[2026-11-02 09:00:02.272] 3260,911\n[2026-11-02 09:00:02.288] 3280,905\n[2026-11-02 09:00:02.304] 3300,892\n[2026-11-02 09:00:02.336] 3320,874\n[2026-11-02 09:00:02.352] 3340,850\n[2026-11-02 09:00:02.368] 3360,820\n[2026-11-02 09:00:02.384] 3380,786\n[2026-11-02 09:00:02.416] 3400,747\n[2026-11-02 09:00:02.432] 3420,705\n[2026-11-02 09:00:02.448] 3440,659\n[2026-11-02 09:00:02.464] 3460,611\n[2026-11-02 09:00:02.496] 3480,562\n[2026-11-02 09:00:02.512] 3500,512\n[2026-11-02 09:00:02.528] 3520,462\n[2026-11-02 09:00:02.544] 3540,413\n[2026-11-02 09:00:02.576] 3560,365\n[2026-11-02 09:00:02.592] 3580,319\n[2026-11-02 09:00:02.608] 3600,277\n[2026-11-02 09:00:02.624] 3620,238\n[2026-11-02 09:00:02.656] 3640,204\n[2026-11-02 09:00:02.672] 3660,174\n[2026-11-02 09:00:02.688] 3680,150\n[2026-11-02 09:00:02.704] 3700,132\n[2026-11-02 09:00:02.736] 3720,119\n[2026-11-02 09:00:02.752] 3740,113\n[2026-11-02 09:00:02.768] 3760,113\n[2026-11-02 09:00:02.784] 3780,119\n[2026-11-02 09:00:02.816] 3800,132\n[2026-11-02 09:00:02.832] 3820,150\n[2026-11-02 09:00:02.848] 3840,174\n[2026-11-02 09:00:02.864] 3860,204\n[2026-11-02 09:00:02.896] 3880,238\n[2026-11-02 09:00:02.912] 3900,277\n[2026-11-02 09:00:02.928] 3920,319\n[2026-11-02 09:00:02.944] 3940,365\n[2026-11-02 09:00:02.976] 3960,413\n[2026-11-02 09:00:02.992] 3980,462\n[2026-11-02 09:00:03.008] 4000,512\n[2026-11-02 09:00:03.024] 4020,562\n[2026-11-02 09:00:03.056] 4040,611\n[2026-11-02 09:00:03.072] 4060,659\n[2026-11-02 09:00:03.088] 4080,705\n[2026-11-02 09:00:03.104] 4100,747\n[2026-11-02 09:00:03.136] 4120,786\n[2026-11-02 09:00:03.152] 4140,820\n[2026-11-02 09:00:03.168] 4160,850\n[2026-11-02 09:00:03.184] 4180,874\n[2026-11-02 09:00:03.216] 4200,892\n[2026-11-02 09:00:03.232] 4220,905\n[2026-11-02 09:00:03.248] 4240,911\n[2026-11-02 09:00:03.264] 4260,911\n[2026-11-02 09:00:03.296] 4280,905\n[2026-11-02 09:00:03.312] 4300,892\n[2026-11-02 09:00:03.328] 4320,874\n[2026-11-02 09:00:03.344] 4340,850\n[2026-11-02 09:00:03.376] 4360,820\n[2026-11-02 09:00:03.392] 4380,786\n[2026-11-02 09:00:03.408] 4400,747\n[2026-11-02 09:00:03.424] 4420,705\n[2026-11-02 09:00:03.456] 4440,659\n[2026-11-02 09:00:03.472] 4460,611\n[2026-11-02 09:00:03.488] 4480,562\n[2026-11-02 09:00:03.504] 4500,512\n[2026-11-02 09:00:03.536] 4520,462\n[2026-11-02 09:00:03.552] 4540,413\n[2026-11-02 09:00:03.568] 4560,365\n[2026-11-02 09:00:03.584] 4580,319\n[2026-11-02 09:00:03.616] 4600,277\n[2026-11-02 09:00:03.632] 4620,238\n[2026-11-02 09:00:03.648] 4640,204\n[2026-11-02 09:00:03.664] 4660,174\n[2026-11-02 09:00:03.696] 4680,150\n[2026-11-02 09:00:03.712] 4700,132\n[2026-11-02 09:00:03.728] 4720,119\n[2026-11-02 09:00:03.744] 4740,113\n[2026-11-02 09:00:03.776] 4760,113\n[2026-11-02 09:00:03.792] 4780,119\n[2026-11-02 09:00:03.808] 4800,132\n[2026-11-02 09:00:03.824] 4820,150\n[2026-11-02 09:00:03.856] 4840,174\n[2026-11-02 09:00:03.872] 4860,204\n[2026-11-02 09:00:03.888] 4880,238\n[2026-11-02 09:00:03.904] 4900,277\n[2026-11-02 09:00:03.936] 4920,319\n[2026-11-02 09:00:03.952] 4940,365\n[2026-11-02 09:00:03.968] 4960,413\n[2026-11-02 09:00:03.984] 4980,462\n",
                    "timeBase": "column",
                    "columnUnit": "ms",
                    "hysteresis": 10
                  }
                },
                "example2": {
                  "summary": "Arduino IDE log: temperature and humidity every 250 ms",
                  "value": {
                    "log": "10:15:29.870 -> BME280 sensor ready\n10:15:29.871 -> temp:°C hum:%\n10:15:30.125 -> temp:21.50 hum:42.0\n10:15:30.375 -> temp:21.56 hum:42.0\n10:15:30.625 -> temp:21.63 hum:42.0\n10:15:30.876 -> temp:21.69 hum:41.9\n10:15:31.125 -> temp:21.75 hum:41.9\n10:15:31.375 -> temp:21.81 hum:41.8\n10:15:31.625 -> temp:21.86 hum:41.8\n10:15:31.876 -> temp:21.92 hum:41.7\n10:15:32.125 -> temp:21.97 hum:41.6\n10:15:32.375 -> temp:22.02 hum:41.5\n10:15:32.625 -> temp:22.07 hum:41.4\n10:15:32.876 -> temp:22.11 hum:41.3\n10:15:33.125 -> temp:22.15 hum:41.2\n10:15:33.375 -> temp:22.18 hum:41.0\n10:15:33.625 -> temp:22.21 hum:40.9\n10:15:33.876 -> temp:22.24 hum:40.8\n10:15:34.125 -> temp:22.26 hum:40.6\n10:15:34.375 -> temp:22.28 hum:40.5\n10:15:34.625 -> temp:22.29 hum:40.3\n10:15:34.876 -> temp:22.30 hum:40.2\n10:15:35.125 -> temp:22.30 hum:40.0\n10:15:35.375 -> temp:22.30 hum:39.8\n10:15:35.625 -> temp:22.29 hum:39.7\n10:15:35.876 -> temp:22.28 hum:39.5\n10:15:36.125 -> temp:22.26 hum:39.4\n10:15:36.375 -> temp:22.24 hum:39.2\n10:15:36.625 -> temp:22.21 hum:39.1\n10:15:36.876 -> temp:22.18 hum:39.0\n10:15:37.125 -> temp:22.15 hum:38.8\n10:15:37.375 -> temp:22.11 hum:38.7\n10:15:37.625 -> temp:22.07 hum:38.6\n10:15:37.876 -> temp:22.02 hum:38.5\n10:15:38.125 -> temp:21.97 hum:38.4\n10:15:38.375 -> temp:21.92 hum:38.3\n10:15:38.625 -> temp:21.86 hum:38.2\n10:15:38.876 -> temp:21.81 hum:38.2\n10:15:39.125 -> temp:21.75 hum:38.1\n10:15:39.375 -> temp:21.69 hum:38.1\n10:15:39.625 -> temp:21.63 hum:38.0\n10:15:39.876 -> temp:21.56 hum:38.0\n10:15:40.125 -> temp:21.50 hum:38.0\n10:15:40.375 -> temp:21.44 hum:38.0\n10:15:40.625 -> temp:21.37 hum:38.0\n10:15:40.876 -> temp:21.31 hum:38.1\n10:15:41.125 -> temp:21.25 hum:38.1\n10:15:41.375 -> temp:21.19 hum:38.2\n10:15:41.625 -> temp:21.14 hum:38.2\n10:15:41.876 -> temp:21.08 hum:38.3\n10:15:42.125 -> temp:21.03 hum:38.4\n10:15:42.375 -> temp:20.98 hum:38.5\n10:15:42.625 -> temp:20.93 hum:38.6\n10:15:42.876 -> temp:20.89 hum:38.7\n10:15:43.125 -> temp:20.85 hum:38.8\n10:15:43.375 -> temp:20.82 hum:39.0\n10:15:43.625 -> temp:20.79 hum:39.1\n10:15:43.876 -> temp:20.76 hum:39.2\n10:15:44.125 -> temp:20.74 hum:39.4\n10:15:44.375 -> temp:20.72 hum:39.5\n10:15:44.625 -> temp:20.71 hum:39.7\n10:15:44.876 -> temp:20.70 hum:39.8\n10:15:45.125 -> temp:20.70 hum:40.0\n10:15:45.375 -> temp:20.70 hum:40.2\n10:15:45.625 -> temp:20.71 hum:40.3\n10:15:45.876 -> temp:20.72 hum:40.5\n10:15:46.125 -> temp:20.74 hum:40.6\n10:15:46.375 -> temp:20.76 hum:40.8\n10:15:46.625 -> temp:20.79 hum:40.9\n10:15:46.876 -> temp:20.82 hum:41.0\n10:15:47.125 -> temp:20.85 hum:41.2\n10:15:47.375 -> temp:20.89 hum:41.3\n10:15:47.625 -> temp:20.93 hum:41.4\n10:15:47.876 -> temp:20.98 hum:41.5\n10:15:48.125 -> temp:21.03 hum:41.6\n10:15:48.375 -> temp:21.08 hum:41.7\n10:15:48.625 -> temp:21.14 hum:41.8\n10:15:48.876 -> temp:21.19 hum:41.8\n10:15:49.125 -> temp:21.25 hum:41.9\n10:15:49.375 -> temp:21.31 hum:41.9\n10:15:49.625 -> temp:21.37 hum:42.0\n10:15:49.876 -> temp:21.44 hum:42.0\n10:15:50.125 -> temp:21.50 hum:42.0\n10:15:50.375 -> temp:21.56 hum:42.0\n10:15:50.625 -> temp:21.63 hum:42.0\n10:15:50.876 -> temp:21.69 hum:41.9\n10:15:51.125 -> temp:21.75 hum:41.9\n10:15:51.375 -> temp:21.81 hum:41.8\n10:15:51.625 -> temp:21.86 hum:41.8\n10:15:51.876 -> temp:21.92 hum:41.7\n10:15:52.125 -> temp:21.97 hum:41.6\n10:15:52.375 -> temp:22.02 hum:41.5\n10:15:52.625 -> temp:22.07 hum:41.4\n10:15:52.876 -> temp:22.11 hum:41.3\n10:15:53.125 -> temp:22.15 hum:41.2\n10:15:53.375 -> temp:22.18 hum:41.0\n10:15:53.625 -> temp:22.21 hum:40.9\n10:15:53.876 -> temp:22.24 hum:40.8\n10:15:54.125 -> temp:22.26 hum:40.6\n10:15:54.375 -> temp:22.28 hum:40.5\n10:15:54.625 -> temp:22.29 hum:40.3\n10:15:54.876 -> temp:22.30 hum:40.2\n10:15:55.125 -> temp:22.30 hum:40.0\n10:15:55.375 -> temp:22.30 hum:39.8\n10:15:55.625 -> temp:22.29 hum:39.7\n10:15:55.876 -> temp:22.28 hum:39.5\n10:15:56.125 -> temp:22.26 hum:39.4\n10:15:56.375 -> temp:22.24 hum:39.2\n10:15:56.625 -> temp:22.21 hum:39.1\n10:15:56.876 -> temp:22.18 hum:39.0\n10:15:57.125 -> temp:22.15 hum:38.8\n10:15:57.375 -> temp:22.11 hum:38.7\n10:15:57.625 -> temp:22.07 hum:38.6\n10:15:57.876 -> temp:22.02 hum:38.5\n10:15:58.125 -> temp:21.97 hum:38.4\n10:15:58.375 -> temp:21.92 hum:38.3\n10:15:58.625 -> temp:21.86 hum:38.2\n10:15:58.876 -> temp:21.81 hum:38.2\n10:15:59.125 -> temp:21.75 hum:38.1\n10:15:59.375 -> temp:21.69 hum:38.1\n10:15:59.625 -> temp:21.63 hum:38.0\n10:15:59.876 -> temp:21.56 hum:38.0\n10:16:00.125 -> temp:21.50 hum:38.0\n10:16:00.375 -> temp:21.44 hum:38.0\n10:16:00.625 -> temp:21.37 hum:38.0\n10:16:00.876 -> temp:21.31 hum:38.1\n10:16:01.125 -> temp:21.25 hum:38.1\n10:16:01.375 -> temp:21.19 hum:38.2\n10:16:01.625 -> temp:21.14 hum:38.2\n10:16:01.876 -> temp:21.08 hum:38.3\n10:16:02.125 -> temp:21.03 hum:38.4\n10:16:02.375 -> temp:20.98 hum:38.5\n10:16:02.625 -> temp:20.93 hum:38.6\n10:16:02.876 -> temp:20.89 hum:38.7\n10:16:03.125 -> temp:20.85 hum:38.8\n10:16:03.375 -> temp:20.82 hum:39.0\n10:16:03.625 -> temp:20.79 hum:39.1\n10:16:03.876 -> temp:20.76 hum:39.2\n10:16:04.125 -> temp:20.74 hum:39.4\n10:16:04.375 -> temp:20.72 hum:39.5\n10:16:04.625 -> temp:20.71 hum:39.7\n10:16:04.876 -> temp:20.70 hum:39.8\n10:16:05.125 -> temp:20.70 hum:40.0\n10:16:05.375 -> temp:20.70 hum:40.2\n10:16:05.625 -> temp:20.71 hum:40.3\n10:16:05.876 -> temp:20.72 hum:40.5\n10:16:06.125 -> temp:20.74 hum:40.6\n10:16:06.375 -> temp:20.76 hum:40.8\n10:16:06.625 -> temp:20.79 hum:40.9\n10:16:06.876 -> temp:20.82 hum:41.0\n10:16:07.125 -> temp:20.85 hum:41.2\n10:16:07.375 -> temp:20.89 hum:41.3\n10:16:07.625 -> temp:20.93 hum:41.4\n10:16:07.876 -> temp:20.98 hum:41.5\n10:16:08.125 -> temp:21.03 hum:41.6\n10:16:08.375 -> temp:21.08 hum:41.7\n10:16:08.625 -> temp:21.14 hum:41.8\n10:16:08.876 -> temp:21.19 hum:41.8\n10:16:09.125 -> temp:21.25 hum:41.9\n10:16:09.375 -> temp:21.31 hum:41.9\n10:16:09.625 -> temp:21.37 hum:42.0\n10:16:09.876 -> temp:21.44 hum:42.0\n10:16:10.125 -> temp:21.50 hum:42.0\n10:16:10.375 -> temp:21.56 hum:42.0\n10:16:10.625 -> temp:21.63 hum:42.0\n10:16:10.876 -> temp:21.69 hum:41.9\n10:16:11.125 -> temp:21.75 hum:41.9\n10:16:11.375 -> temp:21.81 hum:41.8\n10:16:11.625 -> temp:21.86 hum:41.8\n10:16:11.876 -> temp:21.92 hum:41.7\n10:16:12.125 -> temp:21.97 hum:41.6\n10:16:12.375 -> temp:22.02 hum:41.5\n10:16:12.625 -> temp:22.07 hum:41.4\n10:16:12.876 -> temp:22.11 hum:41.3\n10:16:13.125 -> temp:22.15 hum:41.2\n10:16:13.375 -> temp:22.18 hum:41.0\n10:16:13.625 -> temp:22.21 hum:40.9\n10:16:13.876 -> temp:22.24 hum:40.8\n10:16:14.125 -> temp:22.26 hum:40.6\n10:16:14.375 -> temp:22.28 hum:40.5\n10:16:14.625 -> temp:22.29 hum:40.3\n10:16:14.876 -> temp:22.30 hum:40.2\n10:16:15.125 -> temp:22.30 hum:40.0\n10:16:15.375 -> temp:22.30 hum:39.8\n10:16:15.625 -> temp:22.29 hum:39.7\n10:16:15.876 -> temp:22.28 hum:39.5\n10:16:16.125 -> temp:22.26 hum:39.4\n10:16:16.375 -> temp:22.24 hum:39.2\n10:16:16.625 -> temp:22.21 hum:39.1\n10:16:16.876 -> temp:22.18 hum:39.0\n10:16:17.125 -> temp:22.15 hum:38.8\n10:16:17.375 -> temp:22.11 hum:38.7\n10:16:17.625 -> temp:22.07 hum:38.6\n10:16:17.876 -> temp:22.02 hum:38.5\n10:16:18.125 -> temp:21.97 hum:38.4\n10:16:18.375 -> temp:21.92 hum:38.3\n10:16:18.625 -> temp:21.86 hum:38.2\n10:16:18.876 -> temp:21.81 hum:38.2\n10:16:19.125 -> temp:21.75 hum:38.1\n10:16:19.375 -> temp:21.69 hum:38.1\n10:16:19.625 -> temp:21.63 hum:38.0\n10:16:19.876 -> temp:21.56 hum:38.0\n10:16:20.125 -> temp:21.50 hum:38.0\n10:16:20.375 -> temp:21.44 hum:38.0\n10:16:20.625 -> temp:21.37 hum:38.0\n10:16:20.876 -> temp:21.31 hum:38.1\n10:16:21.125 -> temp:21.25 hum:38.1\n10:16:21.375 -> temp:21.19 hum:38.2\n10:16:21.625 -> temp:21.14 hum:38.2\n10:16:21.876 -> temp:21.08 hum:38.3\n10:16:22.125 -> temp:21.03 hum:38.4\n10:16:22.375 -> temp:20.98 hum:38.5\n10:16:22.625 -> temp:20.93 hum:38.6\n10:16:22.876 -> temp:20.89 hum:38.7\n10:16:23.125 -> temp:20.85 hum:38.8\n10:16:23.375 -> temp:20.82 hum:39.0\n10:16:23.625 -> temp:20.79 hum:39.1\n10:16:23.876 -> temp:20.76 hum:39.2\n10:16:24.125 -> temp:20.74 hum:39.4\n10:16:24.375 -> temp:20.72 hum:39.5\n10:16:24.625 -> temp:20.71 hum:39.7\n10:16:24.876 -> temp:20.70 hum:39.8\n10:16:25.125 -> temp:20.70 hum:40.0\n10:16:25.375 -> temp:20.70 hum:40.2\n10:16:25.625 -> temp:20.71 hum:40.3\n10:16:25.876 -> temp:20.72 hum:40.5\n10:16:26.125 -> temp:20.74 hum:40.6\n10:16:26.375 -> temp:20.76 hum:40.8\n10:16:26.625 -> temp:20.79 hum:40.9\n10:16:26.876 -> temp:20.82 hum:41.0\n10:16:27.125 -> temp:20.85 hum:41.2\n10:16:27.375 -> temp:20.89 hum:41.3\n10:16:27.625 -> temp:20.93 hum:41.4\n10:16:27.876 -> temp:20.98 hum:41.5\n10:16:28.125 -> temp:21.03 hum:41.6\n10:16:28.375 -> temp:21.08 hum:41.7\n10:16:28.625 -> temp:21.14 hum:41.8\n10:16:28.876 -> temp:21.19 hum:41.8\n10:16:29.125 -> temp:21.25 hum:41.9\n10:16:29.375 -> temp:21.31 hum:41.9\n10:16:29.625 -> temp:21.37 hum:42.0\n10:16:29.876 -> temp:21.44 hum:42.0\n",
                    "timeBase": "auto",
                    "columnUnit": "ms",
                    "unit": "",
                    "hysteresis": 10
                  }
                },
                "example3": {
                  "summary": "RC low-pass step response at a fixed 1 kHz (no time stamps)",
                  "value": {
                    "log": "5.00\t0.000\n5.00\t0.476\n5.00\t0.906\n5.00\t1.296\n5.00\t1.648\n5.00\t1.967\n5.00\t2.256\n5.00\t2.517\n5.00\t2.753\n5.00\t2.967\n5.00\t3.161\n5.00\t3.336\n5.00\t3.494\n5.00\t3.637\n5.00\t3.767\n5.00\t3.884\n5.00\t3.991\n5.00\t4.087\n5.00\t4.174\n5.00\t4.252\n5.00\t4.323\n5.00\t4.388\n5.00\t4.446\n5.00\t4.499\n5.00\t4.546\n5.00\t4.590\n5.00\t4.629\n5.00\t4.664\n5.00\t4.696\n5.00\t4.725\n5.00\t4.751\n5.00\t4.775\n5.00\t4.796\n5.00\t4.816\n5.00\t4.833\n5.00\t4.849\n5.00\t4.863\n5.00\t4.876\n5.00\t4.888\n5.00\t4.899\n5.00\t4.908\n5.00\t4.917\n5.00\t4.925\n5.00\t4.932\n5.00\t4.939\n5.00\t4.944\n5.00\t4.950\n5.00\t4.955\n5.00\t4.959\n5.00\t4.963\n0.00\t4.966\n0.00\t4.494\n0.00\t4.066\n0.00\t3.679\n0.00\t3.329\n0.00\t3.012\n0.00\t2.726\n0.00\t2.466\n0.00\t2.232\n0.00\t2.019\n0.00\t1.827\n0.00\t1.653\n0.00\t1.496\n0.00\t1.353\n0.00\t1.225\n0.00\t1.108\n0.00\t1.003\n0.00\t0.907\n0.00\t0.821\n0.00\t0.743\n0.00\t0.672\n0.00\t0.608\n0.00\t0.550\n0.00\t0.498\n0.00\t0.451\n0.00\t0.408\n0.00\t0.369\n0.00\t0.334\n0.00\t0.302\n0.00\t0.273\n0.00\t0.247\n0.00\t0.224\n0.00\t0.202\n0.00\t0.183\n0.00\t0.166\n0.00\t0.150\n0.00\t0.136\n0.00\t0.123\n0.00\t0.111\n0.00\t0.101\n0.00\t0.091\n0.00\t0.082\n0.00\t0.074\n0.00\t0.067\n0.00\t0.061\n0.00\t0.055\n0.00\t0.050\n0.00\t0.045\n0.00\t0.041\n0.00\t0.037\n5.00\t0.033\n5.00\t0.506\n5.00\t0.934\n5.00\t1.321\n5.00\t1.671\n5.00\t1.988\n5.00\t2.274\n5.00\t2.534\n5.00\t2.768\n5.00\t2.981\n5.00\t3.173\n5.00\t3.347\n5.00\t3.504\n5.00\t3.646\n5.00\t3.775\n5.00\t3.892\n5.00\t3.997\n5.00\t4.093\n5.00\t4.179\n5.00\t4.257\n5.00\t4.328\n5.00\t4.392\n5.00\t4.450\n5.00\t4.502\n5.00\t4.549\n5.00\t4.592\n5.00\t4.631\n5.00\t4.666\n5.00\t4.698\n5.00\t4.727\n5.00\t4.753\n5.00\t4.776\n5.00\t4.798\n5.00\t4.817\n5.00\t4.834\n5.00\t4.850\n5.00\t4.864\n5.00\t4.877\n5.00\t4.889\n5.00\t4.899\n5.00\t4.909\n5.00\t4.918\n5.00\t4.926\n5.00\t4.933\n5.00\t4.939\n5.00\t4.945\n5.00\t4.950\n5.00\t4.955\n5.00\t4.959\n5.00\t4.963\n0.00\t4.967\n0.00\t4.494\n0.00\t4.066\n0.00\t3.679\n0.00\t3.329\n0.00\t3.012\n0.00\t2.726\n0.00\t2.466\n0.00\t2.232\n0.00\t2.019\n0.00\t1.827\n0.00\t1.653\n0.00\t1.496\n0.00\t1.354\n0.00\t1.225\n0.00\t1.108\n0.00\t1.003\n0.00\t0.907\n0.00\t0.821\n0.00\t0.743\n0.00\t0.672\n0.00\t0.608\n0.00\t0.550\n0.00\t0.498\n0.00\t0.451\n0.00\t0.408\n0.00\t0.369\n0.00\t0.334\n0.00\t0.302\n0.00\t0.273\n0.00\t0.247\n0.00\t0.224\n0.00\t0.202\n0.00\t0.183\n0.00\t0.166\n0.00\t0.150\n0.00\t0.136\n0.00\t0.123\n0.00\t0.111\n0.00\t0.101\n0.00\t0.091\n0.00\t0.082\n0.00\t0.074\n0.00\t0.067\n0.00\t0.061\n0.00\t0.055\n0.00\t0.050\n0.00\t0.045\n0.00\t0.041\n0.00\t0.037\n5.00\t0.033\n5.00\t0.506\n5.00\t0.934\n5.00\t1.321\n5.00\t1.671\n5.00\t1.988\n5.00\t2.274\n5.00\t2.534\n5.00\t2.768\n5.00\t2.981\n5.00\t3.173\n5.00\t3.347\n5.00\t3.504\n5.00\t3.646\n5.00\t3.775\n5.00\t3.892\n5.00\t3.997\n5.00\t4.093\n5.00\t4.179\n5.00\t4.257\n5.00\t4.328\n5.00\t4.392\n5.00\t4.450\n5.00\t4.502\n5.00\t4.549\n5.00\t4.592\n5.00\t4.631\n5.00\t4.666\n5.00\t4.698\n5.00\t4.727\n5.00\t4.753\n5.00\t4.776\n5.00\t4.798\n5.00\t4.817\n5.00\t4.834\n5.00\t4.850\n5.00\t4.864\n5.00\t4.877\n5.00\t4.889\n5.00\t4.899\n5.00\t4.909\n5.00\t4.918\n5.00\t4.926\n5.00\t4.933\n5.00\t4.939\n5.00\t4.945\n5.00\t4.950\n5.00\t4.955\n5.00\t4.959\n5.00\t4.963\n0.00\t4.967\n0.00\t4.494\n0.00\t4.066\n0.00\t3.679\n0.00\t3.329\n0.00\t3.012\n0.00\t2.726\n0.00\t2.466\n0.00\t2.232\n0.00\t2.019\n0.00\t1.827\n0.00\t1.653\n0.00\t1.496\n0.00\t1.354\n0.00\t1.225\n0.00\t1.108\n0.00\t1.003\n0.00\t0.907\n0.00\t0.821\n0.00\t0.743\n0.00\t0.672\n0.00\t0.608\n0.00\t0.550\n0.00\t0.498\n0.00\t0.451\n0.00\t0.408\n0.00\t0.369\n0.00\t0.334\n0.00\t0.302\n0.00\t0.273\n0.00\t0.247\n0.00\t0.224\n0.00\t0.202\n0.00\t0.183\n0.00\t0.166\n0.00\t0.150\n0.00\t0.136\n0.00\t0.123\n0.00\t0.111\n0.00\t0.101\n0.00\t0.091\n0.00\t0.082\n0.00\t0.074\n0.00\t0.067\n0.00\t0.061\n0.00\t0.055\n0.00\t0.050\n0.00\t0.045\n0.00\t0.041\n0.00\t0.037\n5.00\t0.033\n5.00\t0.506\n5.00\t0.934\n5.00\t1.321\n5.00\t1.671\n5.00\t1.988\n5.00\t2.274\n5.00\t2.534\n5.00\t2.768\n5.00\t2.981\n5.00\t3.173\n5.00\t3.347\n5.00\t3.504\n5.00\t3.646\n5.00\t3.775\n5.00\t3.892\n5.00\t3.997\n5.00\t4.093\n5.00\t4.179\n5.00\t4.257\n5.00\t4.328\n5.00\t4.392\n5.00\t4.450\n5.00\t4.502\n5.00\t4.549\n5.00\t4.592\n5.00\t4.631\n5.00\t4.666\n5.00\t4.698\n5.00\t4.727\n5.00\t4.753\n5.00\t4.776\n5.00\t4.798\n5.00\t4.817\n5.00\t4.834\n5.00\t4.850\n5.00\t4.864\n5.00\t4.877\n5.00\t4.889\n5.00\t4.899\n5.00\t4.909\n5.00\t4.918\n5.00\t4.926\n5.00\t4.933\n5.00\t4.939\n5.00\t4.945\n5.00\t4.950\n5.00\t4.955\n5.00\t4.959\n5.00\t4.963\n0.00\t4.967\n0.00\t4.494\n0.00\t4.066\n0.00\t3.679\n0.00\t3.329\n0.00\t3.012\n0.00\t2.726\n0.00\t2.466\n0.00\t2.232\n0.00\t2.019\n0.00\t1.827\n0.00\t1.653\n0.00\t1.496\n0.00\t1.354\n0.00\t1.225\n0.00\t1.108\n0.00\t1.003\n0.00\t0.907\n0.00\t0.821\n0.00\t0.743\n0.00\t0.672\n0.00\t0.608\n0.00\t0.550\n0.00\t0.498\n0.00\t0.451\n0.00\t0.408\n0.00\t0.369\n0.00\t0.334\n0.00\t0.302\n0.00\t0.273\n0.00\t0.247\n0.00\t0.224\n0.00\t0.202\n0.00\t0.183\n0.00\t0.166\n0.00\t0.150\n0.00\t0.136\n0.00\t0.123\n0.00\t0.111\n0.00\t0.101\n0.00\t0.091\n0.00\t0.082\n0.00\t0.074\n0.00\t0.067\n0.00\t0.061\n0.00\t0.055\n0.00\t0.050\n0.00\t0.045\n0.00\t0.041\n0.00\t0.037\n",
                    "timeBase": "rate",
                    "sampleRate": 1000,
                    "columnUnit": "ms",
                    "unit": "V",
                    "hysteresis": 10
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OhmforgeSerialLogToCaptureResult"
                }
              }
            }
          },
          "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/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "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"
                }
              }
            }
          }
        }
      },
      "OhmforgeSerialLogToCaptureInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "Log file",
            "description": "A text log saved by a serial monitor; up to 10 MB and 200 000 lines. Processed in memory and not kept. Upload as {filename, contentType?, contentBase64}. Max 10240 KiB. Accepts .txt,.log,.csv,.tsv,text/plain,text/csv.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "log": {
            "title": "Or paste the log",
            "description": "Used when no file is uploaded.",
            "type": "string",
            "maxLength": 500000
          },
          "timeBase": {
            "title": "Time base",
            "type": "string",
            "enum": [
              "auto",
              "received",
              "column",
              "rate"
            ],
            "default": "auto"
          },
          "sampleRate": {
            "title": "Sample rate (lines per second, for a fixed sample rate)",
            "type": "number",
            "minimum": 0.000001,
            "maximum": 10000000,
            "x-unit": "Hz"
          },
          "columnUnit": {
            "title": "Unit of the device time column",
            "type": "string",
            "enum": [
              "ms",
              "us",
              "s"
            ],
            "default": "ms"
          },
          "series": {
            "title": "Series to use (optional)",
            "description": "Comma-separated names (\"Value 1\" for unlabelled numbers); empty = the first four.",
            "type": "string",
            "maxLength": 300
          },
          "unit": {
            "title": "Unit of the values (optional)",
            "description": "Shown with the measurements, e.g. V, A or °C; empty = plain numbers.",
            "type": "string",
            "maxLength": 8
          },
          "hysteresis": {
            "title": "Crossing hysteresis",
            "description": "Noise smaller than this band does not count as a crossing.",
            "type": "number",
            "minimum": 0,
            "maximum": 50,
            "default": 10,
            "x-unit": "% of amplitude"
          }
        },
        "required": []
      },
      "OhmforgeSerialLogToCaptureResult": {
        "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": [
              "lines",
              "dataLines",
              "textLines",
              "timestampFormat",
              "timeBase",
              "series",
              "channelsUsed",
              "timeSeries",
              "samples",
              "droppedIncomplete",
              "durationSeconds",
              "sampleRate",
              "uniform",
              "channels",
              "notes"
            ],
            "properties": {
              "lines": {
                "type": "integer"
              },
              "dataLines": {
                "type": "integer"
              },
              "textLines": {
                "type": "integer",
                "description": "Lines without numbers (messages, headers), skipped."
              },
              "timestampFormat": {
                "type": "string",
                "enum": [
                  "bracket-datetime",
                  "arduino",
                  "bracket-seconds",
                  "none"
                ]
              },
              "timeBase": {
                "type": "string",
                "enum": [
                  "received",
                  "rate",
                  "column"
                ]
              },
              "series": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "All series names found in the log."
              },
              "channelsUsed": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "timeSeries": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Series used as the device time column."
              },
              "samples": {
                "type": "integer"
              },
              "droppedIncomplete": {
                "type": "integer"
              },
              "durationSeconds": {
                "type": "number"
              },
              "sampleRate": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "From the median interval between lines."
              },
              "uniform": {
                "type": "boolean"
              },
              "channels": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "unit",
                    "min",
                    "max",
                    "vpp",
                    "mean",
                    "rms",
                    "rmsAc",
                    "cycleMean",
                    "cycleRms",
                    "wholePeriods",
                    "top",
                    "base",
                    "amplitude",
                    "stateMethod",
                    "frequency",
                    "period",
                    "periodJitter",
                    "dutyPercent",
                    "positiveWidth",
                    "negativeWidth",
                    "riseTime",
                    "fallTime",
                    "riseCount",
                    "fallCount",
                    "overshootPercent",
                    "preshootPercent"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "unit": {
                      "type": "string"
                    },
                    "min": {
                      "type": "number"
                    },
                    "max": {
                      "type": "number"
                    },
                    "vpp": {
                      "type": "number"
                    },
                    "mean": {
                      "type": "number"
                    },
                    "rms": {
                      "type": "number",
                      "description": "True RMS including DC (whole record)."
                    },
                    "rmsAc": {
                      "type": "number",
                      "description": "RMS of the AC part: √(RMS² − mean²)."
                    },
                    "cycleMean": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "cycleRms": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "RMS over the whole periods between the first and last rising crossing."
                    },
                    "wholePeriods": {
                      "type": "integer"
                    },
                    "top": {
                      "type": "number"
                    },
                    "base": {
                      "type": "number"
                    },
                    "amplitude": {
                      "type": "number"
                    },
                    "stateMethod": {
                      "type": "string",
                      "enum": [
                        "histogram",
                        "minmax"
                      ]
                    },
                    "frequency": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "period": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "periodJitter": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "Standard deviation of the single periods (s)."
                    },
                    "dutyPercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "positiveWidth": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "negativeWidth": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "riseTime": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "description": "10–90 % rise time, mean over riseCount edges (s)."
                    },
                    "fallTime": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "riseCount": {
                      "type": "integer"
                    },
                    "fallCount": {
                      "type": "integer"
                    },
                    "overshootPercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "preshootPercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              },
              "notes": {
                "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"
              }
            }
          }
        }
      }
    }
  }
}