{
  "openapi": "3.1.1",
  "info": {
    "title": "Printshop API",
    "version": "1.0.0",
    "summary": "Deterministic tools for people and AI agents.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://printshop.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/tools": {
      "get": {
        "operationId": "listTools",
        "summary": "Catalog of all tools",
        "responses": {
          "200": {
            "description": "Tool list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/{id}": {
      "get": {
        "operationId": "getTool",
        "summary": "Definition of one tool",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "printshop-qr-code",
                "printshop-barcode",
                "printshop-calendar",
                "printshop-label-sheet",
                "printshop-graph-paper",
                "printshop-poster-tiler",
                "printshop-booklet",
                "ruledate",
                "lumina-print-planner",
                "lumina-image-splitter",
                "panelcraft-book-plan"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-qr-code/calculate": {
      "post": {
        "operationId": "calculatePrintshopQrCode",
        "summary": "QR codes for links, text, Wi-Fi, contacts and more — as vector PDF, SVG and PNG.",
        "description": "Encode a link, text, Wi-Fi login, contact card, e-mail, phone, SMS or map location as a QR code following ISO/IEC 18004 (versions 1–40, error correction L/M/Q/H, optimal mode switching, all eight masks scored). Get a print page with a test square, the code alone as SVG and PNG, a sheet of copies or Wi-Fi guest cards.\n\nMethodology:\n- Data is split into numeric, alphanumeric and byte (UTF-8) segments with the fewest bits (dynamic programming over the bit costs of ISO/IEC 18004 §7.4); the smallest version 1–40 that holds it at the chosen error-correction level is used.\n- Reed–Solomon error correction over GF(256) (polynomial 0x11D), block interleaving after Table 9, all eight masks scored with the four penalty rules and the lowest chosen; format and version information use the BCH codes of §7.9–7.10.\n- The logo-safe area clears the centre modules (never finder, timing or alignment patterns) and counts, per Reed–Solomon block, how many codewords it touches; the area is reported safe only when that stays within half of the block’s error-correction codewords.\n- Wi-Fi codes use the WIFI:T:…;S:…;P:…;; format read by phone cameras (special characters escaped). Pages print at true size with a 20 mm (or 1 in) test square.\n\n“QR Code” is a registered trademark of DENSO WAVE INCORPORATED. Test a printed code with the phones of your audience before printing many copies.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_qr_code",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopQrCodeInput"
              },
              "examples": {
                "example1": {
                  "summary": "Link to a website",
                  "value": {
                    "content": "url",
                    "text": "https://usefulweb.site/",
                    "ecc": "M",
                    "size": 60
                  }
                },
                "example2": {
                  "summary": "Wi-Fi guest cards",
                  "value": {
                    "content": "wifi",
                    "ssid": "Guest network",
                    "password": "sunny-garden-2027",
                    "security": "WPA",
                    "layout": "wifi-card"
                  }
                },
                "example3": {
                  "summary": "Sheet of small codes with a logo-safe centre",
                  "value": {
                    "content": "text",
                    "text": "Table 12 · ask for the menu",
                    "ecc": "H",
                    "size": 40,
                    "logo": 20,
                    "layout": "sheet",
                    "caption": "Scan for the menu"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopQrCodeResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-barcode/calculate": {
      "post": {
        "operationId": "calculatePrintshopBarcode",
        "summary": "EAN-13, UPC-A and Code 128 barcodes with check digits, true-size PDF, SVG and PNG.",
        "description": "Make an EAN-13, UPC-A or Code 128 barcode. EAN/UPC check digits are calculated (or verified), Code 128 switches between code sets A, B and C for the shortest symbol, and the result prints at GS1 sizes with quiet zones and a test square.\n\nMethodology:\n- EAN-13: the first digit selects the L/G parity pattern of the left half (GS1 table), the right half uses R codes; the check digit is the mod-10 sum with weights 3 and 1 from the right. UPC-A is encoded as EAN-13 with a leading 0.\n- Code 128: a dynamic programme over (position, active code set) picks start code, CODE A/B/C switches and SHIFT for the fewest symbol characters; check value = (start + Σ value × position) mod 103.\n- Sizes: EAN/UPC module 0.330 mm × magnification (80–200 %), bar height 22.85 mm × magnification, guard bars 5 modules longer; quiet zones 11/7 modules (EAN-13), 9/9 (UPC-A), 10/10 (Code 128).\n\nRetail EAN/UPC numbers must be licensed from GS1; making a barcode does not register a product number. Check print quality with a scanner before mass printing.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_barcode",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopBarcodeInput"
              },
              "examples": {
                "example1": {
                  "summary": "EAN-13 with the check digit added",
                  "value": {
                    "symbology": "ean13",
                    "data": "400638133393"
                  }
                },
                "example2": {
                  "summary": "UPC-A",
                  "value": {
                    "symbology": "upca",
                    "data": "03600029145"
                  }
                },
                "example3": {
                  "summary": "Code 128 for a parcel reference",
                  "value": {
                    "symbology": "code128",
                    "data": "PO-2027-000123",
                    "height": 15,
                    "layout": "sheet"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopBarcodeResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-calendar/calculate": {
      "post": {
        "operationId": "calculatePrintshopCalendar",
        "summary": "Month or year calendars in 17 languages with week numbers and public holidays.",
        "description": "Make a printable calendar for any year: one month per page or the whole year on one page, in 17 languages including right-to-left Arabic, with ISO 8601 or US week numbers, the first weekday of the region and public holidays for 16 countries (2024–2030).\n\nMethodology:\n- Month grids use the proleptic Gregorian calendar in UTC. The first weekday follows CLDR week data for the region (for example Sunday in the US, Monday in Germany, Saturday in Egypt) unless you choose one.\n- ISO 8601 weeks start on Monday and week 1 contains the year’s first Thursday; a row shows the ISO week of its Monday. US weeks start on Sunday and week 1 contains 1 January; a row shows the US week of its Saturday.\n- Month and weekday names come from the CLDR data built into the JavaScript runtime (Intl.DateTimeFormat). Arabic calendars run right to left. Text is shaped and embedded with Noto fonts.\n- Public holidays come from the RuleDate data set (Nager.Date) for 16 countries, 2024–2030; regional holidays need an ISO 3166-2 region code.\n\nHoliday data covers 2024–2030 and nationwide plus listed regional holidays; school holidays and local observances are not included. Check dates that matter.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_calendar",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopCalendarInput"
              },
              "examples": {
                "example1": {
                  "summary": "German 2027 wall calendar with ISO weeks and Bavarian holidays",
                  "value": {
                    "year": 2027,
                    "lang": "de",
                    "country": "DE",
                    "subdivision": "DE-BY",
                    "weekNumbers": "iso"
                  }
                },
                "example2": {
                  "summary": "US year at a glance on Letter landscape",
                  "value": {
                    "year": 2027,
                    "layout": "year",
                    "country": "US",
                    "paper": "letter",
                    "orientation": "landscape",
                    "weekNumbers": "us"
                  }
                },
                "example3": {
                  "summary": "Arabic six-month calendar",
                  "value": {
                    "year": 2027,
                    "months": 6,
                    "lang": "ar",
                    "weekStart": "sat"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopCalendarResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-label-sheet/calculate": {
      "post": {
        "operationId": "calculatePrintshopLabelSheet",
        "summary": "Address labels, name badges and product labels from a CSV, for any sheet layout.",
        "description": "Fill a sheet of labels from CSV rows with a {Column} template: address labels, name badges, jar and product labels. Use a generic sheet layout or enter your own geometry, skip labels already used, add a QR code or barcode per label and print a true-size PDF.\n\nMethodology:\n- CSV is read after RFC 4180 (quoted fields, doubled quotes, line breaks inside quotes); comma, semicolon or tab is detected from the header line. Each row fills the {Column} placeholders of the template.\n- Label n sits at left + column × horizontal pitch, top + row × vertical pitch, filled row by row; “start at” skips used positions on the first sheet. Presets are generic dimension sets (no brand or product numbers).\n- Text is wrapped to the label width and reduced in 10 % steps until it fits; labels whose text still does not fit are counted as overflow. A QR code takes up to 45 % of the width; barcodes sit at the bottom.\n\nPrinters shift paper by up to a millimetre or two. Print one test page on plain paper, hold it against a label sheet and adjust the margins before printing on labels.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_label_sheet",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopLabelSheetInput"
              },
              "examples": {
                "example1": {
                  "summary": "Address labels on a 3 × 8 sheet",
                  "value": {}
                },
                "example2": {
                  "summary": "Jar labels with a QR code, starting at label 4",
                  "value": {
                    "sheet": "a4-3x7-63x38",
                    "template": "{Product}\nBest before {Date}",
                    "csv": "Product,Date,Code\nPlum jam,2028-06,https://example.com/jam/plum\nApricot jam,2028-07,https://example.com/jam/apricot",
                    "code": "qr",
                    "codeTemplate": "{Code}",
                    "fontSize": 4.5,
                    "align": "start",
                    "startAt": 4,
                    "outlines": true
                  }
                },
                "example3": {
                  "summary": "Custom 2 × 3 badges",
                  "value": {
                    "sheet": "custom",
                    "cols": 2,
                    "rows": 3,
                    "labelW": 90,
                    "labelH": 80,
                    "top": 18.5,
                    "left": 12,
                    "pitchX": 96,
                    "pitchY": 88,
                    "template": "{Name}\n{Team}",
                    "csv": "Name,Team\nAlex,Design\nSam,Support\nKim,Finance",
                    "align": "middle",
                    "fontSize": 8,
                    "outlines": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopLabelSheetResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-graph-paper/calculate": {
      "post": {
        "operationId": "calculatePrintshopGraphPaper",
        "summary": "Printable grid, dot, isometric, hexagon, music staff and lined paper at exact sizes.",
        "description": "Make printable paper with a square grid (with major lines), dot grid, isometric triangles, hexagons, music staves or writing lines. Spacing is exact in millimetres, the grid is centred on the page and a 10 cm scale bar lets you check the printer scale.\n\nMethodology:\n- Square and dot grids use whole cells centred in the area inside the margin, so leftover space is split evenly. Major lines count from the first line.\n- Isometric paper draws three families of lines (horizontal and ±60°) that form equilateral triangles of the given side; hexagons are regular with the given side, in offset rows (pointy top) or columns (flat top).\n- Music staves have five lines with the given spacing and a gap of 1.75 staff heights between staves. Lined paper starts one line spacing below the top margin.\n\nPrint at 100 % (actual size) and check the 10 cm scale bar: “fit to page” changes every spacing.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_graph_paper",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopGraphPaperInput"
              },
              "examples": {
                "example1": {
                  "summary": "5 mm grid with centimetre lines",
                  "value": {
                    "kind": "grid",
                    "spacing": 5,
                    "majorEvery": 2
                  }
                },
                "example2": {
                  "summary": "Dot grid journal page",
                  "value": {
                    "kind": "dots",
                    "spacing": 5,
                    "majorEvery": 0,
                    "color": "#8f9aa6"
                  }
                },
                "example3": {
                  "summary": "Isometric drawing paper",
                  "value": {
                    "kind": "isometric",
                    "spacing": 8,
                    "majorEvery": 0
                  }
                },
                "example4": {
                  "summary": "Music staff paper",
                  "value": {
                    "kind": "music",
                    "spacing": 2,
                    "header": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopGraphPaperResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-poster-tiler/calculate": {
      "post": {
        "operationId": "calculatePrintshopPosterTiler",
        "summary": "Print a big poster on ordinary paper: tiles with overlap, crop marks and an assembly map.",
        "description": "Enlarge a JPEG or PNG to a poster of any width and split it over A4, Letter or other sheets with overlap, trim lines, crop marks, alignment crosses and tile names, plus a cover page with the assembly map, the effective resolution and a test square. Without an image you get the tiling plan.\n\nMethodology:\n- Printable area = paper − 2 × margin; each next sheet starts one step = printable − overlap further, so neighbouring sheets share the overlap strip. Sheets across = ceil((poster − overlap) / step); with “fewest sheets” both orientations are tried.\n- The image is embedded once (JPEG unchanged, PNG losslessly compressed) and every sheet shows its part through a clipping rectangle, so the PDF stays small and keeps the full resolution.\n- Effective resolution = image pixels ÷ poster inches (Lumina’s print planner gives the matching print size table). Below about 100 pixels per inch prints look soft up close.\n\nPrinters differ slightly in scale and margins: print the cover page first and measure the 50 mm test square. Interlaced PNG and CMYK JPEG files are not supported.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_poster_tiler",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopPosterTilerInput"
              },
              "examples": {
                "example1": {
                  "summary": "60 cm poster plan for a 4000 × 3000 photo",
                  "value": {
                    "imageWidth": 4000,
                    "imageHeight": 3000,
                    "width": 600
                  }
                },
                "example2": {
                  "summary": "One-metre portrait poster on Letter paper",
                  "value": {
                    "imageWidth": 3000,
                    "imageHeight": 4500,
                    "width": 1000,
                    "paper": "letter",
                    "overlap": 15
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopPosterTilerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/printshop-booklet/calculate": {
      "post": {
        "operationId": "calculatePrintshopBooklet",
        "summary": "Fold-and-staple booklets: notebook or calendar pages imposed in the right order.",
        "description": "Make a saddle-stitched booklet: pages of grid, dot or lined paper (a notebook) or a month-per-page calendar are padded to a multiple of four and printed two per sheet side in booklet order, with optional creep compensation, page numbers and fold marks. Prints double-sided, flip on the short edge.\n\nMethodology:\n- Pages are padded with blanks to a multiple of four. Sheet k (from the outside) carries pages (n − 2k, 2k + 1) on the front and (2k + 2, n − 2k − 1) on the back — Panelcraft’s booklet order; right-edge binding swaps each pair.\n- Each page is scaled uniformly into half of the landscape sheet and centred; with creep compensation the pages of sheet k move k × creep towards the fold, because inner sheets stick out further after folding.\n- The PDF alternates front and back of each sheet: print double-sided, flipping on the short edge, then fold the stack and staple along the fold.\n\nDuplex settings differ between printers: print the first sheet and check the page order before printing all.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_booklet",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopBookletInput"
              },
              "examples": {
                "example1": {
                  "summary": "16-page dot-grid pocket notebook",
                  "value": {
                    "source": "ruled",
                    "pages": 16,
                    "kind": "dots"
                  }
                },
                "example2": {
                  "summary": "2027 pocket calendar (12 months, 3 sheets)",
                  "value": {
                    "source": "calendar",
                    "year": 2027
                  }
                },
                "example3": {
                  "summary": "Right-bound 8-page lined booklet with creep",
                  "value": {
                    "source": "ruled",
                    "pages": 8,
                    "kind": "lined",
                    "spacing": 7,
                    "reading": "rtl",
                    "creep": 0.1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopBookletResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/ruledate/calculate": {
      "post": {
        "operationId": "calculateRuledate",
        "summary": "Business-day and deadline maths with public holidays and a step-by-step rule trace.",
        "description": "Chain date operations (add business days, add months with clamping, end of month, roll to next business day) on a start date. RuleDate uses public holidays for 16 countries and their subdivisions (2024–2030) and shows every skipped date with its reason, so the result can be checked rather than trusted.\n\nMethodology:\n- A business day is a day that is not a selected weekend day, not a public holiday of the chosen country (nationwide, or of the chosen subdivision) and not an extra closure date. Only Nager.Date entries of type \"Public\" count; bank, school, optional and observance days are ignored.\n- Add business days counts business days after the start date (the start date itself is not counted); negative amounts count backwards. Every non-business day passed over is listed with all its reasons.\n- Add calendar days / weeks ignore holidays. Add months keeps the day of month; if it does not exist, \"clamp\" uses the month’s last day and \"overflow\" rolls into the next month.\n- End of month moves to the last calendar day of the month that is `amount` months after the current date. Next / previous business day roll only if the current date is not a business day (following / preceding convention).\n- Optional final rule modelled on § 193 BGB: if the result falls on a Saturday, Sunday or a public holiday at the chosen place, it moves to the next day that is none of these (extra closures and custom weekends are ignored for this rule).\n- Holiday data covers 2024–2030; dates outside that range are checked for weekends and closures only and trigger a warning.\n\nNot legal advice. Statutory and contractual deadlines have their own rules (start-day exclusion, service dates, court holidays, local holidays); verify critical deadlines with a qualified professional.",
        "tags": [
          "developer"
        ],
        "x-mcp-tool": "ruledate",
        "x-owner-app": "opsdeck",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuledateInput"
              },
              "examples": {
                "example1": {
                  "summary": "10 business days from 25 Sep 2026 in Bavaria",
                  "value": {
                    "startDate": "2026-09-25",
                    "operations": [
                      {
                        "op": "add-business-days",
                        "amount": 10
                      }
                    ],
                    "country": "DE",
                    "subdivision": "DE-BY"
                  }
                },
                "example2": {
                  "summary": "5 business days over Christmas in England, then end of month",
                  "value": {
                    "startDate": "2026-12-21",
                    "operations": [
                      {
                        "op": "add-business-days",
                        "amount": 5
                      },
                      {
                        "op": "end-of-month",
                        "amount": 0
                      },
                      {
                        "op": "previous-business-day"
                      }
                    ],
                    "country": "GB",
                    "subdivision": "GB-ENG"
                  }
                },
                "example3": {
                  "summary": "31 Aug + 1 month (clamped) + 3 days, § 193 BGB adjustment",
                  "value": {
                    "startDate": "2026-08-31",
                    "operations": [
                      {
                        "op": "add-months",
                        "amount": 1
                      },
                      {
                        "op": "add-calendar-days",
                        "amount": 3
                      }
                    ],
                    "country": "DE",
                    "finalRule": "bgb193"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuledateResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/lumina-print-planner/calculate": {
      "post": {
        "operationId": "calculateLuminaPrintPlanner",
        "summary": "Find how large your photo can print at your chosen resolution.",
        "description": "Convert image pixel dimensions into print dimensions in inches and centimeters at a specified pixels-per-inch resolution. Compare sizes without uploading the image.\n\nMethodology:\n- Print width in inches equals pixel width divided by PPI. One inch equals 2.54 centimeters.\n- PPI describes image pixel density, not printer dot density. Calculated dimensions do not guarantee print quality.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "lumina_print_planner",
        "x-owner-app": "lumina",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LuminaPrintPlannerInput"
              },
              "examples": {
                "example1": {
                  "summary": "24 MP photo at 300 PPI",
                  "value": {
                    "width": 6000,
                    "height": 4000,
                    "ppi": 300
                  }
                },
                "example2": {
                  "summary": "Web image at 150 PPI",
                  "value": {
                    "width": 1920,
                    "height": 1080,
                    "ppi": 150
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LuminaPrintPlannerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/lumina-image-splitter/calculate": {
      "post": {
        "operationId": "calculateLuminaImageSplitter",
        "summary": "Slice a photo into numbered tiles without losing edge pixels.",
        "description": "Split one image into a row-and-column grid and download every tile as a PNG in one ZIP. Uneven dimensions are distributed across the tiles so the complete photo can be reconstructed.\n\nMethodology:\n- The source is auto-oriented. Integer boundaries use floor(index × size / count), ensuring no gaps, overlaps or missing edge pixels.\n- At most 64 nonempty tiles; original decoded photo limited to 16 MP. ZIP names encode row and column.\n- Outputs are PNGs with original EXIF/GPS removed. The ZIP includes a JSON manifest with the exact tile coordinates.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "lumina_image_splitter",
        "x-owner-app": "lumina",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LuminaImageSplitterInput"
              },
              "examples": {
                "example1": {
                  "summary": "Three-by-three tiles",
                  "value": {
                    "images": {
                      "filename": "sample.png",
                      "contentType": "image/png",
                      "contentBase64": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAQMAAABJtOi3AAAABlBMVEX/////AADrWueTAAAAEklEQVQI12NgIBb8/09dgjgAAPcnH+GApkH4AAAAAElFTkSuQmCC"
                    },
                    "rows": 3,
                    "columns": 3
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LuminaImageSplitterResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/panelcraft-book-plan/calculate": {
      "post": {
        "operationId": "calculatePanelcraftBookPlan",
        "summary": "Plan a multi-page comic, contact sheet and folded booklet order.",
        "description": "Create an editable Panelcraft comic book with ordered pages and panel grids. Export a clean SVG contact sheet, complete lettering CSV and book project, plus a deterministic sheet-front and sheet-back imposition plan for a folded booklet.\n\nMethodology:\n- Create 1–12 pages using the same bounded Comic Desk page parser as the interactive workspace. Each page has 1–12 rectangular panels; page dimensions are 1000 × 1400 px at 150 DPI.\n- A contact sheet uses 360 px thumbnails, up to four columns, unique SVG definition IDs and a maximum area of 8 megapixels. It is an overview, not a print-size page export.\n- Booklet page count rounds up to a multiple of four. Sheet fronts pair the last and first remaining pages; backs pair the second and penultimate. Pages beyond the source count are blanks. Right-to-left binding reverses each pair. Consult the printer manual for duplex orientation.\n\nImposition is a page-order plan for manually arranging a folded booklet. It does not rescale pages to a printer sheet or set printer-specific duplex options.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "panelcraft_book_plan",
        "x-owner-app": "panelcraft",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PanelcraftBookPlanInput"
              },
              "examples": {
                "example1": {
                  "summary": "An eight-page pocket comic",
                  "value": {}
                },
                "example2": {
                  "summary": "A six-page right-to-left draft",
                  "value": {
                    "pages": 6,
                    "reading": "rtl",
                    "rows": 1,
                    "columns": 2
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PanelcraftBookPlanResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows": {
      "get": {
        "operationId": "listWorkflows",
        "summary": "Multi-tool workflows",
        "responses": {
          "200": {
            "description": "Workflow list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PrintshopQrCodeInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "content": {
            "title": "Content type",
            "type": "string",
            "enum": [
              "url",
              "text",
              "wifi",
              "email",
              "phone",
              "sms",
              "geo"
            ],
            "default": "url"
          },
          "text": {
            "title": "Content",
            "description": "The address, text, e-mail address, phone number or \"latitude, longitude\". Not used for Wi-Fi.",
            "type": "string",
            "maxLength": 4000,
            "default": "https://usefulweb.site/"
          },
          "ssid": {
            "title": "Wi-Fi network name (SSID)",
            "type": "string",
            "maxLength": 64,
            "default": ""
          },
          "password": {
            "title": "Wi-Fi password",
            "description": "Only used for the code; it is not shown in the result or stored in the share link.",
            "type": "string",
            "maxLength": 63,
            "default": ""
          },
          "security": {
            "title": "Wi-Fi security",
            "type": "string",
            "enum": [
              "WPA",
              "WEP",
              "nopass"
            ],
            "default": "WPA"
          },
          "hidden": {
            "title": "Hidden network",
            "type": "boolean",
            "default": false
          },
          "layout": {
            "title": "Print layout",
            "type": "string",
            "enum": [
              "one",
              "sheet",
              "wifi-card"
            ],
            "default": "one"
          },
          "ecc": {
            "title": "Error correction",
            "type": "string",
            "enum": [
              "L",
              "M",
              "Q",
              "H"
            ],
            "default": "M"
          },
          "size": {
            "title": "Code width (mm, with quiet zone)",
            "type": "number",
            "minimum": 10,
            "maximum": 400,
            "default": 60
          },
          "quiet": {
            "title": "Quiet zone (modules)",
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "default": 4
          },
          "dark": {
            "title": "Dark colour",
            "type": "string",
            "maxLength": 7,
            "default": "#000000"
          },
          "light": {
            "title": "Light colour",
            "type": "string",
            "maxLength": 7,
            "default": "#ffffff"
          },
          "logo": {
            "title": "Logo-safe area (% of the code width)",
            "description": "Leaves an empty square in the centre for a logo and checks it against the error correction.",
            "type": "number",
            "minimum": 0,
            "maximum": 30,
            "default": 0
          },
          "caption": {
            "title": "Caption under the code",
            "type": "string",
            "maxLength": 200,
            "default": ""
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "orientation": {
            "title": "Orientation",
            "type": "string",
            "enum": [
              "portrait",
              "landscape"
            ],
            "default": "portrait"
          }
        },
        "required": []
      },
      "PrintshopQrCodeResult": {
        "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": [
              "version",
              "modules",
              "ecc",
              "mask",
              "segments",
              "dataBits",
              "capacityBits",
              "moduleMm",
              "payloadChars",
              "logo",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "version": {
                "type": "integer"
              },
              "modules": {
                "type": "integer"
              },
              "ecc": {
                "type": "string"
              },
              "mask": {
                "type": "integer"
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "dataBits": {
                "type": "integer"
              },
              "capacityBits": {
                "type": "integer"
              },
              "moduleMm": {
                "type": "number"
              },
              "payloadChars": {
                "type": "integer"
              },
              "logo": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "safe",
                  "worstBlockCodewords",
                  "correctablePerBlock"
                ],
                "properties": {
                  "safe": {
                    "type": "boolean"
                  },
                  "worstBlockCodewords": {
                    "type": "integer"
                  },
                  "correctablePerBlock": {
                    "type": "integer"
                  }
                }
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopBarcodeInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "symbology": {
            "title": "Barcode type",
            "type": "string",
            "enum": [
              "ean13",
              "upca",
              "code128"
            ],
            "default": "ean13"
          },
          "data": {
            "title": "Data",
            "description": "EAN-13: 12 digits (the check digit is added) or 13 digits (it is checked). UPC-A: 11 or 12 digits. Code 128: up to 80 ASCII characters.",
            "type": "string",
            "maxLength": 80,
            "default": "400638133393"
          },
          "magnification": {
            "title": "Size (magnification)",
            "description": "EAN/UPC: 1 = 0.33 mm modules (GS1 nominal); Code 128: 1 = 0.30 mm modules.",
            "type": "number",
            "minimum": 0.8,
            "maximum": 2,
            "default": 1
          },
          "height": {
            "title": "Bar height (mm)",
            "type": "number",
            "minimum": 5,
            "maximum": 100,
            "default": 22.85
          },
          "text": {
            "title": "Print the digits under the bars",
            "type": "boolean",
            "default": true
          },
          "layout": {
            "title": "Print layout",
            "type": "string",
            "enum": [
              "one",
              "sheet"
            ],
            "default": "one"
          },
          "caption": {
            "title": "Caption above the barcode",
            "type": "string",
            "maxLength": 200,
            "default": ""
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          }
        },
        "required": []
      },
      "PrintshopBarcodeResult": {
        "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": [
              "symbology",
              "text",
              "checkDigit",
              "modules",
              "xMm",
              "widthMm",
              "codeSets",
              "symbolValues",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "symbology": {
                "type": "string"
              },
              "text": {
                "type": "string"
              },
              "checkDigit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "modules": {
                "type": "integer"
              },
              "xMm": {
                "type": "number"
              },
              "widthMm": {
                "type": "number"
              },
              "codeSets": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "symbolValues": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "integer"
                }
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopCalendarInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "year": {
            "title": "Year",
            "type": "integer",
            "minimum": 1900,
            "maximum": 2200,
            "default": 2027
          },
          "startMonth": {
            "title": "First month",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 1
          },
          "months": {
            "title": "Number of months",
            "type": "integer",
            "minimum": 1,
            "maximum": 24,
            "default": 12
          },
          "layout": {
            "title": "Layout",
            "type": "string",
            "enum": [
              "month",
              "year"
            ],
            "default": "month"
          },
          "lang": {
            "title": "Language of month and day names",
            "type": "string",
            "enum": [
              "en",
              "de",
              "fr",
              "es",
              "it",
              "pt",
              "nl",
              "pl",
              "tr",
              "ru",
              "uk",
              "ar",
              "hi",
              "zh",
              "ja",
              "ko",
              "id"
            ],
            "default": "en"
          },
          "country": {
            "title": "Public holidays",
            "type": "string",
            "enum": [
              "none",
              "DE",
              "AT",
              "CH",
              "US",
              "GB",
              "FR",
              "NL",
              "BE",
              "ES",
              "IT",
              "PL",
              "SE",
              "DK",
              "IE",
              "CA",
              "AU"
            ],
            "default": "none"
          },
          "subdivision": {
            "title": "Region (optional)",
            "description": "ISO 3166-2 code such as DE-BY, CH-ZH or US-CA for regional holidays.",
            "type": "string",
            "maxLength": 10,
            "default": ""
          },
          "localNames": {
            "title": "Holiday names in the local language",
            "type": "boolean",
            "default": true
          },
          "weekStart": {
            "title": "First day of the week",
            "type": "string",
            "enum": [
              "auto",
              "mon",
              "sun",
              "sat"
            ],
            "default": "auto"
          },
          "weekNumbers": {
            "title": "Week numbers",
            "type": "string",
            "enum": [
              "none",
              "iso",
              "us"
            ],
            "default": "none"
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "orientation": {
            "title": "Orientation",
            "type": "string",
            "enum": [
              "portrait",
              "landscape"
            ],
            "default": "portrait"
          },
          "accent": {
            "title": "Accent colour",
            "type": "string",
            "maxLength": 7,
            "default": "#1f6f8b"
          },
          "title": {
            "title": "Title (optional)",
            "type": "string",
            "maxLength": 120,
            "default": ""
          },
          "notes": {
            "title": "Notes lines under each month",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "PrintshopCalendarResult": {
        "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": [
              "year",
              "months",
              "firstWeekday",
              "holidays",
              "holidayDataCovers",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "year": {
                "type": "integer"
              },
              "months": {
                "type": "integer"
              },
              "firstWeekday": {
                "type": "string"
              },
              "holidayDataCovers": {
                "type": "boolean"
              },
              "holidays": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "date",
                    "name"
                  ],
                  "properties": {
                    "date": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopLabelSheetInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "sheet": {
            "title": "Sheet layout",
            "type": "string",
            "enum": [
              "a4-3x8-70x37",
              "a4-3x7-63x38",
              "a4-2x7-99x38",
              "a4-2x4-99x68",
              "a4-4x10-48x25",
              "a4-5x13-38x21",
              "a4-2x5-90x54",
              "a4-4x6-round40",
              "letter-3x10",
              "letter-2x10",
              "letter-2x5",
              "letter-4x20",
              "letter-3x4-round2",
              "custom"
            ],
            "default": "a4-3x8-70x37"
          },
          "paper": {
            "title": "Paper size (custom layout)",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "cols": {
            "title": "Columns (custom)",
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "default": 3
          },
          "rows": {
            "title": "Rows (custom)",
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "default": 8
          },
          "labelW": {
            "title": "Label width (mm, custom)",
            "type": "number",
            "minimum": 5,
            "maximum": 1200,
            "default": 70
          },
          "labelH": {
            "title": "Label height (mm, custom)",
            "type": "number",
            "minimum": 5,
            "maximum": 1200,
            "default": 37
          },
          "top": {
            "title": "Top margin (mm, custom)",
            "type": "number",
            "minimum": 0,
            "maximum": 600,
            "default": 0.5
          },
          "left": {
            "title": "Left margin (mm, custom)",
            "type": "number",
            "minimum": 0,
            "maximum": 600,
            "default": 0
          },
          "pitchX": {
            "title": "Horizontal pitch (mm, custom)",
            "description": "Distance from the left edge of one label to the left edge of the next.",
            "type": "number",
            "minimum": 5,
            "maximum": 1200,
            "default": 70
          },
          "pitchY": {
            "title": "Vertical pitch (mm, custom)",
            "type": "number",
            "minimum": 5,
            "maximum": 1200,
            "default": 37
          },
          "template": {
            "title": "Label text",
            "description": "Use {Column} for values from the CSV header.",
            "type": "string",
            "maxLength": 2000,
            "default": "{Name}\n{Street}\n{Postcode} {City}"
          },
          "csv": {
            "title": "CSV data (first row = column names)",
            "type": "string",
            "maxLength": 200000,
            "default": "Name,Street,Postcode,City\nAda Example,1 Sample Road,12345,Exampletown\nBo Sample,22 Test Lane,54321,Demoville"
          },
          "code": {
            "title": "Code on each label",
            "type": "string",
            "enum": [
              "none",
              "qr",
              "code128",
              "ean13"
            ],
            "default": "none"
          },
          "codeTemplate": {
            "title": "Code content",
            "description": "Template for the code, for example {SKU} or https://example.com/{Id}.",
            "type": "string",
            "maxLength": 500,
            "default": ""
          },
          "fontSize": {
            "title": "Font size (mm)",
            "description": "The text shrinks automatically when it does not fit.",
            "type": "number",
            "minimum": 1.5,
            "maximum": 20,
            "default": 3.6
          },
          "align": {
            "title": "Alignment",
            "type": "string",
            "enum": [
              "start",
              "middle",
              "end"
            ],
            "default": "start"
          },
          "startAt": {
            "title": "Start at label number",
            "description": "Skip labels already used on a partly used sheet (counted row by row).",
            "type": "integer",
            "minimum": 1,
            "maximum": 900,
            "default": 1
          },
          "copies": {
            "title": "Copies of each label",
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 1
          },
          "outlines": {
            "title": "Draw label outlines",
            "description": "Useful for a test print on plain paper; usually off for real label sheets.",
            "type": "boolean",
            "default": false
          }
        },
        "required": []
      },
      "PrintshopLabelSheetResult": {
        "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": [
              "labels",
              "records",
              "perSheet",
              "overflow",
              "missingFields",
              "codeErrors",
              "sheetLabel",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "labels": {
                "type": "integer"
              },
              "records": {
                "type": "integer"
              },
              "perSheet": {
                "type": "integer"
              },
              "overflow": {
                "type": "integer"
              },
              "missingFields": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "codeErrors": {
                "type": "integer"
              },
              "sheetLabel": {
                "type": "string"
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopGraphPaperInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kind": {
            "title": "Paper type",
            "type": "string",
            "enum": [
              "grid",
              "dots",
              "isometric",
              "hex",
              "music",
              "lined"
            ],
            "default": "grid"
          },
          "spacing": {
            "title": "Spacing (mm, 0 = usual for the paper type)",
            "description": "Grid/dot pitch, triangle or hexagon side, line distance, or the distance between two staff lines. 0 uses 5 mm for grid and dots, 8 mm for isometric, hexagons and lined paper, 2 mm for music staves.",
            "type": "number",
            "minimum": 0,
            "maximum": 50,
            "default": 0
          },
          "majorEvery": {
            "title": "Major line every … cells",
            "type": "integer",
            "minimum": 0,
            "maximum": 20,
            "default": 5
          },
          "lineWidth": {
            "title": "Line width (mm)",
            "type": "number",
            "minimum": 0.05,
            "maximum": 2,
            "default": 0.15
          },
          "color": {
            "title": "Line colour",
            "type": "string",
            "maxLength": 7,
            "default": "#9db7d5"
          },
          "majorColor": {
            "title": "Major line colour",
            "type": "string",
            "maxLength": 7,
            "default": "#5f86b5"
          },
          "margin": {
            "title": "Margin (mm)",
            "type": "number",
            "minimum": 0,
            "maximum": 50,
            "default": 10
          },
          "marginLine": {
            "title": "Margin line for lined paper (mm from the left)",
            "type": "number",
            "minimum": 0,
            "maximum": 200,
            "default": 0
          },
          "header": {
            "title": "Name and date line at the top",
            "type": "boolean",
            "default": false
          },
          "hexOrientation": {
            "title": "Hexagon orientation",
            "type": "string",
            "enum": [
              "pointy",
              "flat"
            ],
            "default": "pointy"
          },
          "pages": {
            "title": "Pages",
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 1
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "orientation": {
            "title": "Orientation",
            "type": "string",
            "enum": [
              "portrait",
              "landscape"
            ],
            "default": "portrait"
          }
        },
        "required": []
      },
      "PrintshopGraphPaperResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "spacingMm",
              "cellsPerPage",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "kind": {
                "type": "string"
              },
              "spacingMm": {
                "type": "number"
              },
              "cellsPerPage": {
                "type": "integer"
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopPosterTilerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "image": {
            "title": "Image (JPEG or PNG, optional)",
            "type": "object",
            "description": "Upload as {filename, contentType?, contentBase64}. Max 24414 KiB. Accepts image/jpeg,image/png.",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "imageWidth": {
            "title": "Image width in pixels (when no file)",
            "type": "integer",
            "minimum": 1,
            "maximum": 100000,
            "default": 4000
          },
          "imageHeight": {
            "title": "Image height in pixels (when no file)",
            "type": "integer",
            "minimum": 1,
            "maximum": 100000,
            "default": 3000
          },
          "width": {
            "title": "Poster width (mm)",
            "type": "number",
            "minimum": 100,
            "maximum": 5000,
            "default": 600
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "orientation": {
            "title": "Sheet orientation",
            "type": "string",
            "enum": [
              "auto",
              "portrait",
              "landscape"
            ],
            "default": "auto"
          },
          "margin": {
            "title": "Printer margin (mm)",
            "description": "Most printers cannot print the outer 3–6 mm.",
            "type": "number",
            "minimum": 0,
            "maximum": 30,
            "default": 8
          },
          "overlap": {
            "title": "Overlap (mm)",
            "type": "number",
            "minimum": 0,
            "maximum": 40,
            "default": 10
          },
          "cropMarks": {
            "title": "Crop marks and alignment crosses",
            "type": "boolean",
            "default": true
          },
          "title": {
            "title": "Title on the cover page",
            "type": "string",
            "maxLength": 120,
            "default": "Poster"
          }
        },
        "required": []
      },
      "PrintshopPosterTilerResult": {
        "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": [
              "sheets",
              "cols",
              "rows",
              "orientation",
              "posterWidthMm",
              "posterHeightMm",
              "ppi",
              "tiles",
              "imageUsed",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "sheets": {
                "type": "integer"
              },
              "cols": {
                "type": "integer"
              },
              "rows": {
                "type": "integer"
              },
              "orientation": {
                "type": "string"
              },
              "posterWidthMm": {
                "type": "number"
              },
              "posterHeightMm": {
                "type": "number"
              },
              "ppi": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "imageUsed": {
                "type": "boolean"
              },
              "tiles": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "xMm",
                    "yMm",
                    "widthMm",
                    "heightMm"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "xMm": {
                      "type": "number"
                    },
                    "yMm": {
                      "type": "number"
                    },
                    "widthMm": {
                      "type": "number"
                    },
                    "heightMm": {
                      "type": "number"
                    }
                  }
                }
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrintshopBookletInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "title": "Booklet pages",
            "type": "string",
            "enum": [
              "ruled",
              "calendar"
            ],
            "default": "ruled"
          },
          "pages": {
            "title": "Notebook pages",
            "type": "integer",
            "minimum": 1,
            "maximum": 200,
            "default": 16
          },
          "kind": {
            "title": "Notebook paper type",
            "type": "string",
            "enum": [
              "grid",
              "dots",
              "isometric",
              "hex",
              "music",
              "lined"
            ],
            "default": "dots"
          },
          "spacing": {
            "title": "Notebook spacing (mm)",
            "type": "number",
            "minimum": 1,
            "maximum": 50,
            "default": 5
          },
          "year": {
            "title": "Calendar year",
            "type": "integer",
            "minimum": 1900,
            "maximum": 2200,
            "default": 2027
          },
          "startMonth": {
            "title": "Calendar first month",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 1
          },
          "lang": {
            "title": "Calendar language",
            "type": "string",
            "enum": [
              "en",
              "de",
              "fr",
              "es",
              "it",
              "pt",
              "nl",
              "pl",
              "tr",
              "ru",
              "uk",
              "ar",
              "hi",
              "zh",
              "ja",
              "ko",
              "id"
            ],
            "default": "en"
          },
          "paper": {
            "title": "Sheet size (folded in half)",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "reading": {
            "title": "Binding",
            "type": "string",
            "enum": [
              "ltr",
              "rtl"
            ],
            "default": "ltr"
          },
          "creep": {
            "title": "Creep compensation (mm per sheet)",
            "description": "About the paper thickness (0.1 mm for 80 g/m²) for thick booklets.",
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "default": 0
          },
          "pageNumbers": {
            "title": "Page numbers",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "PrintshopBookletResult": {
        "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": [
              "bookletPages",
              "sheets",
              "blankPages",
              "order",
              "pages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "bookletPages": {
                "type": "integer"
              },
              "sheets": {
                "type": "integer"
              },
              "blankPages": {
                "type": "integer"
              },
              "order": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "sheet",
                    "front",
                    "back"
                  ],
                  "properties": {
                    "sheet": {
                      "type": "integer"
                    },
                    "front": {
                      "type": "array",
                      "items": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      }
                    },
                    "back": {
                      "type": "array",
                      "items": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      }
                    }
                  }
                }
              },
              "pages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "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)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "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)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "RuledateInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "startDate": {
            "title": "Start date",
            "type": "string",
            "format": "date"
          },
          "operations": {
            "title": "Operations (applied in order)",
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "op": {
                  "title": "Operation",
                  "type": "string",
                  "enum": [
                    "add-business-days",
                    "add-calendar-days",
                    "add-weeks",
                    "add-months",
                    "end-of-month",
                    "next-business-day",
                    "previous-business-day"
                  ]
                },
                "amount": {
                  "title": "Amount",
                  "description": "Negative values go backwards.",
                  "type": "integer",
                  "minimum": -3650,
                  "maximum": 3650,
                  "default": 0
                }
              },
              "required": [
                "op"
              ]
            }
          },
          "country": {
            "title": "Holiday calendar",
            "type": "string",
            "enum": [
              "none",
              "DE",
              "AT",
              "CH",
              "US",
              "GB",
              "FR",
              "NL",
              "BE",
              "ES",
              "IT",
              "PL",
              "SE",
              "DK",
              "IE",
              "CA",
              "AU"
            ],
            "default": "DE"
          },
          "subdivision": {
            "title": "Subdivision (optional)",
            "description": "ISO 3166-2 code, e.g. DE-BY (Bavaria), CH-ZH, US-CA. Without it only nationwide holidays count.",
            "type": "string",
            "maxLength": 10
          },
          "weekendDays": {
            "title": "Weekend days",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sun",
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
                "sat"
              ]
            },
            "default": [
              "sat",
              "sun"
            ]
          },
          "closures": {
            "title": "Extra closure dates",
            "description": "One YYYY-MM-DD per line (company holidays, bridge days).",
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 366
          },
          "monthEndRule": {
            "title": "Month arithmetic",
            "type": "string",
            "enum": [
              "clamp",
              "overflow"
            ],
            "default": "clamp"
          },
          "finalRule": {
            "title": "Final adjustment",
            "type": "string",
            "enum": [
              "none",
              "bgb193"
            ],
            "default": "none"
          }
        },
        "required": [
          "startDate",
          "operations"
        ]
      },
      "RuledateResult": {
        "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": [
              "startDate",
              "finalDate",
              "finalWeekday",
              "country",
              "subdivision",
              "weekendDays",
              "steps",
              "holidaysApplied",
              "dataRange",
              "outsideDataRange"
            ],
            "properties": {
              "startDate": {
                "type": "string",
                "format": "date"
              },
              "finalDate": {
                "type": "string",
                "format": "date"
              },
              "finalWeekday": {
                "type": "string"
              },
              "country": {
                "type": "string"
              },
              "subdivision": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "weekendDays": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "steps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "step",
                    "operation",
                    "amount",
                    "from",
                    "to",
                    "skipped",
                    "note"
                  ],
                  "properties": {
                    "step": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "operation": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "integer"
                    },
                    "from": {
                      "type": "string",
                      "format": "date"
                    },
                    "to": {
                      "type": "string",
                      "format": "date"
                    },
                    "note": {
                      "type": "string"
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "date",
                          "weekday",
                          "reasons"
                        ],
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "weekday": {
                            "type": "string"
                          },
                          "reasons": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "holidaysApplied": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "date",
                    "name",
                    "localName",
                    "scope"
                  ],
                  "properties": {
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "name": {
                      "type": "string"
                    },
                    "localName": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              },
              "dataRange": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "firstYear",
                  "lastYear"
                ],
                "properties": {
                  "firstYear": {
                    "type": "integer"
                  },
                  "lastYear": {
                    "type": "integer"
                  }
                }
              },
              "outsideDataRange": {
                "type": "boolean"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "LuminaPrintPlannerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "width": {
            "title": "Photo width (px)",
            "type": "integer",
            "minimum": 1,
            "maximum": 100000,
            "default": 6000
          },
          "height": {
            "title": "Photo height (px)",
            "type": "integer",
            "minimum": 1,
            "maximum": 100000,
            "default": 4000
          },
          "ppi": {
            "title": "Print resolution (PPI)",
            "type": "integer",
            "minimum": 1,
            "maximum": 2400,
            "default": 300
          }
        },
        "required": []
      },
      "LuminaPrintPlannerResult": {
        "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": [
              "widthInches",
              "heightInches",
              "widthCm",
              "heightCm",
              "ppi",
              "megapixels"
            ],
            "properties": {
              "widthInches": {
                "type": "number"
              },
              "heightInches": {
                "type": "number"
              },
              "widthCm": {
                "type": "number"
              },
              "heightCm": {
                "type": "number"
              },
              "ppi": {
                "type": "number"
              },
              "megapixels": {
                "type": "number"
              }
            }
          },
          "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"
              }
            }
          }
        }
      },
      "LuminaImageSplitterInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "images": {
            "title": "Single photo (PNG, JPEG, WebP or GIF)",
            "description": "Exactly one PNG, JPEG, WebP or GIF image (first frame), up to 16 MP decoded; a ZIP containing exactly one photo also works. To split several photos, run the tool once per photo. Upload as {filename, contentType?, contentBase64}. Max 78125 KiB. Accepts .zip,.png,.jpg,.jpeg,.webp,.gif.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "rows": {
            "title": "Rows",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 3
          },
          "columns": {
            "title": "Columns",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 3
          }
        },
        "required": [
          "images"
        ]
      },
      "LuminaImageSplitterResult": {
        "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": [
              "width",
              "height",
              "tiles",
              "artifact"
            ],
            "properties": {
              "width": {
                "type": "integer"
              },
              "height": {
                "type": "integer"
              },
              "tiles": {
                "type": "integer"
              },
              "artifact": {
                "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)."
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      },
      "PanelcraftBookPlanInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "title": "Book title",
            "type": "string",
            "maxLength": 120,
            "default": "A small adventure"
          },
          "author": {
            "title": "Author or credit",
            "type": "string",
            "maxLength": 120,
            "default": ""
          },
          "pages": {
            "title": "Book pages",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 8
          },
          "rows": {
            "title": "Panel rows",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 2
          },
          "columns": {
            "title": "Panel columns",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 2
          },
          "reading": {
            "title": "Reading and binding direction",
            "type": "string",
            "enum": [
              "ltr",
              "rtl"
            ],
            "default": "ltr"
          },
          "sheetColumns": {
            "title": "Contact-sheet columns",
            "type": "integer",
            "minimum": 1,
            "maximum": 4,
            "default": 3
          }
        },
        "required": []
      },
      "PanelcraftBookPlanResult": {
        "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": [
              "project",
              "report",
              "imposition",
              "contactSheet",
              "projectFile",
              "letteringCsv",
              "openInApp"
            ],
            "properties": {
              "project": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "format",
                  "version",
                  "name",
                  "author",
                  "reading",
                  "pages"
                ],
                "properties": {
                  "format": {
                    "const": "panelcraft-book"
                  },
                  "version": {
                    "const": 1
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "author": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "reading": {
                    "enum": [
                      "ltr",
                      "rtl"
                    ]
                  },
                  "pages": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 12,
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "notes",
                        "comic"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[-a-zA-Z0-9_]{1,64}$"
                        },
                        "notes": {
                          "type": "string",
                          "maxLength": 2000
                        },
                        "comic": {
                          "type": "object",
                          "additionalProperties": false,
                          "required": [
                            "format",
                            "version",
                            "name",
                            "width",
                            "height",
                            "dpi",
                            "margin",
                            "gutter",
                            "border",
                            "paper",
                            "reading",
                            "panels",
                            "balloons",
                            "artwork"
                          ],
                          "properties": {
                            "format": {
                              "const": "flipline-comic"
                            },
                            "version": {
                              "const": 1
                            },
                            "name": {
                              "type": "string",
                              "maxLength": 120
                            },
                            "width": {
                              "type": "integer",
                              "minimum": 400,
                              "maximum": 2400
                            },
                            "height": {
                              "type": "integer",
                              "minimum": 400,
                              "maximum": 4000
                            },
                            "dpi": {
                              "type": "integer",
                              "minimum": 72,
                              "maximum": 600
                            },
                            "margin": {
                              "type": "number"
                            },
                            "gutter": {
                              "type": "number"
                            },
                            "border": {
                              "type": "number"
                            },
                            "paper": {
                              "type": "string"
                            },
                            "reading": {
                              "enum": [
                                "ltr",
                                "rtl"
                              ]
                            },
                            "panels": {
                              "type": "array",
                              "minItems": 1,
                              "maxItems": 12,
                              "items": {
                                "type": "object",
                                "additionalProperties": false,
                                "required": [
                                  "id",
                                  "name",
                                  "x",
                                  "y",
                                  "width",
                                  "height",
                                  "paper",
                                  "fit",
                                  "zoom",
                                  "panX",
                                  "panY",
                                  "sourceWidth",
                                  "sourceHeight",
                                  "tone"
                                ],
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "maxLength": 64
                                  },
                                  "name": {
                                    "type": "string",
                                    "maxLength": 80
                                  },
                                  "x": {
                                    "type": "number"
                                  },
                                  "y": {
                                    "type": "number"
                                  },
                                  "width": {
                                    "type": "number"
                                  },
                                  "height": {
                                    "type": "number"
                                  },
                                  "paper": {
                                    "type": "string"
                                  },
                                  "fit": {
                                    "enum": [
                                      "contain",
                                      "cover"
                                    ]
                                  },
                                  "zoom": {
                                    "type": "number"
                                  },
                                  "panX": {
                                    "type": "number"
                                  },
                                  "panY": {
                                    "type": "number"
                                  },
                                  "sourceWidth": {
                                    "type": "integer"
                                  },
                                  "sourceHeight": {
                                    "type": "integer"
                                  },
                                  "tone": {
                                    "type": "object",
                                    "additionalProperties": false,
                                    "required": [
                                      "kind",
                                      "pitch",
                                      "coverage",
                                      "angle",
                                      "ink",
                                      "over"
                                    ],
                                    "properties": {
                                      "kind": {
                                        "enum": [
                                          "none",
                                          "dots",
                                          "lines",
                                          "crosshatch"
                                        ]
                                      },
                                      "pitch": {
                                        "type": "number",
                                        "minimum": 4,
                                        "maximum": 80
                                      },
                                      "coverage": {
                                        "type": "number",
                                        "minimum": 0.05,
                                        "maximum": 0.75
                                      },
                                      "angle": {
                                        "type": "number",
                                        "minimum": -90,
                                        "maximum": 90
                                      },
                                      "ink": {
                                        "type": "string",
                                        "pattern": "^#[a-fA-F0-9]{6}$"
                                      },
                                      "over": {
                                        "type": "boolean"
                                      }
                                    }
                                  }
                                }
                              }
                            },
                            "balloons": {
                              "type": "array",
                              "maxItems": 36,
                              "items": {
                                "type": "object",
                                "additionalProperties": false,
                                "required": [
                                  "id",
                                  "panel",
                                  "kind",
                                  "x",
                                  "y",
                                  "width",
                                  "height",
                                  "tailX",
                                  "tailY",
                                  "text",
                                  "fontSize",
                                  "ink",
                                  "paper"
                                ],
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "maxLength": 64
                                  },
                                  "panel": {
                                    "type": "string",
                                    "maxLength": 64
                                  },
                                  "kind": {
                                    "enum": [
                                      "speech",
                                      "thought",
                                      "caption"
                                    ]
                                  },
                                  "x": {
                                    "type": "number"
                                  },
                                  "y": {
                                    "type": "number"
                                  },
                                  "width": {
                                    "type": "number"
                                  },
                                  "height": {
                                    "type": "number"
                                  },
                                  "tailX": {
                                    "type": "number"
                                  },
                                  "tailY": {
                                    "type": "number"
                                  },
                                  "text": {
                                    "type": "string",
                                    "maxLength": 600
                                  },
                                  "fontSize": {
                                    "type": "number"
                                  },
                                  "ink": {
                                    "type": "string"
                                  },
                                  "paper": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "artwork": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "format",
                                "version",
                                "name",
                                "width",
                                "height",
                                "fps",
                                "paper",
                                "boards"
                              ],
                              "properties": {
                                "format": {
                                  "const": "flipline-story"
                                },
                                "version": {
                                  "const": 1
                                },
                                "name": {
                                  "type": "string",
                                  "maxLength": 120
                                },
                                "width": {
                                  "type": "integer",
                                  "minimum": 32,
                                  "maximum": 1600
                                },
                                "height": {
                                  "type": "integer",
                                  "minimum": 32,
                                  "maximum": 1600
                                },
                                "fps": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 30
                                },
                                "paper": {
                                  "type": "string",
                                  "pattern": "^#[a-fA-F0-9]{6}$"
                                },
                                "boards": {
                                  "type": "array",
                                  "minItems": 1,
                                  "maxItems": 48,
                                  "items": {
                                    "type": "object",
                                    "additionalProperties": false,
                                    "required": [
                                      "id",
                                      "title",
                                      "scene",
                                      "shot",
                                      "camera",
                                      "frames",
                                      "action",
                                      "dialogue",
                                      "notes",
                                      "locked",
                                      "marks",
                                      "reference"
                                    ],
                                    "properties": {
                                      "id": {
                                        "type": "string",
                                        "pattern": "^[-a-zA-Z0-9_]{1,80}$"
                                      },
                                      "title": {
                                        "type": "string",
                                        "maxLength": 80
                                      },
                                      "scene": {
                                        "type": "string",
                                        "maxLength": 80
                                      },
                                      "shot": {
                                        "enum": [
                                          "wide",
                                          "medium",
                                          "close",
                                          "detail",
                                          "over-shoulder"
                                        ]
                                      },
                                      "camera": {
                                        "enum": [
                                          "static",
                                          "pan-left",
                                          "pan-right",
                                          "tilt-up",
                                          "tilt-down",
                                          "push-in",
                                          "pull-out",
                                          "handheld"
                                        ]
                                      },
                                      "frames": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 3600
                                      },
                                      "action": {
                                        "type": "string",
                                        "maxLength": 1200
                                      },
                                      "dialogue": {
                                        "type": "string",
                                        "maxLength": 1200
                                      },
                                      "notes": {
                                        "type": "string",
                                        "maxLength": 1200
                                      },
                                      "locked": {
                                        "type": "boolean"
                                      },
                                      "marks": {
                                        "type": "array",
                                        "maxItems": 500,
                                        "items": {
                                          "type": "object",
                                          "additionalProperties": false,
                                          "required": [
                                            "id",
                                            "kind",
                                            "points",
                                            "color",
                                            "size",
                                            "fill"
                                          ],
                                          "properties": {
                                            "brush": {
                                              "type": "object",
                                              "additionalProperties": false,
                                              "required": [
                                                "kind",
                                                "opacity",
                                                "flow",
                                                "spacing",
                                                "texture",
                                                "pressure",
                                                "seed"
                                              ],
                                              "properties": {
                                                "kind": {
                                                  "enum": [
                                                    "ink",
                                                    "pencil",
                                                    "marker",
                                                    "wash",
                                                    "airbrush"
                                                  ]
                                                },
                                                "opacity": {
                                                  "type": "number",
                                                  "minimum": 0,
                                                  "maximum": 1
                                                },
                                                "flow": {
                                                  "type": "number",
                                                  "minimum": 0,
                                                  "maximum": 1
                                                },
                                                "spacing": {
                                                  "type": "number",
                                                  "minimum": 0.08,
                                                  "maximum": 1
                                                },
                                                "texture": {
                                                  "type": "number",
                                                  "minimum": 0,
                                                  "maximum": 1
                                                },
                                                "pressure": {
                                                  "type": "boolean"
                                                },
                                                "seed": {
                                                  "type": "integer",
                                                  "minimum": 0,
                                                  "maximum": 4294967295
                                                }
                                              }
                                            },
                                            "pressures": {
                                              "type": "array",
                                              "minItems": 1,
                                              "maxItems": 4096,
                                              "items": {
                                                "type": "number",
                                                "minimum": 0,
                                                "maximum": 1
                                              }
                                            },
                                            "id": {
                                              "type": "string",
                                              "minLength": 1,
                                              "maxLength": 80
                                            },
                                            "kind": {
                                              "enum": [
                                                "pen",
                                                "eraser",
                                                "line",
                                                "rect",
                                                "ellipse",
                                                "image"
                                              ]
                                            },
                                            "points": {
                                              "type": "array",
                                              "minItems": 1,
                                              "maxItems": 4096,
                                              "items": {
                                                "type": "array",
                                                "minItems": 2,
                                                "maxItems": 2,
                                                "items": {
                                                  "type": "number",
                                                  "minimum": 0,
                                                  "maximum": 1
                                                }
                                              }
                                            },
                                            "color": {
                                              "type": "string",
                                              "pattern": "^#[a-fA-F0-9]{6}$"
                                            },
                                            "size": {
                                              "type": "number",
                                              "minimum": 1,
                                              "maximum": 100
                                            },
                                            "fill": {
                                              "type": "boolean"
                                            },
                                            "source": {
                                              "type": "string",
                                              "pattern": "^data:image/(png|jpeg|webp);base64,[A-Za-z0-9+/=]+$"
                                            },
                                            "angle": {
                                              "type": "number",
                                              "minimum": -360,
                                              "maximum": 360,
                                              "description": "Clockwise rotation in degrees around the center of the mark bounds (normalized to -180…180)."
                                            },
                                            "flipX": {
                                              "type": "boolean",
                                              "description": "Mirror horizontally around the mark center."
                                            },
                                            "flipY": {
                                              "type": "boolean",
                                              "description": "Mirror vertically around the mark center."
                                            }
                                          }
                                        }
                                      },
                                      "reference": {
                                        "type": [
                                          "object",
                                          "null"
                                        ],
                                        "additionalProperties": false,
                                        "required": [
                                          "source",
                                          "opacity",
                                          "visible"
                                        ],
                                        "properties": {
                                          "source": {
                                            "type": "string",
                                            "pattern": "^data:image/(png|jpeg|webp);base64,[A-Za-z0-9+/=]+$"
                                          },
                                          "opacity": {
                                            "type": "number",
                                            "minimum": 0,
                                            "maximum": 1
                                          },
                                          "visible": {
                                            "type": "boolean"
                                          }
                                        }
                                      }
                                    }
                                  }
                                }
                              },
                              "description": "Story Desk. Frame-based board durations, half-open timeline intervals and non-drop-frame timecodes. Up to 600 seconds total and 120 seconds per board at the chosen FPS. Canvas up to 2 MP, 50000 points, 2000 marks and 6 million source-image characters across all boards. Ink erasers affect preceding ink only; the independent reference is preserved. Camera moves are planning labels, not animated camera paths."
                            }
                          },
                          "description": "Comic Desk page. At most 6 MP, 12 panels and 36 balloons. Panel/artwork board IDs align by index. Shared Story Desk mark budgets apply; image marks are disallowed. PNG references match declared dimensions, at most 2 MP each and 8 MP total. All embedded references together fit 6 million characters. Text overflow is reported, never silently exported by the workspace."
                        }
                      }
                    }
                  }
                },
                "description": "Panelcraft 1.0 comic book, 1–12 ordered pages. Each comic follows the Flipline Comic Desk schema. Aggregate normalized page JSON must fit 24 million characters. Page IDs are unique. Per-page art and image limits apply. Reading sets booklet binding; each page retains its own panel reading direction."
              },
              "report": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "pages",
                  "panels",
                  "balloons",
                  "overflow",
                  "embeddedCharacters"
                ],
                "properties": {
                  "pages": {
                    "type": "integer"
                  },
                  "panels": {
                    "type": "integer"
                  },
                  "balloons": {
                    "type": "integer"
                  },
                  "overflow": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "id"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "id": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "embeddedCharacters": {
                    "type": "integer"
                  }
                }
              },
              "imposition": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "pages",
                  "paddedPages",
                  "blankPages",
                  "sheets"
                ],
                "properties": {
                  "pages": {
                    "type": "integer"
                  },
                  "paddedPages": {
                    "type": "integer"
                  },
                  "blankPages": {
                    "type": "integer"
                  },
                  "sheets": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "sheet",
                        "front",
                        "back"
                      ],
                      "properties": {
                        "sheet": {
                          "type": "integer"
                        },
                        "front": {
                          "type": "array",
                          "minItems": 2,
                          "maxItems": 2,
                          "items": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "back": {
                          "type": "array",
                          "minItems": 2,
                          "maxItems": 2,
                          "items": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              },
              "contactSheet": {
                "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)."
                  }
                }
              },
              "projectFile": {
                "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)."
                  }
                }
              },
              "letteringCsv": {
                "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)."
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}