{
  "openapi": "3.1.1",
  "info": {
    "title": "Ohmforge Gerber \u0026 Drill Viewer with DRC-lite API",
    "version": "1.0.0",
    "summary": "Gerber X2 and Excellon files in – board render, drill table, trace and clearance checks out.",
    "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://ohmforgegerberviewer.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Gerber X2 and Excellon files in – board render, drill table, trace and clearance checks out.",
        "description": "Upload the fabrication data of a printed circuit board – a ZIP of Gerber (RS-274X / X2) layers and Excellon drill files from KiCad, Altium, Eagle, EasyEDA or any CAM tool – and get a rendered board (top and bottom), one SVG per layer with correct dark and clear polarity, the board size from the outline, a drill table per diameter, the narrowest drawn trace, a sampled copper clearance and copper area, and a DRC-lite for annular rings and hole-to-edge distances. Layers are recognised from X2 attributes or file names. A board model with the outline and mounting holes is ready for the enclosure generator.\n\nMethodology:\n- Gerber files are read as the Ucamco Gerber Layer Format Specification (2024.05) defines them: format and unit, standard apertures with holes, aperture macros with variables and expressions (primitives 1, 4, 5, 7, 20, 21 and the deprecated 2, 22, 6), linear and circular plotting with G75 (and deprecated G74), regions with several contours, dark/clear polarity, mirroring, rotation and scaling (LM, LR, LS), step and repeat (SR), block apertures (AB) and X2 attributes. Excellon drill files: METRIC/INCH, LZ/TZ or decimal coordinates, tool tables, G85 slots and routed slots.\n- Layers are identified by their X2 .FileFunction attribute first, then by KiCad, Altium/Protel, Eagle and EasyEDA file names. Plating comes from X2 attributes, the file name (PTH/NPTH) or Altium comments; a hole of unknown plating without a copper pad on the outer layers counts as non-plated.\n- Exact values: board size, area and perimeter from the closed contour of the profile (edge-cuts) layer, measured on the line centres; drill counts per diameter; the narrowest drawn trace (circular-aperture draws and arcs); annular ring = largest inscribed distance of the flashed pad at the hole centre minus the drill radius (smallest over the outer copper layers); hole-to-edge = distance from the hole centre to the outline minus the radius.\n- Sampled values: copper is rasterised with dark and clear polarity on a grid (about four million points, at least 0.02 mm). Copper area = copper points inside the outline ÷ outline points. Clearance = smallest gap between separate 8-connected copper islands, found with an exact Euclidean distance transform (Felzenszwalb–Huttenlocher); it is accurate to about one grid step, and islands closer than one step merge.\n- Mounting-hole candidates are holes between the two diameters (default 2–4.5 mm, M2–M4 clearance holes); non-plated ones and those within 12 mm of the edge are preselected. The board model moves the outline's lower-left corner to (0, 0) and simplifies the contour to at most 200 points.\n\nA viewer and a quick check, not a fabricator's CAM or a full design-rule check: clearances are sampled on a grid (± one grid step), only flashed pads count for annular rings, and the default rules are typical values. Check your manufacturer's capabilities and review the files in their own viewer before ordering.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "ohmforge_gerber_viewer",
        "x-owner-app": "ohmforge",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OhmforgeGerberViewerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Two-layer sensor board: KiCad Gerber X2 ZIP with drill files",
                  "value": {
                    "file": {
                      "filename": "sensor-node-gerbers.zip",
                      "contentType": "application/zip",
                      "contentBase64": "UEsDBBQAAAgAAAAAIQBFVKeTVgkAAFYJAAAUAAAAc2Vuc29yLW5vZGUtRl9DdS5nYnJHMDQgT2htZm9yZ2UgZXhhbXBsZSBib2FyZCAtIGdlbmVyYXRlZCB0ZXN0IGRhdGEqCiVURi5HZW5lcmF0aW9uU29mdHdhcmUsVXNlZnVsV2ViLE9obWZvcmdlIGV4YW1wbGUgZ2VuZXJhdG9yLDEuMColCiVURi5TYW1lQ29vcmRpbmF0ZXMsT3JpZ2luYWwqJQolVEYuRmlsZUZ1bmN0aW9uLENvcHBlcixMMSxUb3AqJQolVEYuRmlsZVBvbGFyaXR5LFBvc2l0aXZlKiUKJUZTTEFYNDZZNDYqJQolTU9NTSolCiVMUEQqJQolQU1Sb3VuZFJlY3QqCjAgUmVjdGFuZ2xlIHdpdGggcm91bmRlZCBjb3JuZXJzOiAkMSB3aWR0aCwgJDIgaGVpZ2h0LCAkMyBjb3JuZXIgcmFkaXVzKgoyMSwxLCQxLCQyLSQzLSQzLDAsMCwwKgoyMSwxLCQxLSQzLSQzLCQyLDAsMCwwKgokND0kMS8yLSQzKgokNT0kMi8yLSQzKgokNj0yeCQzKgoxLDEsJDYsJDQsJDUqCjEsMSwkNiwtJDQsJDUqCjEsMSwkNiwtJDQsLSQ1KgoxLDEsJDYsJDQsLSQ1KiUKJUFNVGhlcm1hbFBhZCoKNywwLDAsMi40LDEuOCwwLjQsNDUqJQolVEEuQXBlckZ1bmN0aW9uLENvbmR1Y3RvciolCiVBREQxMEMsMC4yNSolCiVUQS5BcGVyRnVuY3Rpb24sQ29tcG9uZW50UGFkKiUKJUFERDExQywxLjcqJQolVEEuQXBlckZ1bmN0aW9uLFNNRFBhZCxDdURlZiolCiVBREQxMlJvdW5kUmVjdCwxLjJYMS40WDAuMjUqJQolVEEuQXBlckZ1bmN0aW9uLFZpYVBhZColCiVBREQxM0MsMC42KiUKJVRBLkFwZXJGdW5jdGlvbixTTURQYWQsQ3VEZWYqJQolQUREMTRSLDEuNVgwLjYqJQolVEEuQXBlckZ1bmN0aW9uLENvbXBvbmVudFBhZColCiVBREQxNU8sMS44WDMuMSolCiVUQS5BcGVyRnVuY3Rpb24sVGVzdFBhZColCiVBREQxNkMsMSolCiVUQS5BcGVyRnVuY3Rpb24sQ29tcG9uZW50UGFkKiUKJUFERDE3VGhlcm1hbFBhZColCiVURColCiVBREQyMEMsMC42NSolCiVBREQyMUMsMi40KiUKJUFERDIyQywxKiUKJUFERDIzUiwxLjlYMSolCiVBREQyNEMsMS40KiUKJVRBLkFwZXJGdW5jdGlvbixDb25kdWN0b3IqJQolVE8uTixHTkQqJQpHMDEqCkczNioKWDEzMTAwMDAwMFk4MTAwMDAwMEQwMioKWDE0OTAwMDAwMFk4MTAwMDAwMEQwMSoKWDE0OTAwMDAwMFk5NTAwMDAwMEQwMSoKWDEzMTAwMDAwMFk5NTAwMDAwMEQwMSoKWDEzMTAwMDAwMFk4MTAwMDAwMEQwMSoKRzM3KgolVEQqJQolTFBDKiUKRDIxKgpYMTQwMDAwMDAwWTg4MDAwMDAwRDAzKgolQUREMjZDLDQuNiolCkQyNioKWDE0NjUwMDAwMFk4MzUwMDAwMEQwMyoKJUxQRColCkQxMCoKWDEwNTUwMDAwMFk5ODAwMDAwMEQwMioKWDEwNTUwMDAwMFk5MzAwMDAwMEQwMSoKWDExMTAwMDAwMFk5MzAwMDAwMEQwMSoKWDExMTAwMDAwMFk5MzAwMDAwMEQwMioKWDExNDUwMDAwMFk5MjAwMDAwMEQwMSoKWDExNjUwMDAwMFk5MjAwMDAwMEQwMioKWDEyMjMwMDAwMFk5MjU0MDAwMEQwMSoKWDExNjUwMDAwMFk4ODAwMDAwMEQwMioKWDEyMDAwMDAwMFk4NjAwMDAwMEQwMSoKWDEyNzcwMDAwMFk5MzgxMDAwMEQwMioKWDEzNDAwMDAwMFk5OTAwMDAwMEQwMSoKWDEwODA0MDAwMFkxMDA1NDAwMDBEMDIqClgxMDgwNDAwMDBZMTA0MDAwMDAwRDAxKgpYMTIyMDAwMDAwWTEwNDAwMDAwMEQwMSoKWDEyNzcwMDAwMFk5MDAwMDAwMEQwMioKRzc1KgpHMDIqClgxMzE3MDAwMDBZODYwMDAwMDBJMEotNDAwMDAwMEQwMSoKRzAxKgpEMTEqClgxMDU1MDAwMDBZMTAwNTQwMDAwRDAzKgpYMTA4MDQwMDAwWTk4MDAwMDAwRDAzKgpYMTA4MDQwMDAwWTEwMDU0MDAwMEQwMyoKWDExMDU4MDAwMFk5ODAwMDAwMEQwMyoKWDExMDU4MDAwMFkxMDA1NDAwMDBEMDMqClgxMTMxMjAwMDBZOTgwMDAwMDBEMDMqClgxMTMxMjAwMDBZMTAwNTQwMDAwRDAzKgpEMTcqClgxMDU1MDAwMDBZOTgwMDAwMDBEMDMqCkQxMioKWDExNDUwMDAwMFk4ODAwMDAwMEQwMyoKWDExNjUwMDAwMFk4ODAwMDAwMEQwMyoKWDExNDUwMDAwMFk5MjAwMDAwMEQwMyoKWDExNjUwMDAwMFk5MjAwMDAwMEQwMyoKRDE0KgpYMTIyMzAwMDAwWTkwMDAwMDAwRDAzKgpYMTI3NzAwMDAwWTkwMDAwMDAwRDAzKgpYMTIyMzAwMDAwWTkxMjcwMDAwRDAzKgpYMTI3NzAwMDAwWTkxMjcwMDAwRDAzKgpYMTIyMzAwMDAwWTkyNTQwMDAwRDAzKgpYMTI3NzAwMDAwWTkyNTQwMDAwRDAzKgpYMTIyMzAwMDAwWTkzODEwMDAwRDAzKgpYMTI3NzAwMDAwWTkzODEwMDAwRDAzKgpEMTMqClgxMjAwMDAwMDBZODYwMDAwMDBEMDMqClgxMjIwMDAwMDBZMTA0MDAwMDAwRDAzKgpYMTM0MDAwMDAwWTk5MDAwMDAwRDAzKgpYMTQwMDAwMDAwWTg4MDAwMDAwRDAzKgpYMTExMDAwMDAwWTkzMDAwMDAwRDAzKgpYMTI4MDAwMDAwWTEwNjAwMDAwMEQwMyoKRDE1KgpYMTQzMDAwMDAwWTk4MjUwMDAwRDAzKgpEMTYqCiVTUlg1WTFJMi41SjAqJQpYMTEwMDAwMDAwWTg0MDAwMDAwRDAzKgolU1IqJQpNMDIqClBLAwQUAAAIAAAAACEAJN+FaQ4GAAAOBgAAFAAAAHNlbnNvci1ub2RlLUJfQ3UuZ2JyRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolVEYuR2VuZXJhdGlvblNvZnR3YXJlLFVzZWZ1bFdlYixPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvciwxLjAqJQolVEYuU2FtZUNvb3JkaW5hdGVzLE9yaWdpbmFsKiUKJVRGLkZpbGVGdW5jdGlvbixDb3BwZXIsTDIsQm90KiUKJVRGLkZpbGVQb2xhcml0eSxQb3NpdGl2ZSolCiVGU0xBWDQ2WTQ2KiUKJU1PTU0qJQolTFBEKiUKJVRBLkFwZXJGdW5jdGlvbixDb21wb25lbnRQYWQqJQolQUREMTFDLDEuNyolCiVUQS5BcGVyRnVuY3Rpb24sVmlhUGFkKiUKJUFERDEzQywwLjYqJQolVEEuQXBlckZ1bmN0aW9uLENvbmR1Y3RvciolCiVBREQxMEMsMC4zKiUKJVREKiUKJUFERDIwQywyLjMqJQolQUREMjFDLDEuMSolCiVBREQyMkMsNC42KiUKJUFERDIzQywwLjgqJQolQUREMjRDLDEuNColCiVUTy5OLEdORColCkcwMSoKRzM2KgpYMTAwNTAwMDAwWTgwNTAwMDAwRDAyKgpYMTQ5NTAwMDAwWTgwNTAwMDAwRDAxKgpYMTQ5NTAwMDAwWTEwOTUwMDAwMEQwMSoKWDEwMDUwMDAwMFkxMDk1MDAwMDBEMDEqClgxMDA1MDAwMDBZODA1MDAwMDBEMDEqCkczNyoKJVREKiUKJUxQQyolCkQyMCoKWDEwNTUwMDAwMFkxMDA1NDAwMDBEMDMqClgxMDgwNDAwMDBZOTgwMDAwMDBEMDMqClgxMDgwNDAwMDBZMTAwNTQwMDAwRDAzKgpYMTEwNTgwMDAwWTk4MDAwMDAwRDAzKgpYMTEwNTgwMDAwWTEwMDU0MDAwMEQwMyoKWDExMzEyMDAwMFk5ODAwMDAwMEQwMyoKWDExMzEyMDAwMFkxMDA1NDAwMDBEMDMqCkQyMSoKWDEyMDAwMDAwMFk4NjAwMDAwMEQwMyoKWDEyMjAwMDAwMFkxMDQwMDAwMDBEMDMqClgxMzQwMDAwMDBZOTkwMDAwMDBEMDMqClgxNDAwMDAwMDBZODgwMDAwMDBEMDMqCkQyMioKWDEwMzUwMDAwMFk4MzUwMDAwMEQwMyoKWDE0NjUwMDAwMFk4MzUwMDAwMEQwMyoKWDEwMzUwMDAwMFkxMDY1MDAwMDBEMDMqClgxNDY1MDAwMDBZMTA2NTAwMDAwRDAzKgpEMjMqClgxMjAwMDAwMDBZODYwMDAwMDBEMDIqClgxNDAwMDAwMDBZODgwMDAwMDBEMDEqCiVBREQyNU8sMi42WDMuOSolCkQyNSoKWDE0MzAwMDAwMFk5ODI1MDAwMEQwMyoKJUxQRColCkQxMCoKWDEyMDAwMDAwMFk4NjAwMDAwMEQwMioKWDE0MDAwMDAwMFk4ODAwMDAwMEQwMSoKRDExKgpYMTA1NTAwMDAwWTk4MDAwMDAwRDAzKgpYMTA1NTAwMDAwWTEwMDU0MDAwMEQwMyoKWDEwODA0MDAwMFk5ODAwMDAwMEQwMyoKWDEwODA0MDAwMFkxMDA1NDAwMDBEMDMqClgxMTA1ODAwMDBZOTgwMDAwMDBEMDMqClgxMTA1ODAwMDBZMTAwNTQwMDAwRDAzKgpYMTEzMTIwMDAwWTk4MDAwMDAwRDAzKgpYMTEzMTIwMDAwWTEwMDU0MDAwMEQwMyoKRDEzKgpYMTIwMDAwMDAwWTg2MDAwMDAwRDAzKgpYMTIyMDAwMDAwWTEwNDAwMDAwMEQwMyoKWDEzNDAwMDAwMFk5OTAwMDAwMEQwMyoKWDE0MDAwMDAwMFk4ODAwMDAwMEQwMyoKWDExMTAwMDAwMFk5MzAwMDAwMEQwMyoKWDEyODAwMDAwMFkxMDYwMDAwMDBEMDMqCiVBREQxNU8sMS44WDMuMSolCkQxNSoKWDE0MzAwMDAwMFk5ODI1MDAwMEQwMyoKTTAyKgpQSwMEFAAACAAAAAAhAIUl1JiIBAAAiAQAABYAAABzZW5zb3Itbm9kZS1GX01hc2suZ2JyRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolVEYuR2VuZXJhdGlvblNvZnR3YXJlLFVzZWZ1bFdlYixPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvciwxLjAqJQolVEYuU2FtZUNvb3JkaW5hdGVzLE9yaWdpbmFsKiUKJVRGLkZpbGVGdW5jdGlvbixTb2xkZXJtYXNrLFRvcColCiVURi5GaWxlUG9sYXJpdHksTmVnYXRpdmUqJQolRlNMQVg0Nlk0NiolCiVNT01NKiUKJUxQRColCiVBTVJvdW5kUmVjdCoKMjEsMSwkMSwkMi0kMy0kMywwLDAsMCoKMjEsMSwkMS0kMy0kMywkMiwwLDAsMCoKJDQ9JDEvMi0kMyoKJDU9JDIvMi0kMyoKJDY9MngkMyoKMSwxLCQ2LCQ0LCQ1KgoxLDEsJDYsLSQ0LCQ1KgoxLDEsJDYsLSQ0LC0kNSoKMSwxLCQ2LCQ0LC0kNSolCiVBREQxMUMsMS44KiUKJUFERDEyUm91bmRSZWN0LDEuM1gxLjVYMC4zKiUKJUFERDE0UiwxLjZYMC43KiUKJUFERDE1TywxLjlYMy4yKiUKJUFERDE2QywxLjEqJQolQUREMjRDLDEuNSolCkQxMSoKWDEwNTUwMDAwMFk5ODAwMDAwMEQwMyoKWDEwNTUwMDAwMFkxMDA1NDAwMDBEMDMqClgxMDgwNDAwMDBZOTgwMDAwMDBEMDMqClgxMDgwNDAwMDBZMTAwNTQwMDAwRDAzKgpYMTEwNTgwMDAwWTk4MDAwMDAwRDAzKgpYMTEwNTgwMDAwWTEwMDU0MDAwMEQwMyoKWDExMzEyMDAwMFk5ODAwMDAwMEQwMyoKWDExMzEyMDAwMFkxMDA1NDAwMDBEMDMqCkQxNSoKWDE0MzAwMDAwMFk5ODI1MDAwMEQwMyoKRDEyKgpYMTE0NTAwMDAwWTg4MDAwMDAwRDAzKgpYMTE2NTAwMDAwWTg4MDAwMDAwRDAzKgpYMTE0NTAwMDAwWTkyMDAwMDAwRDAzKgpYMTE2NTAwMDAwWTkyMDAwMDAwRDAzKgpEMTQqClgxMjIzMDAwMDBZOTAwMDAwMDBEMDMqClgxMjc3MDAwMDBZOTAwMDAwMDBEMDMqClgxMjIzMDAwMDBZOTEyNzAwMDBEMDMqClgxMjc3MDAwMDBZOTEyNzAwMDBEMDMqClgxMjIzMDAwMDBZOTI1NDAwMDBEMDMqClgxMjc3MDAwMDBZOTI1NDAwMDBEMDMqClgxMjIzMDAwMDBZOTM4MTAwMDBEMDMqClgxMjc3MDAwMDBZOTM4MTAwMDBEMDMqCkQxNioKWDExMDAwMDAwMFk4NDAwMDAwMEQwMyoKWDExMjUwMDAwMFk4NDAwMDAwMEQwMyoKWDExNTAwMDAwMFk4NDAwMDAwMEQwMyoKWDExNzUwMDAwMFk4NDAwMDAwMEQwMyoKWDEyMDAwMDAwMFk4NDAwMDAwMEQwMyoKTTAyKgpQSwMEFAAACAAAAAAhAKVr8GnhAgAA4QIAABYAAABzZW5zb3Itbm9kZS1CX01hc2suZ2JyRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolVEYuR2VuZXJhdGlvblNvZnR3YXJlLFVzZWZ1bFdlYixPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvciwxLjAqJQolVEYuU2FtZUNvb3JkaW5hdGVzLE9yaWdpbmFsKiUKJVRGLkZpbGVGdW5jdGlvbixTb2xkZXJtYXNrLEJvdColCiVURi5GaWxlUG9sYXJpdHksTmVnYXRpdmUqJQolRlNMQVg0Nlk0NiolCiVNT01NKiUKJUxQRColCiVBTVJvdW5kUmVjdCoKMjEsMSwkMSwkMi0kMy0kMywwLDAsMCoKMjEsMSwkMS0kMy0kMywkMiwwLDAsMCoKJDQ9JDEvMi0kMyoKJDU9JDIvMi0kMyoKJDY9MngkMyoKMSwxLCQ2LCQ0LCQ1KgoxLDEsJDYsLSQ0LCQ1KgoxLDEsJDYsLSQ0LC0kNSoKMSwxLCQ2LCQ0LC0kNSolCiVBREQxMUMsMS44KiUKJUFERDEyUm91bmRSZWN0LDEuM1gxLjVYMC4zKiUKJUFERDE0UiwxLjZYMC43KiUKJUFERDE1TywxLjlYMy4yKiUKJUFERDE2QywxLjEqJQolQUREMjRDLDEuNSolCkQxMSoKWDEwNTUwMDAwMFk5ODAwMDAwMEQwMyoKWDEwNTUwMDAwMFkxMDA1NDAwMDBEMDMqClgxMDgwNDAwMDBZOTgwMDAwMDBEMDMqClgxMDgwNDAwMDBZMTAwNTQwMDAwRDAzKgpYMTEwNTgwMDAwWTk4MDAwMDAwRDAzKgpYMTEwNTgwMDAwWTEwMDU0MDAwMEQwMyoKWDExMzEyMDAwMFk5ODAwMDAwMEQwMyoKWDExMzEyMDAwMFkxMDA1NDAwMDBEMDMqCkQxNSoKWDE0MzAwMDAwMFk5ODI1MDAwMEQwMyoKTTAyKgpQSwMEFAAACAAAAAAhAFfqcDj8AgAA/AIAABwAAABzZW5zb3Itbm9kZS1GX1NpbGtzY3JlZW4uZ2JyRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolVEYuR2VuZXJhdGlvblNvZnR3YXJlLFVzZWZ1bFdlYixPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvciwxLjAqJQolVEYuU2FtZUNvb3JkaW5hdGVzLE9yaWdpbmFsKiUKJVRGLkZpbGVGdW5jdGlvbixMZWdlbmQsVG9wKiUKJVRGLkZpbGVQb2xhcml0eSxQb3NpdGl2ZSolCiVGU0xBWDQ2WTQ2KiUKJU1PTU0qJQolTFBEKiUKJUFERDEwQywwLjE1KiUKRDEwKgpHMDEqClgxMDQyMDAwMDBZOTY3MDAwMDBEMDIqClgxMTQ0MDAwMDBZOTY3MDAwMDBEMDEqClgxMTQ0MDAwMDBZMTAzODAwMDAwRDAxKgpYMTA0MjAwMDAwWTEwMzgwMDAwMEQwMSoKWDEwNDIwMDAwMFk5NjcwMDAwMEQwMSoKWDEyMzQwMDAwMFk4ODkwMDAwMEQwMioKWDEyNjYwMDAwMFk4ODkwMDAwMEQwMSoKWDEyNjYwMDAwMFk5NDkwMDAwMEQwMSoKWDEyMzQwMDAwMFk5NDkwMDAwMEQwMSoKWDEyMzQwMDAwMFk4ODkwMDAwMEQwMSoKJUFCRDMwKiUKRDEwKgpYMFkwRDAyKgpYMFkyMDAwMDAwRDAxKgpYMTIwMDAwMFkyMDAwMDAwRDAxKgpYMTIwMDAwMFkwRDAxKgpYMFkwRDAxKgpYMjAwMDAwMFkwRDAyKgpYMjAwMDAwMFkyMDAwMDAwRDAxKgpYMzIwMDAwMFkyMDAwMDAwRDAxKgpYMjAwMDAwMFkxMDAwMDAwRDAyKgpYMjgwMDAwMFkxMDAwMDAwRDAxKgolQUIqJQpEMzAqClgxMzUwMDAwMDBZMTAzMDAwMDAwRDAzKgolTFI5MColClgxNDgwMDAwMDBZMTAwMDAwMDAwRDAzKgolTFIwKiUKTTAyKgpQSwMEFAAACAAAAAAhAGuroDw/AgAAPwIAABkAAABzZW5zb3Itbm9kZS1FZGdlX0N1dHMuZ2JyRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolVEYuR2VuZXJhdGlvblNvZnR3YXJlLFVzZWZ1bFdlYixPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvciwxLjAqJQolVEYuU2FtZUNvb3JkaW5hdGVzLE9yaWdpbmFsKiUKJVRGLkZpbGVGdW5jdGlvbixQcm9maWxlLE5QKiUKJUZTTEFYNDZZNDYqJQolTU9NTSolCiVMUEQqJQolVEEuQXBlckZ1bmN0aW9uLFByb2ZpbGUqJQolQUREMTBDLDAuMSolCiVURColCkQxMCoKRzc1KgpHMDEqClgxMDIwMDAwMDBZODAwMDAwMDBEMDIqClgxNDgwMDAwMDBZODAwMDAwMDBEMDEqCkcwMyoKWDE1MDAwMDAwMFk4MjAwMDAwMEkwSjIwMDAwMDBEMDEqCkcwMSoKWDE1MDAwMDAwMFkxMDgwMDAwMDBEMDEqCkcwMyoKWDE0ODAwMDAwMFkxMTAwMDAwMDBJLTIwMDAwMDBKMEQwMSoKRzAxKgpYMTAyMDAwMDAwWTExMDAwMDAwMEQwMSoKRzAzKgpYMTAwMDAwMDAwWTEwODAwMDAwMEkwSi0yMDAwMDAwRDAxKgpHMDEqClgxMDAwMDAwMDBZODIwMDAwMDBEMDEqCkcwMyoKWDEwMjAwMDAwMFk4MDAwMDAwMEkyMDAwMDAwSjBEMDEqCkcwMSoKTTAyKgpQSwMEFAAACAAAAAAhABwEkt9VAgAAVQIAABMAAABzZW5zb3Itbm9kZS1QVEguZHJsTTQ4CjsgRFJJTEwgZmlsZSB7T2htZm9yZ2UgZXhhbXBsZSBnZW5lcmF0b3J9IFBUSAo7IEZPUk1BVD17LTotLyBhYnNvbHV0ZSAvIG1ldHJpYyAvIGRlY2ltYWx9CjsgI0AhIFRGLkZpbGVGdW5jdGlvbixQbGF0ZWQsMSwyLFBUSApGTUFULDIKTUVUUklDCjsgI0AhIFRBLkFwZXJGdW5jdGlvbixQbGF0ZWQsUFRILFZpYURyaWxsClQxQzAuMzAwCjsgI0AhIFRBLkFwZXJGdW5jdGlvbixQbGF0ZWQsUFRILENvbXBvbmVudERyaWxsClQyQzEuMDAwCjsgI0AhIFRBLkFwZXJGdW5jdGlvbixQbGF0ZWQsUFRILENvbXBvbmVudERyaWxsClQzQzEuMjAwCiUKRzkwCkcwNQpUMQpYMTIwLjAwMFk4Ni4wMDAKWDEyMi4wMDBZMTA0LjAwMApYMTM0LjAwMFk5OS4wMDAKWDE0MC4wMDBZODguMDAwClgxMTEuMDAwWTkzLjAwMApYMTI4LjAwMFkxMDYuMDAwClQyClgxMDUuNTAwWTk4LjAwMApYMTA1LjUwMFkxMDAuNTQwClgxMDguMDQwWTk4LjAwMApYMTA4LjA0MFkxMDAuNTQwClgxMTAuNTgwWTk4LjAwMApYMTEwLjU4MFkxMDAuNTQwClgxMTMuMTIwWTk4LjAwMApYMTEzLjEyMFkxMDAuNTQwClQzClgxNDMuMDAwWTk3LjAwMEc4NVgxNDMuMDAwWTk5LjUwMApNMzAKUEsDBBQAAAgAAAAAIQCETE/FJwEAACcBAAAUAAAAc2Vuc29yLW5vZGUtTlBUSC5kcmxNNDgKOyBEUklMTCBmaWxlIHtPaG1mb3JnZSBleGFtcGxlIGdlbmVyYXRvcn0gTlBUSAo7IEZPUk1BVD17LTotLyBhYnNvbHV0ZSAvIG1ldHJpYyAvIGRlY2ltYWx9CjsgI0AhIFRGLkZpbGVGdW5jdGlvbixOb25QbGF0ZWQsMSwyLE5QVEgKRk1BVCwyCk1FVFJJQwo7ICNAISBUQS5BcGVyRnVuY3Rpb24sTm9uUGxhdGVkLE5QVEgsTWVjaGFuaWNhbERyaWxsClQxQzMuMjAwCiUKRzkwCkcwNQpUMQpYMTAzLjUwMFk4My41MDAKWDE0Ni41MDBZODMuNTAwClgxMDMuNTAwWTEwNi41MDAKWDE0Ni41MDBZMTA2LjUwMApNMzAKUEsBAhQAFAAACAAAAAAhAEVUp5NWCQAAVgkAABQAAAAAAAAAAAAAAAAAAAAAAHNlbnNvci1ub2RlLUZfQ3UuZ2JyUEsBAhQAFAAACAAAAAAhACTfhWkOBgAADgYAABQAAAAAAAAAAAAAAAAAiAkAAHNlbnNvci1ub2RlLUJfQ3UuZ2JyUEsBAhQAFAAACAAAAAAhAIUl1JiIBAAAiAQAABYAAAAAAAAAAAAAAAAAyA8AAHNlbnNvci1ub2RlLUZfTWFzay5nYnJQSwECFAAUAAAIAAAAACEApWvwaeECAADhAgAAFgAAAAAAAAAAAAAAAACEFAAAc2Vuc29yLW5vZGUtQl9NYXNrLmdiclBLAQIUABQAAAgAAAAAIQBX6nA4/AIAAPwCAAAcAAAAAAAAAAAAAAAAAJkXAABzZW5zb3Itbm9kZS1GX1NpbGtzY3JlZW4uZ2JyUEsBAhQAFAAACAAAAAAhAGuroDw/AgAAPwIAABkAAAAAAAAAAAAAAAAAzxoAAHNlbnNvci1ub2RlLUVkZ2VfQ3V0cy5nYnJQSwECFAAUAAAIAAAAACEAHASS31UCAABVAgAAEwAAAAAAAAAAAAAAAABFHQAAc2Vuc29yLW5vZGUtUFRILmRybFBLAQIUABQAAAgAAAAAIQCETE/FJwEAACcBAAAUAAAAAAAAAAAAAAAAAMsfAABzZW5zb3Itbm9kZS1OUFRILmRybFBLBQYAAAAACAAIACACAAAkIQAAAAA="
                    }
                  }
                },
                "example2": {
                  "summary": "Same board in Eagle style (inch, no X2 attributes) with DRC problems",
                  "value": {
                    "file": {
                      "filename": "sensor-node-eagle.zip",
                      "contentType": "application/zip",
                      "contentBase64": "UEsDBBQAAAgAAAAAIQD14ZHm0QYAANEGAAAPAAAAc2Vuc29yLW5vZGUuY21wRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolRlNMQVgyNFkyNColCkc3MCoKJUxQRColCiVBTVJvdW5kUmVjdCoKMCBSZWN0YW5nbGUgd2l0aCByb3VuZGVkIGNvcm5lcnM6ICQxIHdpZHRoLCAkMiBoZWlnaHQsICQzIGNvcm5lciByYWRpdXMqCjIxLDEsJDEsJDItJDMtJDMsMCwwLDAqCjIxLDEsJDEtJDMtJDMsJDIsMCwwLDAqCiQ0PSQxLzItJDMqCiQ1PSQyLzItJDMqCiQ2PTJ4JDMqCjEsMSwkNiwkNCwkNSoKMSwxLCQ2LC0kNCwkNSoKMSwxLCQ2LC0kNCwtJDUqCjEsMSwkNiwkNCwtJDUqJQolQU1UaGVybWFsUGFkKgo3LDAsMCwwLjA5NDQ5LDAuMDcwODcsMC4wMTU3NSw0NSolCiVBREQxMEMsMC4wMDk4NColCiVBREQxMUMsMC4wNjY5MyolCiVBREQxMlJvdW5kUmVjdCwwLjA0NzI0WDAuMDU1MTJYMC4wMDk4NColCiVBREQxM0MsMC4wMTU3NSolCiVBREQxNFIsMC4wNTkwNlgwLjAyMzYyKiUKJUFERDE1TywwLjA3MDg3WDAuMTIyMDUqJQolQUREMTZDLDAuMDM5MzcqJQolQUREMTdUaGVybWFsUGFkKiUKJUFERDIwQywwLjAyNTU5KiUKJUFERDIxQywwLjA5NDQ5KiUKJUFERDIyQywwLjAzOTM3KiUKJUFERDIzUiwwLjA3NDhYMC4wMzkzNyolCiVBREQyNEMsMC4wNTUxMiolCkcwMSoKRzM2KgpYNTE1NzVZMzE4OTBEMDIqCkcwMVg1ODY2MVkzMTg5MEQwMSoKRzAxWDU4NjYxWTM3NDAyRDAxKgpHMDFYNTE1NzVZMzc0MDJEMDEqCkcwMVg1MTU3NVkzMTg5MEQwMSoKRzM3KgolTFBDKiUKRzU0RDIxKgpYNTUxMThZMzQ2NDZEMDMqCiVBREQyNkMsMC4xODExKiUKRzU0RDI2KgpYNTc2NzdZMzI4NzREMDMqCiVMUEQqJQpHNTREMTAqClg0MTUzNVkzODU4M0QwMioKRzAxWDQxNTM1WTM2NjE0RDAxKgpHMDFYNDM3MDFZMzY2MTREMDEqClg0MzcwMVkzNjYxNEQwMioKRzAxWDQ1MDc5WTM2MjIwRDAxKgpYNDU4NjZZMzYyMjBEMDIqCkcwMVg0ODE1MFkzNjQzM0QwMSoKWDQ1ODY2WTM0NjQ2RDAyKgpHMDFYNDcyNDRZMzM4NThEMDEqClg1MDI3NlkzNjkzM0QwMioKRzAxWDUyNzU2WTM4OTc2RDAxKgpYNDI1MzVZMzk1ODNEMDIqCkcwMVg0MjUzNVk0MDk0NUQwMSoKRzAxWDQ4MDMxWTQwOTQ1RDAxKgpYNTAyNzZZMzU0MzNEMDIqCkc3NSoKRzAyKgpYNTE4NTBZMzM4NThJMEotMTU3NUQwMSoKRzAxKgpHNTREMTEqClg0MTUzNVkzOTU4M0QwMyoKWDQyNTM1WTM4NTgzRDAzKgpYNDI1MzVZMzk1ODNEMDMqClg0MzUzNVkzODU4M0QwMyoKWDQzNTM1WTM5NTgzRDAzKgpYNDQ1MzVZMzg1ODNEMDMqClg0NDUzNVkzOTU4M0QwMyoKRzU0RDE3KgpYNDE1MzVZMzg1ODNEMDMqCkc1NEQxMioKWDQ1MDc5WTM0NjQ2RDAzKgpYNDU4NjZZMzQ2NDZEMDMqClg0NTA3OVkzNjIyMEQwMyoKWDQ1ODY2WTM2MjIwRDAzKgpHNTREMTQqClg0ODE1MFkzNTQzM0QwMyoKWDUwMjc2WTM1NDMzRDAzKgpYNDgxNTBZMzU5MzNEMDMqClg1MDI3NlkzNTkzM0QwMyoKWDQ4MTUwWTM2NDMzRDAzKgpYNTAyNzZZMzY0MzNEMDMqClg0ODE1MFkzNjkzM0QwMyoKWDUwMjc2WTM2OTMzRDAzKgpHNTREMTMqClg0NzI0NFkzMzg1OEQwMyoKWDQ4MDMxWTQwOTQ1RDAzKgpYNTI3NTZZMzg5NzZEMDMqClg1NTExOFkzNDY0NkQwMyoKWDQzNzAxWTM2NjE0RDAzKgpYNTAzOTRZNDE3MzJEMDMqCkc1NEQxNSoKWDU2Mjk5WTM4NjgxRDAzKgpHNTREMTYqCiVTUlg1WTFJMC4wOTg0M0owKiUKWDQzMzA3WTMzMDcxRDAzKgolU1IqJQpHNTREMjQqClgzOTY2NVkzNzQwMkQwMyoKTTAyKgpQSwMEFAAACAAAAAAhAElvQQZLBAAASwQAAA8AAABzZW5zb3Itbm9kZS5zb2xHMDQgT2htZm9yZ2UgZXhhbXBsZSBib2FyZCAtIGdlbmVyYXRlZCB0ZXN0IGRhdGEqCiVGU0xBWDI0WTI0KiUKRzcwKgolTFBEKiUKJUFERDExQywwLjA2NjkzKiUKJUFERDEzQywwLjAxNTc1KiUKJUFERDEwQywwLjAxMTgxKiUKJUFERDIwQywwLjA5MDU1KiUKJUFERDIxQywwLjA0MzMxKiUKJUFERDIyQywwLjE4MTEqJQolQUREMjNDLDAuMDMxNSolCiVBREQyNEMsMC4wNTUxMiolCkcwMSoKRzM2KgpYMzk1NjdZMzE2OTNEMDIqCkcwMVg1ODg1OFkzMTY5M0QwMSoKRzAxWDU4ODU4WTQzMTEwRDAxKgpHMDFYMzk1NjdZNDMxMTBEMDEqCkcwMVgzOTU2N1kzMTY5M0QwMSoKRzM3KgolTFBDKiUKRzU0RDIwKgpYNDE1MzVZMzk1ODNEMDMqClg0MjUzNVkzODU4M0QwMyoKWDQyNTM1WTM5NTgzRDAzKgpYNDM1MzVZMzg1ODNEMDMqClg0MzUzNVkzOTU4M0QwMyoKWDQ0NTM1WTM4NTgzRDAzKgpYNDQ1MzVZMzk1ODNEMDMqCkc1NEQyMSoKWDQ3MjQ0WTMzODU4RDAzKgpYNDgwMzFZNDA5NDVEMDMqClg1Mjc1NlkzODk3NkQwMyoKWDU1MTE4WTM0NjQ2RDAzKgpHNTREMjIqClg0MDc0OFkzMjg3NEQwMyoKWDU3Njc3WTMyODc0RDAzKgpYNDA3NDhZNDE5MjlEMDMqClg1NzY3N1k0MTkyOUQwMyoKRzU0RDIzKgpYNDcyNDRZMzM4NThEMDIqCkcwMVg1NTExOFkzNDY0NkQwMSoKJUFERDI1TywwLjEwMjM2WDAuMTUzNTQqJQpHNTREMjUqClg1NjI5OVkzODY4MUQwMyoKJUxQRColCkc1NEQxMCoKWDQ3MjQ0WTMzODU4RDAyKgpHMDFYNTUxMThZMzQ2NDZEMDEqCkc1NEQxMSoKWDQxNTM1WTM4NTgzRDAzKgpYNDE1MzVZMzk1ODNEMDMqClg0MjUzNVkzODU4M0QwMyoKWDQyNTM1WTM5NTgzRDAzKgpYNDM1MzVZMzg1ODNEMDMqClg0MzUzNVkzOTU4M0QwMyoKWDQ0NTM1WTM4NTgzRDAzKgpYNDQ1MzVZMzk1ODNEMDMqCkc1NEQxMyoKWDQ3MjQ0WTMzODU4RDAzKgpYNDgwMzFZNDA5NDVEMDMqClg1Mjc1NlkzODk3NkQwMyoKWDU1MTE4WTM0NjQ2RDAzKgpYNDM3MDFZMzY2MTREMDMqClg1MDM5NFk0MTczMkQwMyoKJUFERDE1TywwLjA3MDg3WDAuMTIyMDUqJQpHNTREMTUqClg1NjI5OVkzODY4MUQwMyoKRzU0RDI0KgpYMzk2NjVZMzc0MDJEMDMqCk0wMioKUEsDBBQAAAgAAAAAIQDbl6zqewMAAHsDAAAPAAAAc2Vuc29yLW5vZGUuc3RjRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolRlNMQVgyNFkyNColCkc3MCoKJUxQRColCiVBTVJvdW5kUmVjdCoKMjEsMSwkMSwkMi0kMy0kMywwLDAsMCoKMjEsMSwkMS0kMy0kMywkMiwwLDAsMCoKJDQ9JDEvMi0kMyoKJDU9JDIvMi0kMyoKJDY9MngkMyoKMSwxLCQ2LCQ0LCQ1KgoxLDEsJDYsLSQ0LCQ1KgoxLDEsJDYsLSQ0LC0kNSoKMSwxLCQ2LCQ0LC0kNSolCiVBREQxMUMsMC4wNzA4NyolCiVBREQxMlJvdW5kUmVjdCwwLjA1MTE4WDAuMDU5MDZYMC4wMTE4MSolCiVBREQxNFIsMC4wNjI5OVgwLjAyNzU2KiUKJUFERDE1TywwLjA3NDhYMC4xMjU5OColCiVBREQxNkMsMC4wNDMzMSolCiVBREQyNEMsMC4wNTkwNiolCkc1NEQxMSoKWDQxNTM1WTM4NTgzRDAzKgpYNDE1MzVZMzk1ODNEMDMqClg0MjUzNVkzODU4M0QwMyoKWDQyNTM1WTM5NTgzRDAzKgpYNDM1MzVZMzg1ODNEMDMqClg0MzUzNVkzOTU4M0QwMyoKWDQ0NTM1WTM4NTgzRDAzKgpYNDQ1MzVZMzk1ODNEMDMqCkc1NEQxNSoKWDU2Mjk5WTM4NjgxRDAzKgpHNTREMTIqClg0NTA3OVkzNDY0NkQwMyoKWDQ1ODY2WTM0NjQ2RDAzKgpYNDUwNzlZMzYyMjBEMDMqClg0NTg2NlkzNjIyMEQwMyoKRzU0RDE0KgpYNDgxNTBZMzU0MzNEMDMqClg1MDI3NlkzNTQzM0QwMyoKWDQ4MTUwWTM1OTMzRDAzKgpYNTAyNzZZMzU5MzNEMDMqClg0ODE1MFkzNjQzM0QwMyoKWDUwMjc2WTM2NDMzRDAzKgpYNDgxNTBZMzY5MzNEMDMqClg1MDI3NlkzNjkzM0QwMyoKRzU0RDE2KgpYNDMzMDdZMzMwNzFEMDMqClg0NDI5MVkzMzA3MUQwMyoKWDQ1Mjc2WTMzMDcxRDAzKgpYNDYyNjBZMzMwNzFEMDMqClg0NzI0NFkzMzA3MUQwMyoKRzU0RDI0KgpYMzk2NjVZMzc0MDJEMDMqCk0wMioKUEsDBBQAAAgAAAAAIQC/QlMgQgIAAEICAAAPAAAAc2Vuc29yLW5vZGUuc3RzRzA0IE9obWZvcmdlIGV4YW1wbGUgYm9hcmQgLSBnZW5lcmF0ZWQgdGVzdCBkYXRhKgolRlNMQVgyNFkyNColCkc3MCoKJUxQRColCiVBTVJvdW5kUmVjdCoKMjEsMSwkMSwkMi0kMy0kMywwLDAsMCoKMjEsMSwkMS0kMy0kMywkMiwwLDAsMCoKJDQ9JDEvMi0kMyoKJDU9JDIvMi0kMyoKJDY9MngkMyoKMSwxLCQ2LCQ0LCQ1KgoxLDEsJDYsLSQ0LCQ1KgoxLDEsJDYsLSQ0LC0kNSoKMSwxLCQ2LCQ0LC0kNSolCiVBREQxMUMsMC4wNzA4NyolCiVBREQxMlJvdW5kUmVjdCwwLjA1MTE4WDAuMDU5MDZYMC4wMTE4MSolCiVBREQxNFIsMC4wNjI5OVgwLjAyNzU2KiUKJUFERDE1TywwLjA3NDhYMC4xMjU5OColCiVBREQxNkMsMC4wNDMzMSolCiVBREQyNEMsMC4wNTkwNiolCkc1NEQxMSoKWDQxNTM1WTM4NTgzRDAzKgpYNDE1MzVZMzk1ODNEMDMqClg0MjUzNVkzODU4M0QwMyoKWDQyNTM1WTM5NTgzRDAzKgpYNDM1MzVZMzg1ODNEMDMqClg0MzUzNVkzOTU4M0QwMyoKWDQ0NTM1WTM4NTgzRDAzKgpYNDQ1MzVZMzk1ODNEMDMqCkc1NEQxNSoKWDU2Mjk5WTM4NjgxRDAzKgpHNTREMjQqClgzOTY2NVkzNzQwMkQwMyoKTTAyKgpQSwMEFAAACAAAAAAhAPCEfS8NAgAADQIAAA8AAABzZW5zb3Itbm9kZS5wbGNHMDQgT2htZm9yZ2UgZXhhbXBsZSBib2FyZCAtIGdlbmVyYXRlZCB0ZXN0IGRhdGEqCiVGU0xBWDI0WTI0KiUKRzcwKgolTFBEKiUKJUFERDEwQywwLjAwNTkxKiUKRzU0RDEwKgpHMDEqClg0MTAyNFkzODA3MUQwMioKRzAxWDQ1MDM5WTM4MDcxRDAxKgpHMDFYNDUwMzlZNDA4NjZEMDEqCkcwMVg0MTAyNFk0MDg2NkQwMSoKRzAxWDQxMDI0WTM4MDcxRDAxKgpYNDg1ODNZMzUwMDBEMDIqCkcwMVg0OTg0M1kzNTAwMEQwMSoKRzAxWDQ5ODQzWTM3MzYyRDAxKgpHMDFYNDg1ODNZMzczNjJEMDEqCkcwMVg0ODU4M1kzNTAwMEQwMSoKJUFCRDMwKiUKRzU0RDEwKgpYMFkwRDAyKgpHMDFYMFk3ODdEMDEqCkcwMVg0NzJZNzg3RDAxKgpHMDFYNDcyWTBEMDEqCkcwMVgwWTBEMDEqClg3ODdZMEQwMioKRzAxWDc4N1k3ODdEMDEqCkcwMVgxMjYwWTc4N0QwMSoKWDc4N1kzOTREMDIqCkcwMVgxMTAyWTM5NEQwMSoKJUFCKiUKRzU0RDMwKgpYNTMxNTBZNDA1NTFEMDMqCiVMUjkwKiUKWDU4MjY4WTM5MzcwRDAzKgolTFIwKiUKTTAyKgpQSwMEFAAACAAAAAAhAERIzyNcAQAAXAEAAA8AAABzZW5zb3Itbm9kZS5kaW1HMDQgT2htZm9yZ2UgZXhhbXBsZSBib2FyZCAtIGdlbmVyYXRlZCB0ZXN0IGRhdGEqCiVGU0xBWDI0WTI0KiUKRzcwKgolTFBEKiUKJUFERDEwQywwLjAwMzk0KiUKRzU0RDEwKgpHNzUqCkcwMSoKWDQwMTU3WTMxNDk2RDAyKgpHMDFYNTgyNjhZMzE0OTZEMDEqCkcwMyoKWDU5MDU1WTMyMjgzSTBKNzg3RDAxKgpHMDEqCkcwMVg1OTA1NVk0MjUyMEQwMSoKRzAzKgpYNTgyNjhZNDMzMDdJLTc4N0owRDAxKgpHMDEqCkcwMVg0MDE1N1k0MzMwN0QwMSoKRzAzKgpYMzkzNzBZNDI1MjBJMEotNzg3RDAxKgpHMDEqCkcwMVgzOTM3MFkzMjI4M0QwMSoKRzAzKgpYNDAxNTdZMzE0OTZJNzg3SjBEMDEqCkcwMSoKTTAyKgpQSwMEFAAACAAAAAAhAKY57804AQAAOAEAAA8AAABzZW5zb3Itbm9kZS5kcmRNNDgKO0VhZ2xlLXN0eWxlIGRyaWxsIGZpbGUKSU5DSCxUWgpUMUMwLjAxMTgKVDJDMC4wMzk0ClQzQzAuMDQ3MgolCkc5MApHMDUKVDEKWDQ3MjQ0WTMzODU4Clg0ODAzMVk0MDk0NQpYNTI3NTZZMzg5NzYKWDU1MTE4WTM0NjQ2Clg0MzcwMVkzNjYxNApYNTAzOTRZNDE3MzIKVDIKWDQxNTM1WTM4NTgzClg0MTUzNVkzOTU4MwpYNDI1MzVZMzg1ODMKWDQyNTM1WTM5NTgzClg0MzUzNVkzODU4MwpYNDM1MzVZMzk1ODMKWDQ0NTM1WTM4NTgzClg0NDUzNVkzOTU4MwpYMzk2NjVZMzc0MDIKVDMKWDU2Mjk5WTM4MTg5Rzg1WDU2Mjk5WTM5MTczCk0zMApQSwMEFAAACAAAAAAhACl5Bv1zAAAAcwAAABUAAABzZW5zb3Itbm9kZS1ob2xlcy5kcmRNNDgKO0VhZ2xlLXN0eWxlIGRyaWxsIGZpbGUKSU5DSCxUWgpUMUMwLjEyNjAKJQpHOTAKRzA1ClQxClg0MDc0OFkzMjg3NApYNTc2NzdZMzI4NzQKWDQwNzQ4WTQxOTI5Clg1NzY3N1k0MTkyOQpNMzAKUEsBAhQAFAAACAAAAAAhAPXhkebRBgAA0QYAAA8AAAAAAAAAAAAAAAAAAAAAAHNlbnNvci1ub2RlLmNtcFBLAQIUABQAAAgAAAAAIQBJb0EGSwQAAEsEAAAPAAAAAAAAAAAAAAAAAP4GAABzZW5zb3Itbm9kZS5zb2xQSwECFAAUAAAIAAAAACEA25es6nsDAAB7AwAADwAAAAAAAAAAAAAAAAB2CwAAc2Vuc29yLW5vZGUuc3RjUEsBAhQAFAAACAAAAAAhAL9CUyBCAgAAQgIAAA8AAAAAAAAAAAAAAAAAHg8AAHNlbnNvci1ub2RlLnN0c1BLAQIUABQAAAgAAAAAIQDwhH0vDQIAAA0CAAAPAAAAAAAAAAAAAAAAAI0RAABzZW5zb3Itbm9kZS5wbGNQSwECFAAUAAAIAAAAACEAREjPI1wBAABcAQAADwAAAAAAAAAAAAAAAADHEwAAc2Vuc29yLW5vZGUuZGltUEsBAhQAFAAACAAAAAAhAKY57804AQAAOAEAAA8AAAAAAAAAAAAAAAAAUBUAAHNlbnNvci1ub2RlLmRyZFBLAQIUABQAAAgAAAAAIQApeQb9cwAAAHMAAAAVAAAAAAAAAAAAAAAAALUWAABzZW5zb3Itbm9kZS1ob2xlcy5kcmRQSwUGAAAAAAgACADuAQAAWxcAAAAA"
                    },
                    "side": "bottom"
                  }
                },
                "example3": {
                  "summary": "Specification example: two square boxes (pasted Gerber)",
                  "value": {
                    "text": "G04 Ucamco ex. 1: Two square boxes*\n%MOMM*%\n%FSLAX26Y26*%\n%TF.Part,Other,example*%\n%LPD*%\n%ADD10C,0.010*%\nD10*\nX0Y0D02*\nG01*\nX5000000Y0D01*\nY5000000D01*\nX0D01*\nY0D01*\nX6000000D02*\nX11000000D01*\nY5000000D01*\nX6000000D01*\nY0D01*\nM02*\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OhmforgeGerberViewerResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "OhmforgeGerberViewerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "Gerber files (ZIP) or one Gerber or drill file",
            "description": "A ZIP of the fabrication files (layers and drill files) or a single file, up to 25 MB. Files are processed in memory and not kept. Upload as {filename, contentType?, contentBase64}. Max 25600 KiB. Accepts .zip,.gbr,.ger,.pho,.art,.gtl,.gbl,.gts,.gbs,.gto,.gbo,.gtp,.gbp,.gko,.gm1,.gml,.g1,.g2,.g3,.g4,.cmp,.sol,.stc,.sts,.plc,.pls,.crc,.crs,.dim,.drl,.xln,.drd,.exc,.txt,application/zip,text/plain.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "drill": {
            "title": "Separate drill file (optional)",
            "description": "Add an Excellon drill file when it is not inside the ZIP. Upload as {filename, contentType?, contentBase64}. Max 25600 KiB. Accepts .zip,.gbr,.ger,.pho,.art,.gtl,.gbl,.gts,.gbs,.gto,.gbo,.gtp,.gbp,.gko,.gm1,.gml,.g1,.g2,.g3,.g4,.cmp,.sol,.stc,.sts,.plc,.pls,.crc,.crs,.dim,.drl,.xln,.drd,.exc,.txt,application/zip,text/plain.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "text": {
            "title": "Or paste one Gerber or Excellon file",
            "description": "Used together with any uploaded files.",
            "type": "string",
            "maxLength": 500000
          },
          "side": {
            "title": "Board side for the image",
            "type": "string",
            "enum": [
              "top",
              "bottom"
            ],
            "default": "top"
          },
          "minTraceMm": {
            "title": "Minimum trace width",
            "description": "Drawn traces narrower than this are reported.",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.15,
            "x-unit": "mm"
          },
          "minClearanceMm": {
            "title": "Minimum copper clearance",
            "description": "Sampled gaps between separate copper islands below this are reported.",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.15,
            "x-unit": "mm"
          },
          "minAnnularRingMm": {
            "title": "Minimum annular ring",
            "description": "Copper left around a plated hole, from the drill edge to the pad edge.",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.13,
            "x-unit": "mm"
          },
          "minEdgeMm": {
            "title": "Minimum hole-to-edge distance",
            "description": "From the hole edge to the nearest board outline.",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.3,
            "x-unit": "mm"
          },
          "sampleMm": {
            "title": "Sampling grid (0 = automatic)",
            "description": "Grid step for the copper area and clearance estimate; automatic keeps about four million points.",
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0,
            "x-unit": "mm"
          },
          "mountMinMm": {
            "title": "Mounting holes from",
            "type": "number",
            "minimum": 1,
            "maximum": 8,
            "default": 2,
            "x-unit": "mm"
          },
          "mountMaxMm": {
            "title": "Mounting holes up to",
            "description": "Holes in this diameter range are mounting-hole candidates for the enclosure board model.",
            "type": "number",
            "minimum": 1,
            "maximum": 8,
            "default": 4.5,
            "x-unit": "mm"
          }
        },
        "required": []
      },
      "OhmforgeGerberViewerResult": {
        "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": [
              "ok",
              "board",
              "layers",
              "drills",
              "holeCount",
              "slotCount",
              "viaCount",
              "findings",
              "files"
            ],
            "properties": {
              "ok": {
                "type": "boolean"
              },
              "board": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "widthMm": {
                    "type": "number"
                  },
                  "heightMm": {
                    "type": "number"
                  },
                  "areaMm2": {
                    "type": "number"
                  },
                  "perimeterMm": {
                    "type": "number"
                  },
                  "outlineSource": {
                    "type": "string",
                    "enum": [
                      "profile",
                      "box",
                      "copper"
                    ]
                  },
                  "cutouts": {
                    "type": "integer"
                  },
                  "origin": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              "layers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "file": {
                      "type": "string"
                    },
                    "layer": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "side": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "detectedBy": {
                      "type": "string"
                    },
                    "objects": {
                      "type": "integer"
                    },
                    "clearObjects": {
                      "type": "integer"
                    },
                    "unit": {
                      "type": "string"
                    },
                    "minTraceMm": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "clearanceMm": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "copperPercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "drills": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "diameterMm": {
                      "type": "number"
                    },
                    "plated": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "holes": {
                      "type": "integer"
                    },
                    "slots": {
                      "type": "integer"
                    }
                  }
                }
              },
              "holeCount": {
                "type": "integer"
              },
              "slotCount": {
                "type": "integer"
              },
              "viaCount": {
                "type": "integer"
              },
              "minTraceMm": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "minClearanceMm": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "minAnnularRingMm": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "minEdgeMm": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "sampleMm": {
                "type": "number"
              },
              "rules": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "minTraceMm": {
                    "type": "number"
                  },
                  "minClearanceMm": {
                    "type": "number"
                  },
                  "minAnnularRingMm": {
                    "type": "number"
                  },
                  "minEdgeMm": {
                    "type": "number"
                  }
                }
              },
              "findings": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "check": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "layer": {
                      "type": "string"
                    },
                    "at": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    },
                    "valueMm": {
                      "type": "number"
                    },
                    "limitMm": {
                      "type": "number"
                    },
                    "text": {
                      "type": "string"
                    }
                  }
                }
              },
              "mountingHoleCandidates": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "diameter": {
                      "type": "number"
                    },
                    "plated": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "edgeMm": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "preselected": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "boardModel": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "notes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "boardPng",
                  "boardTopSvg",
                  "boardBottomSvg",
                  "layersSvg",
                  "layerSvgZip",
                  "report"
                ],
                "properties": {
                  "boardPng": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "boardTopSvg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "boardBottomSvg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "layersSvg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "layerSvgZip": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "report": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "boardJson": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "project": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}