{
  "openapi": "3.1.0",
  "info": {
    "title": "PixelTach API",
    "version": "1.0.0",
    "summary": "Video timing, bandwidth and connector-fit calculations, as a stateless API and an MCP server.",
    "description": "Exact video timing (VESA CVT, reduced blanking, CTA-861), pixel clocks, bandwidth, and whether a signal fits HDMI, DisplayPort, SDI or ST 2110, from the same engine as the PixelTach calculator at https://pixeltach.com.\n\nStateless: nothing you send is stored, and request bodies are never logged. Every response carries `engineVersion`, and echoes the inputs as used with a `defaulted` list, so a result can always be reproduced. Rate-limited per IP address. Cable length and reach are not modelled.\n\nPixelTach is built and maintained by one developer, and this API is free. If it saves you time, the annual Supporter subscription at https://pixeltach.com is what pays for the hosting and keeps it running.",
    "contact": {
      "name": "PixelTach",
      "url": "https://pixeltach.com"
    }
  },
  "servers": [
    {
      "url": "https://api.pixeltach.com"
    }
  ],
  "tags": [
    {
      "name": "Calculations"
    },
    {
      "name": "MCP"
    },
    {
      "name": "Service"
    }
  ],
  "paths": {
    "/v1/timing": {
      "post": {
        "operationId": "calculateTiming",
        "tags": [
          "Calculations"
        ],
        "summary": "Calculate video timing and bandwidth",
        "description": "Timing for a resolution and refresh rate: horizontal and vertical active, front porch, sync width, back porch, totals, sync polarity, pixel clock, line rate, and the bandwidth the link must carry. Send one signal, or `{ \"signals\": [ ... ] }` for up to 50.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TimingSignal"
                  },
                  {
                    "$ref": "#/components/schemas/TimingBatch"
                  }
                ]
              },
              "examples": {
                "one signal": {
                  "summary": "one signal",
                  "value": {
                    "id": "cam-1",
                    "width": 3840,
                    "height": 2160,
                    "refreshHz": 59.94,
                    "blanking": "rb2opt",
                    "bpc": 10,
                    "format": "422"
                  }
                },
                "a batch (the second signal is invalid and fails alone)": {
                  "summary": "a batch (the second signal is invalid and fails alone)",
                  "value": {
                    "signals": [
                      {
                        "id": "a",
                        "width": 1920,
                        "height": 1080,
                        "refreshHz": 60,
                        "standard": "cta"
                      },
                      {
                        "id": "typo",
                        "width": 99999,
                        "height": 1080,
                        "refreshHz": 60
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The calculation. In a batch, each entry of `results` is either a result or `{ ok: false, error }` for that signal alone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimingResponse"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "results": [
                    {
                      "id": "cam-1",
                      "ok": true,
                      "input": {
                        "width": 3840,
                        "height": 2160,
                        "refreshHz": 59.94,
                        "standard": "cvt",
                        "blanking": "rb2opt",
                        "clockMode": "exact",
                        "bpc": 10,
                        "format": "422",
                        "audio": {
                          "channels": 0,
                          "rateHz": 48000
                        }
                      },
                      "defaulted": [
                        "standard",
                        "clockMode",
                        "audio"
                      ],
                      "timing": {
                        "standard": "CVT-RBv2 video-optimized",
                        "horizontal": {
                          "active": 3840,
                          "frontPorch": 8,
                          "syncWidth": 32,
                          "backPorch": 40,
                          "total": 3920,
                          "polarity": "+"
                        },
                        "vertical": {
                          "active": 2160,
                          "frontPorch": 48,
                          "syncWidth": 8,
                          "backPorch": 6,
                          "total": 2222,
                          "polarity": "-"
                        },
                        "pixelClockHz": 522090000,
                        "hFreqHz": 133186.224,
                        "refreshHz": 59.9398,
                        "notes": [
                          "Video-optimized: timing built for 60 Hz, clock ×1000/1001 → 59.940 Hz.",
                          "Exact-refresh clock: CVT porches, clock rounded down to 10 kHz."
                        ]
                      },
                      "bandwidth": {
                        "bitsPerPixel": 20,
                        "linkDataRateBps": 10441800000,
                        "linkDataRateGbps": 10.442,
                        "activeDataRateBps": 9943292713
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, or is not an object, or `signals` is empty or combined with other fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "The request body is not valid JSON."
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than 32 KB, or the batch has more than 50 signals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "The request body is larger than 32 KB."
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type header is not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "Send the request with the header Content-Type: application/json."
                }
              }
            }
          },
          "422": {
            "description": "A single (non-batch) signal could not be calculated: an unknown field, a value outside the allowed set, or a size or rate the engine can't build. `results[0].error` says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimingResponse"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "results": [
                    {
                      "ok": false,
                      "error": "Width must be 64–16384 pixels."
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait a few seconds and try again, and send signals in batches instead of one by one."
          }
        }
      }
    },
    "/v1/link": {
      "post": {
        "operationId": "checkLink",
        "tags": [
          "Calculations"
        ],
        "summary": "Check a signal against connectors",
        "description": "Everything `/v1/timing` returns, plus a verdict for each connector (HDMI 1.4 to 2.2, DisplayPort 1.2 to 2.1, SDI, ST 2110 over 10 to 100 GbE): fits, tight, exceeds or unsupported, with percent used, headroom, the limiting factor and the lowest-cost change that would make it fit. Verdicts are about data rate; cable length and reach are not modelled.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/LinkSignal"
                  },
                  {
                    "$ref": "#/components/schemas/LinkBatch"
                  }
                ]
              },
              "examples": {
                "one signal": {
                  "summary": "one signal",
                  "value": {
                    "id": "program",
                    "width": 1920,
                    "height": 1080,
                    "refreshHz": 59.94,
                    "standard": "cta",
                    "bpc": 10,
                    "format": "422",
                    "connectors": [
                      "hdmi20",
                      "sdi"
                    ]
                  }
                },
                "a batch (the second signal is invalid and fails alone)": {
                  "summary": "a batch (the second signal is invalid and fails alone)",
                  "value": {
                    "signals": [
                      {
                        "id": "a",
                        "width": 1920,
                        "height": 1080,
                        "refreshHz": 60,
                        "standard": "cta"
                      },
                      {
                        "id": "typo",
                        "width": 99999,
                        "height": 1080,
                        "refreshHz": 60
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The calculation. In a batch, each entry of `results` is either a result or `{ ok: false, error }` for that signal alone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "results": [
                    {
                      "id": "program",
                      "ok": true,
                      "input": {
                        "width": 1920,
                        "height": 1080,
                        "refreshHz": 59.94,
                        "standard": "cta",
                        "blanking": "cvt",
                        "clockMode": "exact",
                        "bpc": 10,
                        "format": "422",
                        "audio": {
                          "channels": 0,
                          "rateHz": 48000
                        }
                      },
                      "defaulted": [
                        "blanking",
                        "clockMode",
                        "audio"
                      ],
                      "timing": {
                        "standard": "CTA-861 VIC 16",
                        "vic": 16,
                        "horizontal": {
                          "active": 1920,
                          "frontPorch": 88,
                          "syncWidth": 44,
                          "backPorch": 148,
                          "total": 2200,
                          "polarity": "+"
                        },
                        "vertical": {
                          "active": 1080,
                          "frontPorch": 4,
                          "syncWidth": 5,
                          "backPorch": 36,
                          "total": 1125,
                          "polarity": "+"
                        },
                        "pixelClockHz": 148351648,
                        "hFreqHz": 67432.567,
                        "refreshHz": 59.9401,
                        "notes": [
                          "Timing fixed by CTA-861 (VIC 16). VIC 16 covers both 60 and 59.94 Hz; the EDID lists the VIC so the source can use either."
                        ]
                      },
                      "bandwidth": {
                        "bitsPerPixel": 20,
                        "linkDataRateBps": 2967032960,
                        "linkDataRateGbps": 2.967,
                        "activeDataRateBps": 2485834160
                      },
                      "verdicts": [
                        {
                          "id": "hdmi20",
                          "name": "HDMI 2.0",
                          "family": "hdmi",
                          "status": "fits",
                          "detail": "TMDS character rate 148.35 MHz of 600.00 MHz",
                          "limitingFactor": {
                            "kind": "tmds-clock",
                            "label": "TMDS character rate (600.00 MHz maximum)"
                          },
                          "usagePct": 24.73,
                          "headroomPct": 75.27
                        },
                        {
                          "id": "sdi",
                          "name": "SDI",
                          "family": "sdi",
                          "status": "fits",
                          "sdi": {
                            "rateBps": 2967032967.032967,
                            "needed": "3G-SDI",
                            "standard": "SMPTE ST 425-1",
                            "ladder": [
                              {
                                "name": "HD-SDI",
                                "smpte": "SMPTE ST 292-1",
                                "rateBps": 1483516483.5164835,
                                "state": "no"
                              },
                              {
                                "name": "3G-SDI",
                                "smpte": "SMPTE ST 424",
                                "rateBps": 2967032967.032967,
                                "state": "needed"
                              },
                              {
                                "name": "6G-SDI",
                                "smpte": "SMPTE ST 2081",
                                "rateBps": 5934065934.065934,
                                "state": "higher"
                              },
                              {
                                "name": "12G-SDI",
                                "smpte": "SMPTE ST 2082",
                                "rateBps": 11868131868.131868,
                                "state": "higher"
                              },
                              {
                                "name": "24G-SDI",
                                "smpte": "SMPTE ST 2083",
                                "rateBps": 23736263736.263737,
                                "state": "higher"
                              }
                            ],
                            "alternatives": []
                          },
                          "detail": "3G-SDI (SMPTE ST 425-1), 10-bit YCbCr 4:2:2. SDI uses standard SMPTE blanking, not this EDID timing.",
                          "limitingFactor": {
                            "kind": "sdi-link",
                            "label": "3G-SDI is the lowest single SDI link that carries it"
                          }
                        }
                      ],
                      "summary": {
                        "fits": [
                          "hdmi20",
                          "sdi"
                        ],
                        "tight": [],
                        "exceeds": [],
                        "unsupported": [],
                        "check": []
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, or is not an object, or `signals` is empty or combined with other fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "The request body is not valid JSON."
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than 32 KB, or the batch has more than 50 signals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "The request body is larger than 32 KB."
                }
              }
            }
          },
          "415": {
            "description": "The Content-Type header is not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestError"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "error": "Send the request with the header Content-Type: application/json."
                }
              }
            }
          },
          "422": {
            "description": "A single (non-batch) signal could not be calculated: an unknown field, a value outside the allowed set, or a size or rate the engine can't build. `results[0].error` says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                },
                "example": {
                  "engineVersion": "0.1.0",
                  "results": [
                    {
                      "ok": false,
                      "error": "Width must be 64–16384 pixels."
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait a few seconds and try again, and send signals in batches instead of one by one."
          }
        }
      }
    },
    "/v1/health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Service"
        ],
        "summary": "Service status and engine version",
        "responses": {
          "200": {
            "description": "The service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "engineVersion": {
                      "type": "string"
                    },
                    "apiVersion": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "engineVersion",
                    "apiVersion"
                  ]
                },
                "example": {
                  "ok": true,
                  "engineVersion": "0.1.0",
                  "apiVersion": "1"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "tags": [
          "MCP"
        ],
        "summary": "MCP server (Streamable HTTP)",
        "description": "A remote Model Context Protocol server exposing the tools `calculate_timing` and `check_link`, with the same inputs and outputs as the REST endpoints for a single signal. Point an MCP client at `https://api.pixeltach.com/mcp`. It is stateless: no session, nothing stored.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "A JSON-RPC 2.0 message."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response, as JSON or a server-sent event stream."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TimingSignal": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Your own label for this signal (for example a cable number). Echoed back unchanged.",
            "type": "string",
            "maxLength": 64
          },
          "width": {
            "type": "integer",
            "minimum": 64,
            "maximum": 16384,
            "description": "Active pixels across, for example 3840."
          },
          "height": {
            "type": "integer",
            "minimum": 64,
            "maximum": 16384,
            "description": "Active lines down, for example 2160."
          },
          "refreshHz": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "description": "Refresh rate in Hz. Fractional rates are exact: 59.94, 29.97, 23.976, 119.88."
          },
          "standard": {
            "description": "\"cvt\" (default) = timing built with the VESA CVT formulas (the blanking field applies). \"cta\" = the fixed CTA-861 table timing for a standard format such as 1920x1080 at 59.94 (blanking and clockMode are ignored).",
            "type": "string",
            "enum": [
              "cvt",
              "cta"
            ]
          },
          "blanking": {
            "description": "Blanking for standard \"cvt\": \"cvt\" (default, CRT-style), \"rb1\" (reduced blanking v1), \"rb2\" (reduced blanking v2) or \"rb2opt\" (RB v2 video-optimized: built for the whole rate, clock x 1000/1001).",
            "type": "string",
            "enum": [
              "cvt",
              "rb1",
              "rb2",
              "rb2opt"
            ]
          },
          "clockMode": {
            "description": "\"exact\" (default) keeps the CVT porches and sets the pixel clock so the refresh rate is exactly what you asked for (rounded down to 10 kHz). \"strict\" rounds the clock to the CVT clock step, so the refresh rate comes out slightly different.",
            "type": "string",
            "enum": [
              "exact",
              "strict"
            ]
          },
          "bpc": {
            "description": "Bits per colour component: 8 (default), 10 or 12.",
            "type": "number",
            "enum": [
              8,
              10,
              12
            ]
          },
          "format": {
            "description": "Colour format: \"rgb\", \"444\", \"422\" (default) or \"420\".",
            "type": "string",
            "enum": [
              "420",
              "422",
              "444",
              "rgb"
            ]
          },
          "audio": {
            "type": "object",
            "properties": {
              "channels": {
                "type": "number",
                "enum": [
                  0,
                  2,
                  8
                ],
                "description": "0 = no audio, 2 = stereo, 8 = eight channels (LPCM)."
              },
              "rateHz": {
                "description": "Sample rate in Hz. Default 48000.",
                "type": "number",
                "enum": [
                  48000,
                  96000,
                  192000
                ]
              }
            },
            "required": [
              "channels"
            ],
            "additionalProperties": false,
            "description": "Embedded audio the signal must carry. Used for the HDMI blanking-room check and the SDI / ST 2110 audio notes."
          }
        },
        "required": [
          "width",
          "height",
          "refreshHz"
        ],
        "additionalProperties": false
      },
      "LinkSignal": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Your own label for this signal (for example a cable number). Echoed back unchanged.",
            "type": "string",
            "maxLength": 64
          },
          "width": {
            "type": "integer",
            "minimum": 64,
            "maximum": 16384,
            "description": "Active pixels across, for example 3840."
          },
          "height": {
            "type": "integer",
            "minimum": 64,
            "maximum": 16384,
            "description": "Active lines down, for example 2160."
          },
          "refreshHz": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "description": "Refresh rate in Hz. Fractional rates are exact: 59.94, 29.97, 23.976, 119.88."
          },
          "standard": {
            "description": "\"cvt\" (default) = timing built with the VESA CVT formulas (the blanking field applies). \"cta\" = the fixed CTA-861 table timing for a standard format such as 1920x1080 at 59.94 (blanking and clockMode are ignored).",
            "type": "string",
            "enum": [
              "cvt",
              "cta"
            ]
          },
          "blanking": {
            "description": "Blanking for standard \"cvt\": \"cvt\" (default, CRT-style), \"rb1\" (reduced blanking v1), \"rb2\" (reduced blanking v2) or \"rb2opt\" (RB v2 video-optimized: built for the whole rate, clock x 1000/1001).",
            "type": "string",
            "enum": [
              "cvt",
              "rb1",
              "rb2",
              "rb2opt"
            ]
          },
          "clockMode": {
            "description": "\"exact\" (default) keeps the CVT porches and sets the pixel clock so the refresh rate is exactly what you asked for (rounded down to 10 kHz). \"strict\" rounds the clock to the CVT clock step, so the refresh rate comes out slightly different.",
            "type": "string",
            "enum": [
              "exact",
              "strict"
            ]
          },
          "bpc": {
            "description": "Bits per colour component: 8 (default), 10 or 12.",
            "type": "number",
            "enum": [
              8,
              10,
              12
            ]
          },
          "format": {
            "description": "Colour format: \"rgb\", \"444\", \"422\" (default) or \"420\".",
            "type": "string",
            "enum": [
              "420",
              "422",
              "444",
              "rgb"
            ]
          },
          "audio": {
            "type": "object",
            "properties": {
              "channels": {
                "type": "number",
                "enum": [
                  0,
                  2,
                  8
                ],
                "description": "0 = no audio, 2 = stereo, 8 = eight channels (LPCM)."
              },
              "rateHz": {
                "description": "Sample rate in Hz. Default 48000.",
                "type": "number",
                "enum": [
                  48000,
                  96000,
                  192000
                ]
              }
            },
            "required": [
              "channels"
            ],
            "additionalProperties": false,
            "description": "Embedded audio the signal must carry. Used for the HDMI blanking-room check and the SDI / ST 2110 audio notes."
          },
          "connectors": {
            "description": "Only report these connectors. Each entry is a connector id (for example \"hdmi20\", \"dp14\", \"sdi\") or a family: \"hdmi\", \"dp\", \"sdi\" or \"ip\" (ST 2110 over Ethernet). Default: all.",
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "width",
          "height",
          "refreshHz"
        ],
        "additionalProperties": false
      },
      "TimingBatch": {
        "type": "object",
        "properties": {
          "signals": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "description": "Your own label for this signal (for example a cable number). Echoed back unchanged.",
                  "type": "string",
                  "maxLength": 64
                },
                "width": {
                  "type": "integer",
                  "minimum": 64,
                  "maximum": 16384,
                  "description": "Active pixels across, for example 3840."
                },
                "height": {
                  "type": "integer",
                  "minimum": 64,
                  "maximum": 16384,
                  "description": "Active lines down, for example 2160."
                },
                "refreshHz": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 1000,
                  "description": "Refresh rate in Hz. Fractional rates are exact: 59.94, 29.97, 23.976, 119.88."
                },
                "standard": {
                  "description": "\"cvt\" (default) = timing built with the VESA CVT formulas (the blanking field applies). \"cta\" = the fixed CTA-861 table timing for a standard format such as 1920x1080 at 59.94 (blanking and clockMode are ignored).",
                  "type": "string",
                  "enum": [
                    "cvt",
                    "cta"
                  ]
                },
                "blanking": {
                  "description": "Blanking for standard \"cvt\": \"cvt\" (default, CRT-style), \"rb1\" (reduced blanking v1), \"rb2\" (reduced blanking v2) or \"rb2opt\" (RB v2 video-optimized: built for the whole rate, clock x 1000/1001).",
                  "type": "string",
                  "enum": [
                    "cvt",
                    "rb1",
                    "rb2",
                    "rb2opt"
                  ]
                },
                "clockMode": {
                  "description": "\"exact\" (default) keeps the CVT porches and sets the pixel clock so the refresh rate is exactly what you asked for (rounded down to 10 kHz). \"strict\" rounds the clock to the CVT clock step, so the refresh rate comes out slightly different.",
                  "type": "string",
                  "enum": [
                    "exact",
                    "strict"
                  ]
                },
                "bpc": {
                  "description": "Bits per colour component: 8 (default), 10 or 12.",
                  "type": "number",
                  "enum": [
                    8,
                    10,
                    12
                  ]
                },
                "format": {
                  "description": "Colour format: \"rgb\", \"444\", \"422\" (default) or \"420\".",
                  "type": "string",
                  "enum": [
                    "420",
                    "422",
                    "444",
                    "rgb"
                  ]
                },
                "audio": {
                  "type": "object",
                  "properties": {
                    "channels": {
                      "type": "number",
                      "enum": [
                        0,
                        2,
                        8
                      ],
                      "description": "0 = no audio, 2 = stereo, 8 = eight channels (LPCM)."
                    },
                    "rateHz": {
                      "description": "Sample rate in Hz. Default 48000.",
                      "type": "number",
                      "enum": [
                        48000,
                        96000,
                        192000
                      ]
                    }
                  },
                  "required": [
                    "channels"
                  ],
                  "additionalProperties": false,
                  "description": "Embedded audio the signal must carry. Used for the HDMI blanking-room check and the SDI / ST 2110 audio notes."
                }
              },
              "required": [
                "width",
                "height",
                "refreshHz"
              ],
              "additionalProperties": false
            },
            "description": "Up to 50 signals. Each is calculated independently; one bad signal does not fail the others."
          }
        },
        "required": [
          "signals"
        ],
        "additionalProperties": false
      },
      "LinkBatch": {
        "type": "object",
        "properties": {
          "signals": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "description": "Your own label for this signal (for example a cable number). Echoed back unchanged.",
                  "type": "string",
                  "maxLength": 64
                },
                "width": {
                  "type": "integer",
                  "minimum": 64,
                  "maximum": 16384,
                  "description": "Active pixels across, for example 3840."
                },
                "height": {
                  "type": "integer",
                  "minimum": 64,
                  "maximum": 16384,
                  "description": "Active lines down, for example 2160."
                },
                "refreshHz": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 1000,
                  "description": "Refresh rate in Hz. Fractional rates are exact: 59.94, 29.97, 23.976, 119.88."
                },
                "standard": {
                  "description": "\"cvt\" (default) = timing built with the VESA CVT formulas (the blanking field applies). \"cta\" = the fixed CTA-861 table timing for a standard format such as 1920x1080 at 59.94 (blanking and clockMode are ignored).",
                  "type": "string",
                  "enum": [
                    "cvt",
                    "cta"
                  ]
                },
                "blanking": {
                  "description": "Blanking for standard \"cvt\": \"cvt\" (default, CRT-style), \"rb1\" (reduced blanking v1), \"rb2\" (reduced blanking v2) or \"rb2opt\" (RB v2 video-optimized: built for the whole rate, clock x 1000/1001).",
                  "type": "string",
                  "enum": [
                    "cvt",
                    "rb1",
                    "rb2",
                    "rb2opt"
                  ]
                },
                "clockMode": {
                  "description": "\"exact\" (default) keeps the CVT porches and sets the pixel clock so the refresh rate is exactly what you asked for (rounded down to 10 kHz). \"strict\" rounds the clock to the CVT clock step, so the refresh rate comes out slightly different.",
                  "type": "string",
                  "enum": [
                    "exact",
                    "strict"
                  ]
                },
                "bpc": {
                  "description": "Bits per colour component: 8 (default), 10 or 12.",
                  "type": "number",
                  "enum": [
                    8,
                    10,
                    12
                  ]
                },
                "format": {
                  "description": "Colour format: \"rgb\", \"444\", \"422\" (default) or \"420\".",
                  "type": "string",
                  "enum": [
                    "420",
                    "422",
                    "444",
                    "rgb"
                  ]
                },
                "audio": {
                  "type": "object",
                  "properties": {
                    "channels": {
                      "type": "number",
                      "enum": [
                        0,
                        2,
                        8
                      ],
                      "description": "0 = no audio, 2 = stereo, 8 = eight channels (LPCM)."
                    },
                    "rateHz": {
                      "description": "Sample rate in Hz. Default 48000.",
                      "type": "number",
                      "enum": [
                        48000,
                        96000,
                        192000
                      ]
                    }
                  },
                  "required": [
                    "channels"
                  ],
                  "additionalProperties": false,
                  "description": "Embedded audio the signal must carry. Used for the HDMI blanking-room check and the SDI / ST 2110 audio notes."
                },
                "connectors": {
                  "description": "Only report these connectors. Each entry is a connector id (for example \"hdmi20\", \"dp14\", \"sdi\") or a family: \"hdmi\", \"dp\", \"sdi\" or \"ip\" (ST 2110 over Ethernet). Default: all.",
                  "maxItems": 20,
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "required": [
                "width",
                "height",
                "refreshHz"
              ],
              "additionalProperties": false
            },
            "description": "Up to 50 signals. Each is calculated independently; one bad signal does not fail the others."
          }
        },
        "required": [
          "signals"
        ],
        "additionalProperties": false
      },
      "TimingResponse": {
        "type": "object",
        "properties": {
          "engineVersion": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "input": {
                      "type": "object",
                      "properties": {
                        "width": {
                          "type": "integer"
                        },
                        "height": {
                          "type": "integer"
                        },
                        "refreshHz": {
                          "type": "number"
                        },
                        "standard": {
                          "type": "string",
                          "enum": [
                            "cvt",
                            "cta"
                          ]
                        },
                        "blanking": {
                          "type": "string",
                          "enum": [
                            "cvt",
                            "rb1",
                            "rb2",
                            "rb2opt"
                          ]
                        },
                        "clockMode": {
                          "type": "string",
                          "enum": [
                            "exact",
                            "strict"
                          ]
                        },
                        "bpc": {
                          "type": "number",
                          "enum": [
                            8,
                            10,
                            12
                          ]
                        },
                        "format": {
                          "type": "string",
                          "enum": [
                            "420",
                            "422",
                            "444",
                            "rgb"
                          ]
                        },
                        "audio": {
                          "type": "object",
                          "properties": {
                            "channels": {
                              "type": "number",
                              "enum": [
                                0,
                                2,
                                8
                              ]
                            },
                            "rateHz": {
                              "type": "number",
                              "enum": [
                                48000,
                                96000,
                                192000
                              ]
                            }
                          },
                          "required": [
                            "channels",
                            "rateHz"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "width",
                        "height",
                        "refreshHz",
                        "standard",
                        "blanking",
                        "clockMode",
                        "bpc",
                        "format",
                        "audio"
                      ],
                      "additionalProperties": false,
                      "description": "The inputs as used, with defaults filled in."
                    },
                    "defaulted": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Input fields you left out, filled from the defaults."
                    },
                    "timing": {
                      "type": "object",
                      "properties": {
                        "standard": {
                          "type": "string",
                          "description": "For example \"CVT-RBv1\" or \"CTA-861 VIC 97\"."
                        },
                        "vic": {
                          "description": "CTA-861 video identification code, only for standard format timings.",
                          "type": "integer"
                        },
                        "horizontal": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer"
                            },
                            "frontPorch": {
                              "type": "integer"
                            },
                            "syncWidth": {
                              "type": "integer"
                            },
                            "backPorch": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "polarity": {
                              "type": "string",
                              "enum": [
                                "+",
                                "-"
                              ]
                            }
                          },
                          "required": [
                            "active",
                            "frontPorch",
                            "syncWidth",
                            "backPorch",
                            "total",
                            "polarity"
                          ],
                          "additionalProperties": false,
                          "description": "Pixels per line. total = active + frontPorch + syncWidth + backPorch."
                        },
                        "vertical": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer"
                            },
                            "frontPorch": {
                              "type": "integer"
                            },
                            "syncWidth": {
                              "type": "integer"
                            },
                            "backPorch": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "polarity": {
                              "type": "string",
                              "enum": [
                                "+",
                                "-"
                              ]
                            }
                          },
                          "required": [
                            "active",
                            "frontPorch",
                            "syncWidth",
                            "backPorch",
                            "total",
                            "polarity"
                          ],
                          "additionalProperties": false,
                          "description": "Lines per frame. total = active + frontPorch + syncWidth + backPorch."
                        },
                        "pixelClockHz": {
                          "type": "integer"
                        },
                        "hFreqHz": {
                          "type": "number",
                          "description": "Line rate in Hz."
                        },
                        "refreshHz": {
                          "type": "number",
                          "description": "The refresh rate this timing actually produces, in Hz."
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Plain-language remarks, for example when the width was rounded."
                        }
                      },
                      "required": [
                        "standard",
                        "horizontal",
                        "vertical",
                        "pixelClockHz",
                        "hFreqHz",
                        "refreshHz",
                        "notes"
                      ],
                      "additionalProperties": false
                    },
                    "bandwidth": {
                      "type": "object",
                      "properties": {
                        "bitsPerPixel": {
                          "type": "number"
                        },
                        "linkDataRateBps": {
                          "type": "number",
                          "description": "Pixel clock x bits per pixel, blanking included: what a TMDS or DisplayPort link must carry."
                        },
                        "linkDataRateGbps": {
                          "type": "number"
                        },
                        "activeDataRateBps": {
                          "type": "number",
                          "description": "Active pixels only: the picture payload."
                        }
                      },
                      "required": [
                        "bitsPerPixel",
                        "linkDataRateBps",
                        "linkDataRateGbps",
                        "activeDataRateBps"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "ok",
                    "input",
                    "defaulted",
                    "timing",
                    "bandwidth"
                  ],
                  "additionalProperties": false
                },
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean",
                      "const": false
                    },
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "error"
                  ],
                  "additionalProperties": false
                }
              ]
            }
          }
        },
        "required": [
          "engineVersion",
          "results"
        ],
        "additionalProperties": false
      },
      "LinkResponse": {
        "type": "object",
        "properties": {
          "engineVersion": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "input": {
                      "type": "object",
                      "properties": {
                        "width": {
                          "type": "integer"
                        },
                        "height": {
                          "type": "integer"
                        },
                        "refreshHz": {
                          "type": "number"
                        },
                        "standard": {
                          "type": "string",
                          "enum": [
                            "cvt",
                            "cta"
                          ]
                        },
                        "blanking": {
                          "type": "string",
                          "enum": [
                            "cvt",
                            "rb1",
                            "rb2",
                            "rb2opt"
                          ]
                        },
                        "clockMode": {
                          "type": "string",
                          "enum": [
                            "exact",
                            "strict"
                          ]
                        },
                        "bpc": {
                          "type": "number",
                          "enum": [
                            8,
                            10,
                            12
                          ]
                        },
                        "format": {
                          "type": "string",
                          "enum": [
                            "420",
                            "422",
                            "444",
                            "rgb"
                          ]
                        },
                        "audio": {
                          "type": "object",
                          "properties": {
                            "channels": {
                              "type": "number",
                              "enum": [
                                0,
                                2,
                                8
                              ]
                            },
                            "rateHz": {
                              "type": "number",
                              "enum": [
                                48000,
                                96000,
                                192000
                              ]
                            }
                          },
                          "required": [
                            "channels",
                            "rateHz"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "width",
                        "height",
                        "refreshHz",
                        "standard",
                        "blanking",
                        "clockMode",
                        "bpc",
                        "format",
                        "audio"
                      ],
                      "additionalProperties": false,
                      "description": "The inputs as used, with defaults filled in."
                    },
                    "defaulted": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Input fields you left out, filled from the defaults."
                    },
                    "timing": {
                      "type": "object",
                      "properties": {
                        "standard": {
                          "type": "string",
                          "description": "For example \"CVT-RBv1\" or \"CTA-861 VIC 97\"."
                        },
                        "vic": {
                          "description": "CTA-861 video identification code, only for standard format timings.",
                          "type": "integer"
                        },
                        "horizontal": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer"
                            },
                            "frontPorch": {
                              "type": "integer"
                            },
                            "syncWidth": {
                              "type": "integer"
                            },
                            "backPorch": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "polarity": {
                              "type": "string",
                              "enum": [
                                "+",
                                "-"
                              ]
                            }
                          },
                          "required": [
                            "active",
                            "frontPorch",
                            "syncWidth",
                            "backPorch",
                            "total",
                            "polarity"
                          ],
                          "additionalProperties": false,
                          "description": "Pixels per line. total = active + frontPorch + syncWidth + backPorch."
                        },
                        "vertical": {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "integer"
                            },
                            "frontPorch": {
                              "type": "integer"
                            },
                            "syncWidth": {
                              "type": "integer"
                            },
                            "backPorch": {
                              "type": "integer"
                            },
                            "total": {
                              "type": "integer"
                            },
                            "polarity": {
                              "type": "string",
                              "enum": [
                                "+",
                                "-"
                              ]
                            }
                          },
                          "required": [
                            "active",
                            "frontPorch",
                            "syncWidth",
                            "backPorch",
                            "total",
                            "polarity"
                          ],
                          "additionalProperties": false,
                          "description": "Lines per frame. total = active + frontPorch + syncWidth + backPorch."
                        },
                        "pixelClockHz": {
                          "type": "integer"
                        },
                        "hFreqHz": {
                          "type": "number",
                          "description": "Line rate in Hz."
                        },
                        "refreshHz": {
                          "type": "number",
                          "description": "The refresh rate this timing actually produces, in Hz."
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Plain-language remarks, for example when the width was rounded."
                        }
                      },
                      "required": [
                        "standard",
                        "horizontal",
                        "vertical",
                        "pixelClockHz",
                        "hFreqHz",
                        "refreshHz",
                        "notes"
                      ],
                      "additionalProperties": false
                    },
                    "bandwidth": {
                      "type": "object",
                      "properties": {
                        "bitsPerPixel": {
                          "type": "number"
                        },
                        "linkDataRateBps": {
                          "type": "number",
                          "description": "Pixel clock x bits per pixel, blanking included: what a TMDS or DisplayPort link must carry."
                        },
                        "linkDataRateGbps": {
                          "type": "number"
                        },
                        "activeDataRateBps": {
                          "type": "number",
                          "description": "Active pixels only: the picture payload."
                        }
                      },
                      "required": [
                        "bitsPerPixel",
                        "linkDataRateBps",
                        "linkDataRateGbps",
                        "activeDataRateBps"
                      ],
                      "additionalProperties": false
                    },
                    "verdicts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "family": {
                            "type": "string",
                            "enum": [
                              "hdmi",
                              "dp",
                              "sdi",
                              "ip"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "fits",
                              "tight",
                              "exceeds",
                              "unsupported",
                              "check"
                            ],
                            "description": "\"fits\", \"tight\" (over 95% of capacity), \"exceeds\", \"unsupported\" (the connector cannot carry this format) or \"check\" (not in the SMPTE tables used; see the equipment datasheet)."
                          },
                          "usagePct": {
                            "description": "Percent of the connector's capacity used. Absent for SDI, which has no percentage.",
                            "type": "number"
                          },
                          "headroomPct": {
                            "description": "Percent of capacity still free (100 - usagePct). Negative when the signal does not fit.",
                            "type": "number"
                          },
                          "limitingFactor": {
                            "description": "What runs out first on this connector.",
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "tmds-clock",
                                  "frl-payload",
                                  "dp-payload",
                                  "ethernet-rate",
                                  "sdi-link",
                                  "format-support"
                                ]
                              },
                              "label": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "kind",
                              "label"
                            ],
                            "additionalProperties": false
                          },
                          "detail": {
                            "type": "string"
                          },
                          "suggestion": {
                            "description": "The lowest-cost change that makes it fit, for example 10-bit 4:2:2 on \"12G-SDI\".",
                            "type": "object",
                            "properties": {
                              "bpc": {
                                "type": "number",
                                "enum": [
                                  8,
                                  10,
                                  12
                                ]
                              },
                              "format": {
                                "type": "string",
                                "enum": [
                                  "420",
                                  "422",
                                  "444",
                                  "rgb"
                                ]
                              },
                              "usagePct": {
                                "type": "number"
                              },
                              "sdiLink": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "bpc",
                              "format",
                              "usagePct"
                            ],
                            "additionalProperties": false
                          },
                          "sdi": {
                            "type": "object",
                            "properties": {
                              "rateBps": {
                                "type": "number"
                              },
                              "needed": {
                                "description": "The lowest single link that carries the format, for example \"3G-SDI\".",
                                "type": "string"
                              },
                              "standard": {
                                "type": "string"
                              },
                              "ladder": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "name": {
                                      "type": "string"
                                    },
                                    "smpte": {
                                      "type": "string"
                                    },
                                    "rateBps": {
                                      "type": "number"
                                    },
                                    "state": {
                                      "type": "string",
                                      "enum": [
                                        "needed",
                                        "higher",
                                        "no"
                                      ]
                                    }
                                  },
                                  "required": [
                                    "name",
                                    "smpte",
                                    "rateBps",
                                    "state"
                                  ],
                                  "additionalProperties": false
                                }
                              },
                              "alternatives": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "required": [
                              "rateBps",
                              "ladder",
                              "alternatives"
                            ],
                            "additionalProperties": false
                          },
                          "hdmiMode": {
                            "description": "HDMI 2.1 and 2.2 ports: whether the signal travels as TMDS (like HDMI 2.0) or needs FRL.",
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "tmds",
                                  "frl"
                                ]
                              },
                              "tmdsHz": {
                                "type": "number"
                              },
                              "tmdsLimitHz": {
                                "type": "number"
                              },
                              "tmdsLimitBps": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "mode",
                              "tmdsHz",
                              "tmdsLimitHz",
                              "tmdsLimitBps"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "family",
                          "status",
                          "detail"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "fits": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "tight": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "exceeds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "unsupported": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "check": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "fits",
                        "tight",
                        "exceeds",
                        "unsupported",
                        "check"
                      ],
                      "additionalProperties": false,
                      "description": "Connector ids grouped by status."
                    },
                    "audio": {
                      "type": "object",
                      "properties": {
                        "hdmi": {
                          "type": "string"
                        },
                        "sdi": {
                          "type": "string"
                        },
                        "ip": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": false,
                      "description": "Notes on the requested audio per connector family. Only present when audio was requested and has something to say."
                    }
                  },
                  "required": [
                    "ok",
                    "input",
                    "defaulted",
                    "timing",
                    "bandwidth",
                    "verdicts",
                    "summary"
                  ],
                  "additionalProperties": false
                },
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean",
                      "const": false
                    },
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "error"
                  ],
                  "additionalProperties": false
                }
              ]
            }
          }
        },
        "required": [
          "engineVersion",
          "results"
        ],
        "additionalProperties": false
      },
      "ErrorResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "error"
        ],
        "additionalProperties": false
      },
      "RequestError": {
        "type": "object",
        "properties": {
          "engineVersion": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "engineVersion",
          "error"
        ],
        "additionalProperties": false
      }
    }
  },
  "externalDocs": {
    "description": "Documentation, examples and MCP setup",
    "url": "https://api.pixeltach.com"
  }
}
