{
  "openapi": "3.1.1",
  "info": {
    "title": "Deckwright 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://deckwright.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": [
                "deckwright-markdown-to-deck",
                "deckwright-pptx-export",
                "deckwright-deck-a11y-check",
                "diagram-flowchart-maker",
                "csv-excel-chart-studio"
              ]
            }
          }
        ],
        "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/deckwright-markdown-to-deck/calculate": {
      "post": {
        "operationId": "calculateDeckwrightMarkdownToDeck",
        "summary": "Turn Markdown into a clean slide deck — PDF with embedded fonts and a single-file HTML presentation.",
        "description": "Write slides in Markdown (headings, lists, tables, code, quotes, images, CSV charts and flowchart/sequence/mind-map diagrams, speaker notes) and get a 16:9 or 4:3 deck in one of six themes: a vector PDF with embedded, searchable fonts (Latin, Cyrillic, Greek, Arabic, Devanagari, Chinese, Japanese, Korean), a self-contained HTML presentation and a PNG of the first slide. Right-to-left decks are mirrored.\n\nMethodology:\n- Slides are split at lines of three dashes (or, without any, at # and ## headings); the first heading of a slide is its title. A slide with only a level-1 heading and a short paragraph becomes a title or section slide.\n- Text is shaped with the embedded Noto fonts (Arabic joining, Devanagari reordering, bidirectional text), wrapped by words (Chinese, Japanese and Korean by characters) and shrunk in steps down to 14 pt when it does not fit; slides that still overflow are reported.\n- Charts are drawn by the same chart engine as the RavingDesk data desk (Okabe–Ito colours, dash patterns, generated description); diagrams by the same Mermaid-subset layout as the diagram tool. Both become vector shapes and real text in the PDF.\n- The HTML file is self-contained: semantic slides (headings, lists, tables, inline SVG with data tables, images as data URLs), speaker notes, a presenter mode with keyboard control, and its own Content-Security-Policy that allows only its single style and script by SHA-256 hash.\n\nOne font weight (Noto Sans Regular): bold and links are shown in the accent colour in the PDF; HTML and PowerPoint keep real bold. Web images are not downloaded; embed them as data URLs or add them in the app.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "deckwright_markdown_to_deck",
        "x-owner-app": "deckwright",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeckwrightMarkdownToDeckInput"
              },
              "examples": {
                "example1": {
                  "summary": "Quarterly review with a chart, a flowchart and a table",
                  "value": {
                    "markdown": "---\ntitle: Quarterly review\nauthor: Example Co\nlang: en\ntheme: paper\nfooter: Example Co · internal\n---\n\n# Quarterly review\n\nWhere we stand after the fourth quarter and what comes next\n\n---\n\n## Agenda\n\n- Results in numbers\n- What **worked** and what did not\n  - Pricing test\n  - New onboarding\n- Plan for the next quarter\n\nNotes:\nThank the team first. Keep this slide under one minute.\n\n---\n\n## Revenue by month\n\n```chart\ntype: bar\ntitle: Revenue in k€ (example data)\nx: Month\ny: Revenue\nalt: Revenue rose every month, from 120 k€ in October to 168 k€ in December.\n\nMonth,Revenue\nOct,120\nNov,141\nDec,168\n```\n\n- December was the best month so far\n- The bundle offer drove a third of the growth\n\nNotes:\nPoint at the December bar. The bundle started on 1 December.\n\n---\n\n## How a support request flows\n\n```diagram\n%% alt: A request is answered with a help article when the issue is known; otherwise a ticket is opened, fixed and answered.\nflowchart LR\n  A[Customer request] --\u003e B{Known issue?}\n  B -- yes --\u003e C[Send help article]\n  B -- no --\u003e D[Open ticket]\n  D --\u003e E[Fix and reply]\n```\n\n---\n\n## Key figures\n\n| Figure | Q3 | Q4 |\n|---|--:|--:|\n| Customers | 1,204 | 1,388 |\n| Churn | 3.1 % | 2.4 % |\n| Replies within a day | 81 % | 92 % |\n\nThe figures are example data.\n\n---\n\n## Next quarter\n\n1. Roll out the new onboarding to everyone\n2. Test yearly prices\n3. Hire a second support person\n"
                  }
                },
                "example2": {
                  "summary": "Arabic deck, right to left",
                  "value": {
                    "markdown": "---\ntitle: خطة المشروع\nlang: ar\ndir: rtl\ntheme: slate\nfooter: عرض تجريبي\n---\n\n# خطة المشروع\n\nعرض تجريبي من اليمين إلى اليسار\n\n---\n\n## الأهداف\n\n- تقليل وقت الانتظار\n- تحسين تجربة المستخدم\n- إطلاق النسخة الأولى في الربيع\n\nNotes:\nتحدث ببطء وأشر إلى كل هدف.\n\n---\n\n## التقدم\n\n```chart\ntype: bar\ntitle: المهام المنجزة (بيانات مثال)\nx: الشهر\ny: المهام\nalt: زاد عدد المهام المنجزة كل شهر: 12 في يناير و18 في فبراير و25 في مارس.\n\nالشهر,المهام\nيناير,12\nفبراير,18\nمارس,25\n```\n\n---\n\n## الخطوات التالية\n\n1. مراجعة التصميم\n2. اختبار مع المستخدمين\n3. النشر\n"
                  }
                },
                "example3": {
                  "summary": "Outline without separators, 4:3, high-contrast theme",
                  "value": {
                    "markdown": "# Team kick-off\n\nGoals, roles and the first four weeks\n\n## Why we are here\n\n- One shared goal for the quarter\n- Clear owners for every part\n- A rhythm for meetings and updates\n\n## Roles\n\n| Role | Person | Decides on |\n|---|---|---|\n| Lead | Alex | Scope and priorities |\n| Design | Kim | Look and flow |\n| Engineering | Sam | Build and release |\n\n## The first four weeks\n\n1. Week 1: interviews with five users\n2. Week 2: first prototype\n3. Week 3: test and change\n4. Week 4: plan the build\n\n## How we work\n\n- Short stand-up on Monday and Thursday\n- Decisions written down in one place\n- Ask early, ask often\n\nNotes:\nThis deck has no separator lines: every # or ## heading starts a slide.\n",
                    "theme": "contrast",
                    "aspect": "4:3"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeckwrightMarkdownToDeckResult"
                }
              }
            }
          },
          "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/deckwright-pptx-export/calculate": {
      "post": {
        "operationId": "calculateDeckwrightPptxExport",
        "summary": "Editable PowerPoint from Markdown: real titles, bullets, tables, speaker notes and alt text.",
        "description": "Converts a Markdown deck into a .pptx file written by hand in Office Open XML: real title placeholders, editable text boxes with bullet levels, bold, italic and links, native tables with a header row, pictures with alternative text, charts and diagrams as pictures with their description, speaker notes and a reading order that follows the Markdown. Opens in PowerPoint, Keynote, LibreOffice Impress and Google Slides.\n\nMethodology:\n- The package follows ECMA-376 PresentationML: presentation, one slide master with a title and a title-and-content layout, a theme with the deck colours and Noto Sans, one slide part per slide, notes pages for slides with speaker notes, and relationships for pictures and hyperlinks.\n- Shapes are placed on the same boxes as the PDF layout (millimetres × 36,000 EMU); the slide title uses the title placeholder, so the outline view, the accessibility checker and screen readers see it. Decorative bars are marked decorative.\n- Text keeps its Markdown structure: one paragraph per list item with its level and bullet or number, runs with bold, italic, code font and external hyperlinks, right-to-left paragraphs for RTL decks; tables are native with the first row marked as header row.\n- Charts and diagrams are rendered to PNG at 200 dpi from the same vector shapes as the PDF and carry their alternative text. The ZIP is written deterministically (fixed timestamps), so equal input gives an identical file.\n\nCharts and diagrams are pictures in the PPTX, not editable PowerPoint charts. Fonts are not embedded in the PPTX: viewers without Noto Sans use a similar sans-serif font, so line breaks can differ slightly from the PDF.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "deckwright_pptx_export",
        "x-owner-app": "deckwright",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeckwrightPptxExportInput"
              },
              "examples": {
                "example1": {
                  "summary": "Quarterly review as PowerPoint",
                  "value": {
                    "markdown": "---\ntitle: Quarterly review\nauthor: Example Co\nlang: en\ntheme: paper\nfooter: Example Co · internal\n---\n\n# Quarterly review\n\nWhere we stand after the fourth quarter and what comes next\n\n---\n\n## Agenda\n\n- Results in numbers\n- What **worked** and what did not\n  - Pricing test\n  - New onboarding\n- Plan for the next quarter\n\nNotes:\nThank the team first. Keep this slide under one minute.\n\n---\n\n## Revenue by month\n\n```chart\ntype: bar\ntitle: Revenue in k€ (example data)\nx: Month\ny: Revenue\nalt: Revenue rose every month, from 120 k€ in October to 168 k€ in December.\n\nMonth,Revenue\nOct,120\nNov,141\nDec,168\n```\n\n- December was the best month so far\n- The bundle offer drove a third of the growth\n\nNotes:\nPoint at the December bar. The bundle started on 1 December.\n\n---\n\n## How a support request flows\n\n```diagram\n%% alt: A request is answered with a help article when the issue is known; otherwise a ticket is opened, fixed and answered.\nflowchart LR\n  A[Customer request] --\u003e B{Known issue?}\n  B -- yes --\u003e C[Send help article]\n  B -- no --\u003e D[Open ticket]\n  D --\u003e E[Fix and reply]\n```\n\n---\n\n## Key figures\n\n| Figure | Q3 | Q4 |\n|---|--:|--:|\n| Customers | 1,204 | 1,388 |\n| Churn | 3.1 % | 2.4 % |\n| Replies within a day | 81 % | 92 % |\n\nThe figures are example data.\n\n---\n\n## Next quarter\n\n1. Roll out the new onboarding to everyone\n2. Test yearly prices\n3. Hire a second support person\n"
                  }
                },
                "example2": {
                  "summary": "Arabic deck with right-to-left paragraphs",
                  "value": {
                    "markdown": "---\ntitle: خطة المشروع\nlang: ar\ndir: rtl\ntheme: slate\nfooter: عرض تجريبي\n---\n\n# خطة المشروع\n\nعرض تجريبي من اليمين إلى اليسار\n\n---\n\n## الأهداف\n\n- تقليل وقت الانتظار\n- تحسين تجربة المستخدم\n- إطلاق النسخة الأولى في الربيع\n\nNotes:\nتحدث ببطء وأشر إلى كل هدف.\n\n---\n\n## التقدم\n\n```chart\ntype: bar\ntitle: المهام المنجزة (بيانات مثال)\nx: الشهر\ny: المهام\nalt: زاد عدد المهام المنجزة كل شهر: 12 في يناير و18 في فبراير و25 في مارس.\n\nالشهر,المهام\nيناير,12\nفبراير,18\nمارس,25\n```\n\n---\n\n## الخطوات التالية\n\n1. مراجعة التصميم\n2. اختبار مع المستخدمين\n3. النشر\n"
                  }
                },
                "example3": {
                  "summary": "Outline deck in the Slate theme, 4:3",
                  "value": {
                    "markdown": "# Team kick-off\n\nGoals, roles and the first four weeks\n\n## Why we are here\n\n- One shared goal for the quarter\n- Clear owners for every part\n- A rhythm for meetings and updates\n\n## Roles\n\n| Role | Person | Decides on |\n|---|---|---|\n| Lead | Alex | Scope and priorities |\n| Design | Kim | Look and flow |\n| Engineering | Sam | Build and release |\n\n## The first four weeks\n\n1. Week 1: interviews with five users\n2. Week 2: first prototype\n3. Week 3: test and change\n4. Week 4: plan the build\n\n## How we work\n\n- Short stand-up on Monday and Thursday\n- Decisions written down in one place\n- Ask early, ask often\n\nNotes:\nThis deck has no separator lines: every # or ## heading starts a slide.\n",
                    "theme": "slate",
                    "aspect": "4:3"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeckwrightPptxExportResult"
                }
              }
            }
          },
          "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/deckwright-deck-a11y-check/calculate": {
      "post": {
        "operationId": "calculateDeckwrightDeckA11yCheck",
        "summary": "Check a Markdown slide deck: contrast, slide titles, alt text, reading order and text size.",
        "description": "Lays out a Markdown deck exactly like the Deckwright exports and checks it: WCAG 2.2 contrast of every colour pair of the theme, a unique title on every slide, alternative text for images, charts and diagrams, the reading order of each slide, link texts, the deck language, text that had to shrink or does not fit, small chart and diagram labels, empty and very dense slides. Every finding names the slide and the WCAG success criterion.\n\nMethodology:\n- Contrast: WCAG 2.2 relative luminance of the sRGB colours and (L1 + 0.05) / (L2 + 0.05) for every pair the theme draws; body text, links, code and subtitles need 4.5:1, titles (30 pt and larger) and graphical marks 3:1 (SC 1.4.3, 1.4.11).\n- Structure: every slide needs a title and titles should be unique (SC 2.4.6; screen readers list PowerPoint and PDF slides by title); images need alternative text that is not a file name (SC 1.1.1); charts and diagrams without their own alt text are reported as using their generated description.\n- Reading order (SC 1.3.2): the exports keep the Markdown order on every slide (title, then text and visuals as written); the report lists it per slide. Link texts such as “here” or “click here” are flagged (SC 2.4.4), a missing deck language too (SC 3.1.1).\n- Layout checks run on the real layout: text that had to shrink, text that does not fit even at 14 pt, chart or diagram labels below 10 pt (warning) or 12 pt (note), slides without content and slides with more than 90 words.\n\nAn automatic check finds structural problems; it cannot judge whether alternative text is accurate or whether the slides make sense. Ask a screen reader user to try important decks.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "deckwright_deck_a11y_check",
        "x-owner-app": "deckwright",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeckwrightDeckA11yCheckInput"
              },
              "examples": {
                "example1": {
                  "summary": "A lesson deck",
                  "value": {
                    "markdown": "---\ntitle: How plants make food\nlang: en\ntheme: harbor\nfooter: Biology · lesson 4\n---\n\n# How plants make food\n\nPhotosynthesis in five slides\n\n---\n\n## The idea in one sentence\n\n\u003e Plants use the energy of light to turn carbon dioxide and water into sugar and oxygen.\n\n---\n\n## What goes in, what comes out\n\n| In | Out |\n|---|---|\n| Carbon dioxide from the air | Sugar (glucose) |\n| Water from the roots | Oxygen |\n| Light energy | |\n\n6 CO₂ + 6 H₂O + light gives C₆H₁₂O₆ + 6 O₂\n\n---\n\n## Where it happens\n\n```mermaid\n%% alt: Photosynthesis happens in the leaf (chloroplasts, stomata) in two stages: light reactions split water and release oxygen; the Calvin cycle fixes carbon dioxide into sugar.\nmindmap\n  Photosynthesis\n    Leaf\n      Chloroplasts\n      Stomata\n    Light reactions\n      Split water\n      Release oxygen\n    Calvin cycle\n      Fix CO₂\n      Build sugar\n```\n\n---\n\n## Try it yourself\n\n- Put a water plant under a lamp\n- Count the oxygen bubbles per minute\n- Move the lamp closer and count again\n\nNotes:\nAsk the class to predict the result before moving the lamp.\n\n---\n\n## Bubbles and light\n\n```chart\ntype: line\ntitle: Bubbles per minute (example class data)\nx: Distance (cm)\ny: Bubbles\nalt: The closer the lamp, the more bubbles: from 4 per minute at 50 cm to 31 per minute at 10 cm.\n\nDistance (cm),Bubbles\n10,31\n20,19\n30,11\n40,7\n50,4\n```\n"
                  }
                },
                "example2": {
                  "summary": "Deck with typical problems",
                  "value": {
                    "markdown": "# Results\n\n---\n\n![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==)\n\nRead more [here](https://example.com/report).\n\n---\n\n## Results\n\n- Same title as before\n\n---\n\nA slide without a title."
                  }
                },
                "example3": {
                  "summary": "Quarterly review in the Midnight theme",
                  "value": {
                    "markdown": "---\ntitle: Quarterly review\nauthor: Example Co\nlang: en\ntheme: paper\nfooter: Example Co · internal\n---\n\n# Quarterly review\n\nWhere we stand after the fourth quarter and what comes next\n\n---\n\n## Agenda\n\n- Results in numbers\n- What **worked** and what did not\n  - Pricing test\n  - New onboarding\n- Plan for the next quarter\n\nNotes:\nThank the team first. Keep this slide under one minute.\n\n---\n\n## Revenue by month\n\n```chart\ntype: bar\ntitle: Revenue in k€ (example data)\nx: Month\ny: Revenue\nalt: Revenue rose every month, from 120 k€ in October to 168 k€ in December.\n\nMonth,Revenue\nOct,120\nNov,141\nDec,168\n```\n\n- December was the best month so far\n- The bundle offer drove a third of the growth\n\nNotes:\nPoint at the December bar. The bundle started on 1 December.\n\n---\n\n## How a support request flows\n\n```diagram\n%% alt: A request is answered with a help article when the issue is known; otherwise a ticket is opened, fixed and answered.\nflowchart LR\n  A[Customer request] --\u003e B{Known issue?}\n  B -- yes --\u003e C[Send help article]\n  B -- no --\u003e D[Open ticket]\n  D --\u003e E[Fix and reply]\n```\n\n---\n\n## Key figures\n\n| Figure | Q3 | Q4 |\n|---|--:|--:|\n| Customers | 1,204 | 1,388 |\n| Churn | 3.1 % | 2.4 % |\n| Replies within a day | 81 % | 92 % |\n\nThe figures are example data.\n\n---\n\n## Next quarter\n\n1. Roll out the new onboarding to everyone\n2. Test yearly prices\n3. Hire a second support person\n",
                    "theme": "midnight",
                    "lang": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeckwrightDeckA11yCheckResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/diagram-flowchart-maker/calculate": {
      "post": {
        "operationId": "calculateDiagramFlowchartMaker",
        "summary": "Write flowcharts, sequence diagrams and mind maps as text and get a laid-out SVG/PNG diagram.",
        "description": "Type a diagram in a Mermaid-like text syntax – flowcharts (top-down or left-right, node shapes, labelled arrows), sequence diagrams (participants, messages, notes, loop/alt blocks) or indented mind maps – and get an automatically laid-out, accessible SVG with SVG/PNG downloads. Syntax errors are reported with line numbers.\n\nMethodology:\n- The text is parsed line by line; every error is reported with its line (and column for flowcharts). Supported: flowchart/graph TD|TB|BT|LR|RL with shapes [rect] (round) ([stadium]) [[subroutine]] [(database)] ((circle)) {diamond} {{hexagon}} [/parallelogram/] [/trapezoid\\] \u003eflag], arrows --\u003e --- -.-\u003e ==\u003e \u003c--\u003e, labels --\u003e|text| or -- text --\u003e, chains A --\u003e B --\u003e C and groups A \u0026 B --\u003e C; sequenceDiagram with participant/actor (… as Alias), -\u003e\u003e --\u003e\u003e -\u003e --\u003e -x --x -) --), Note left of/right of/over, loop/alt/else/opt/par/critical/break … end, autonumber; mindmap with indentation and the usual node shapes.\n- Flowcharts are laid out with a layered (Sugiyama-style) algorithm: cycles are broken by reversing DFS back edges; nodes get the longest-path layer (edges with labels span two layers so the label gets its own slot); long edges get dummy nodes; crossings are reduced with 24 alternating barycentre sweeps plus adjacent swaps, keeping the best ordering; positions are assigned by order-preserving least squares (isotonic regression) toward the neighbours, which keeps long edges straight.\n- Sequence diagrams place participants in order of appearance, widen gaps to fit message texts and stack messages, notes and blocks top-down. Mind maps are drawn as a two-sided tree, balancing first-level branches by their number of leaves.\n- Styling statements (style, classDef, class, linkStyle, click) and subgraph frames are accepted but not drawn; they are listed as ignored lines. The output is plain SVG (no scripts, no external references) that passes the site’s strict sanitiser; arrowheads are drawn as shapes so PNG export keeps them.\n\nA Mermaid-like subset, not full Mermaid compatibility: complex features (subgraph frames, styling, class diagrams, Gantt charts) are not supported.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "diagram_flowchart_maker",
        "x-owner-app": "ravingdesk",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiagramFlowchartMakerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Order flowchart (top-down, shapes, labelled edges, a loop)",
                  "value": {
                    "source": "flowchart TD\n  start([Order received]) --\u003e pay{Paid?}\n  pay --\u003e|Yes| pick[Pick items]\n  pay --\u003e|No| remind[/Send reminder/]\n  remind --\u003e pay\n  pick --\u003e stock{In stock?}\n  stock --\u003e|Yes| ship[[Ship parcel]]\n  stock --\u003e|No| back[(Backorder list)]\n  back -.-\u003e pick\n  ship --\u003e done((Done))",
                    "title": "Order handling"
                  }
                },
                "example2": {
                  "summary": "Login sequence diagram",
                  "value": {
                    "source": "sequenceDiagram\n  autonumber\n  actor U as User\n  participant B as Browser\n  participant S as Server\n  U-\u003e\u003eB: Click \"Log in\"\n  B-\u003e\u003eS: POST /login\n  alt credentials valid\n    S--\u003e\u003eB: 303 + session cookie\n    B--\u003e\u003eU: Dashboard\n  else invalid\n    S--\u003e\u003eB: 401 error\n    Note right of B: show message\n  end",
                    "title": "Login",
                    "png": false
                  }
                },
                "example3": {
                  "summary": "Trip mind map",
                  "value": {
                    "source": "mindmap\n  root((Trip to Lisbon))\n    Travel\n      Flights\n      Airport transfer\n    Stay\n      Hotel near Baixa\n    See\n      Belém tower\n      Tram 28\n      Sintra day trip\n    Eat\n      Pastéis de nata",
                    "png": false
                  }
                },
                "example4": {
                  "summary": "Left-to-right pipeline",
                  "value": {
                    "source": "flowchart LR\n  A[Commit] --\u003e B[Build] --\u003e C{Tests pass?}\n  C -- yes --\u003e D[Deploy]\n  C -- no --\u003e E[Notify] --\u003e A",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiagramFlowchartMakerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/csv-excel-chart-studio/calculate": {
      "post": {
        "operationId": "calculateCsvExcelChartStudio",
        "summary": "Turn CSV, TSV or Excel data into line, bar, pie, scatter or histogram charts with SVG/PNG export.",
        "description": "Upload a CSV, TSV or XLSX file (up to 20 MB) or paste a table. The studio detects numbers, dates and categories, lets you pick the chart type, X/Y columns, a grouping column, aggregation (sum, average, count …), sorting and top-N, and returns an accessible SVG chart with SVG and PNG downloads plus the data table behind it.\n\nMethodology:\n- The upload is identified by its content: XLSX (a ZIP container) is unpacked with a built-in reader (shared strings, number formats for dates, cached formula values of the chosen sheet); everything else is read as UTF-8 text (Windows-1252 as fallback) and split with the delimiter that gives the most consistent column count.\n- Each column is classified as number, date or text when at least 90 % of its non-empty cells parse that way. Numbers may use thousands separators, a decimal comma (detected per column), currency signs, percent signs and (123) for negatives. Day/month order of dates like 03/04/2026 is detected per column; when the data never disambiguates it, day-first is assumed and stated.\n- For bar, stacked, pie, line and area charts, rows with the same X value are combined with the chosen aggregation (automatic = sum). With a group column, the first Y column is split into one series per group value (at most 8; the rest become \"Other\"). Top N keeps the categories with the largest totals.\n- Charts are drawn by the site’s own SVG library: colour-blind-safe Okabe–Ito colours plus dash patterns or marker shapes, a text alternative, and the data table below. PNG images are rendered from the same SVG at 2× resolution with ImageMagick.\n- Very large inputs are reduced for drawing only: lines with more than 2,000 points show bucket averages, scatter plots with more than 5,000 points show every n-th point; the table and CSV keep all values.\n\nCheck that the detected column types and the aggregation match your data before publishing a chart.",
        "tags": [
          "charts"
        ],
        "x-mcp-tool": "csv_excel_chart_studio",
        "x-owner-app": "ravingdesk",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CsvExcelChartStudioInput"
              },
              "examples": {
                "example1": {
                  "summary": "Revenue by month, stacked by region",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "stacked",
                    "x": "Month",
                    "y": "Revenue",
                    "group": "Region",
                    "png": false
                  }
                },
                "example2": {
                  "summary": "Monthly orders as a line (repeated months summed)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "line",
                    "x": "Month",
                    "y": "Orders",
                    "png": true
                  }
                },
                "example3": {
                  "summary": "Share of revenue by region (pie)",
                  "value": {
                    "data": "Month,Region,Revenue,Orders\n2026-01,North,12400,310\n2026-01,South,9800,250\n2026-02,North,13900,342\n2026-02,South,10150,262\n2026-03,North,15100,371\n2026-03,South,11800,290\n2026-04,North,14650,355\n2026-04,South,12900,301",
                    "chartType": "pie",
                    "x": "Region",
                    "y": "Revenue",
                    "png": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsvExcelChartStudioResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/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"
                }
              }
            }
          }
        }
      },
      "DeckwrightMarkdownToDeckInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "markdown": {
            "title": "Deck in Markdown",
            "description": "Slides are separated by a line ---; without separators every # or ## heading starts a slide. Charts: ```chart blocks with options and CSV; diagrams: ```diagram or ```mermaid blocks; speaker notes after a line Notes:. Images: ![alt text](data:image/png;base64,…).",
            "type": "string",
            "maxLength": 400000,
            "default": "---\ntitle: Quarterly review\nauthor: Example Co\nlang: en\ntheme: paper\nfooter: Example Co · internal\n---\n\n# Quarterly review\n\nWhere we stand after the fourth quarter and what comes next\n\n---\n\n## Agenda\n\n- Results in numbers\n- What **worked** and what did not\n  - Pricing test\n  - New onboarding\n- Plan for the next quarter\n\nNotes:\nThank the team first. Keep this slide under one minute.\n\n---\n\n## Revenue by month\n\n```chart\ntype: bar\ntitle: Revenue in k€ (example data)\nx: Month\ny: Revenue\nalt: Revenue rose every month, from 120 k€ in October to 168 k€ in December.\n\nMonth,Revenue\nOct,120\nNov,141\nDec,168\n```\n\n- December was the best month so far\n- The bundle offer drove a third of the growth\n\nNotes:\nPoint at the December bar. The bundle started on 1 December.\n\n---\n\n## How a support request flows\n\n```diagram\n%% alt: A request is answered with a help article when the issue is known; otherwise a ticket is opened, fixed and answered.\nflowchart LR\n  A[Customer request] --\u003e B{Known issue?}\n  B -- yes --\u003e C[Send help article]\n  B -- no --\u003e D[Open ticket]\n  D --\u003e E[Fix and reply]\n```\n\n---\n\n## Key figures\n\n| Figure | Q3 | Q4 |\n|---|--:|--:|\n| Customers | 1,204 | 1,388 |\n| Churn | 3.1 % | 2.4 % |\n| Replies within a day | 81 % | 92 % |\n\nThe figures are example data.\n\n---\n\n## Next quarter\n\n1. Roll out the new onboarding to everyone\n2. Test yearly prices\n3. Hire a second support person\n"
          },
          "theme": {
            "title": "Theme",
            "type": "string",
            "enum": [
              "deck",
              "paper",
              "midnight",
              "harbor",
              "ember",
              "slate",
              "contrast"
            ],
            "default": "deck"
          },
          "aspect": {
            "title": "Slide shape",
            "type": "string",
            "enum": [
              "deck",
              "16:9",
              "4:3"
            ],
            "default": "deck"
          },
          "lang": {
            "title": "Deck language (BCP 47, e.g. en, de, ar)",
            "description": "Leave empty to use “lang:” from the front matter (English if not set).",
            "type": "string",
            "maxLength": 20,
            "default": ""
          },
          "dir": {
            "title": "Text direction",
            "type": "string",
            "enum": [
              "deck",
              "ltr",
              "rtl"
            ],
            "default": "deck"
          }
        },
        "required": []
      },
      "DeckwrightMarkdownToDeckResult": {
        "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": [
              "slides",
              "meta",
              "outline",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "slides": {
                "type": "integer"
              },
              "meta": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "title",
                  "theme",
                  "aspect",
                  "lang",
                  "dir",
                  "slideWidthMm",
                  "slideHeightMm"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "theme": {
                    "type": "string"
                  },
                  "aspect": {
                    "enum": [
                      "16:9",
                      "4:3"
                    ]
                  },
                  "lang": {
                    "type": "string"
                  },
                  "dir": {
                    "enum": [
                      "ltr",
                      "rtl"
                    ]
                  },
                  "slideWidthMm": {
                    "type": "number"
                  },
                  "slideHeightMm": {
                    "type": "number"
                  }
                }
              },
              "outline": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "n",
                    "title",
                    "layout",
                    "words",
                    "notes",
                    "visuals",
                    "images",
                    "minTextPt"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "layout": {
                      "enum": [
                        "title",
                        "section",
                        "content"
                      ]
                    },
                    "words": {
                      "type": "integer"
                    },
                    "notes": {
                      "type": "boolean"
                    },
                    "visuals": {
                      "type": "array",
                      "items": {
                        "enum": [
                          "chart",
                          "diagram"
                        ]
                      }
                    },
                    "images": {
                      "type": "integer"
                    },
                    "minTextPt": {
                      "type": "number"
                    }
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "html",
                  "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)."
                      }
                    }
                  },
                  "html": {
                    "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"
              }
            }
          }
        }
      },
      "DeckwrightPptxExportInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "markdown": {
            "title": "Deck in Markdown",
            "description": "Slides are separated by a line ---; without separators every # or ## heading starts a slide. Charts: ```chart blocks with options and CSV; diagrams: ```diagram or ```mermaid blocks; speaker notes after a line Notes:. Images: ![alt text](data:image/png;base64,…).",
            "type": "string",
            "maxLength": 400000,
            "default": "---\ntitle: Quarterly review\nauthor: Example Co\nlang: en\ntheme: paper\nfooter: Example Co · internal\n---\n\n# Quarterly review\n\nWhere we stand after the fourth quarter and what comes next\n\n---\n\n## Agenda\n\n- Results in numbers\n- What **worked** and what did not\n  - Pricing test\n  - New onboarding\n- Plan for the next quarter\n\nNotes:\nThank the team first. Keep this slide under one minute.\n\n---\n\n## Revenue by month\n\n```chart\ntype: bar\ntitle: Revenue in k€ (example data)\nx: Month\ny: Revenue\nalt: Revenue rose every month, from 120 k€ in October to 168 k€ in December.\n\nMonth,Revenue\nOct,120\nNov,141\nDec,168\n```\n\n- December was the best month so far\n- The bundle offer drove a third of the growth\n\nNotes:\nPoint at the December bar. The bundle started on 1 December.\n\n---\n\n## How a support request flows\n\n```diagram\n%% alt: A request is answered with a help article when the issue is known; otherwise a ticket is opened, fixed and answered.\nflowchart LR\n  A[Customer request] --\u003e B{Known issue?}\n  B -- yes --\u003e C[Send help article]\n  B -- no --\u003e D[Open ticket]\n  D --\u003e E[Fix and reply]\n```\n\n---\n\n## Key figures\n\n| Figure | Q3 | Q4 |\n|---|--:|--:|\n| Customers | 1,204 | 1,388 |\n| Churn | 3.1 % | 2.4 % |\n| Replies within a day | 81 % | 92 % |\n\nThe figures are example data.\n\n---\n\n## Next quarter\n\n1. Roll out the new onboarding to everyone\n2. Test yearly prices\n3. Hire a second support person\n"
          },
          "theme": {
            "title": "Theme",
            "type": "string",
            "enum": [
              "deck",
              "paper",
              "midnight",
              "harbor",
              "ember",
              "slate",
              "contrast"
            ],
            "default": "deck"
          },
          "aspect": {
            "title": "Slide shape",
            "type": "string",
            "enum": [
              "deck",
              "16:9",
              "4:3"
            ],
            "default": "deck"
          },
          "lang": {
            "title": "Deck language (BCP 47, e.g. en, de, ar)",
            "description": "Leave empty to use “lang:” from the front matter (English if not set).",
            "type": "string",
            "maxLength": 20,
            "default": ""
          },
          "dir": {
            "title": "Text direction",
            "type": "string",
            "enum": [
              "deck",
              "ltr",
              "rtl"
            ],
            "default": "deck"
          }
        },
        "required": []
      },
      "DeckwrightPptxExportResult": {
        "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": [
              "slides",
              "meta",
              "shapes",
              "warnings",
              "file",
              "openInApp"
            ],
            "properties": {
              "slides": {
                "type": "integer"
              },
              "meta": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "title",
                  "theme",
                  "aspect",
                  "lang",
                  "dir",
                  "slideWidthMm",
                  "slideHeightMm"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "theme": {
                    "type": "string"
                  },
                  "aspect": {
                    "enum": [
                      "16:9",
                      "4:3"
                    ]
                  },
                  "lang": {
                    "type": "string"
                  },
                  "dir": {
                    "enum": [
                      "ltr",
                      "rtl"
                    ]
                  },
                  "slideWidthMm": {
                    "type": "number"
                  },
                  "slideHeightMm": {
                    "type": "number"
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "shapes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "n",
                    "title",
                    "textBoxes",
                    "tables",
                    "pictures",
                    "altTexts",
                    "notes"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "textBoxes": {
                      "type": "integer"
                    },
                    "tables": {
                      "type": "integer"
                    },
                    "pictures": {
                      "type": "integer"
                    },
                    "altTexts": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "notes": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "file": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "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"
              }
            }
          }
        }
      },
      "DeckwrightDeckA11yCheckInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "markdown": {
            "title": "Deck in Markdown",
            "description": "Slides are separated by a line ---; without separators every # or ## heading starts a slide.",
            "type": "string",
            "maxLength": 400000,
            "default": "---\ntitle: How plants make food\nlang: en\ntheme: harbor\nfooter: Biology · lesson 4\n---\n\n# How plants make food\n\nPhotosynthesis in five slides\n\n---\n\n## The idea in one sentence\n\n\u003e Plants use the energy of light to turn carbon dioxide and water into sugar and oxygen.\n\n---\n\n## What goes in, what comes out\n\n| In | Out |\n|---|---|\n| Carbon dioxide from the air | Sugar (glucose) |\n| Water from the roots | Oxygen |\n| Light energy | |\n\n6 CO₂ + 6 H₂O + light gives C₆H₁₂O₆ + 6 O₂\n\n---\n\n## Where it happens\n\n```mermaid\n%% alt: Photosynthesis happens in the leaf (chloroplasts, stomata) in two stages: light reactions split water and release oxygen; the Calvin cycle fixes carbon dioxide into sugar.\nmindmap\n  Photosynthesis\n    Leaf\n      Chloroplasts\n      Stomata\n    Light reactions\n      Split water\n      Release oxygen\n    Calvin cycle\n      Fix CO₂\n      Build sugar\n```\n\n---\n\n## Try it yourself\n\n- Put a water plant under a lamp\n- Count the oxygen bubbles per minute\n- Move the lamp closer and count again\n\nNotes:\nAsk the class to predict the result before moving the lamp.\n\n---\n\n## Bubbles and light\n\n```chart\ntype: line\ntitle: Bubbles per minute (example class data)\nx: Distance (cm)\ny: Bubbles\nalt: The closer the lamp, the more bubbles: from 4 per minute at 50 cm to 31 per minute at 10 cm.\n\nDistance (cm),Bubbles\n10,31\n20,19\n30,11\n40,7\n50,4\n```\n"
          },
          "theme": {
            "title": "Theme",
            "type": "string",
            "enum": [
              "deck",
              "paper",
              "midnight",
              "harbor",
              "ember",
              "slate",
              "contrast"
            ],
            "default": "deck"
          },
          "lang": {
            "title": "Deck language (BCP 47, e.g. en, de, ar)",
            "description": "Leave empty to use “lang:” from the front matter (English if not set).",
            "type": "string",
            "maxLength": 20,
            "default": ""
          }
        },
        "required": []
      },
      "DeckwrightDeckA11yCheckResult": {
        "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": [
              "passed",
              "errors",
              "warnings",
              "infos",
              "findings",
              "contrast",
              "slides",
              "theme",
              "openInApp"
            ],
            "properties": {
              "passed": {
                "type": "boolean"
              },
              "errors": {
                "type": "integer"
              },
              "warnings": {
                "type": "integer"
              },
              "infos": {
                "type": "integer"
              },
              "theme": {
                "type": "string"
              },
              "findings": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "severity",
                    "slide",
                    "message",
                    "wcag"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "severity": {
                      "enum": [
                        "error",
                        "warning",
                        "info"
                      ]
                    },
                    "slide": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "wcag": {
                      "type": "string"
                    }
                  }
                }
              },
              "contrast": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "fg",
                    "bg",
                    "ratio",
                    "required",
                    "pass"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "fg": {
                      "type": "string"
                    },
                    "bg": {
                      "type": "string"
                    },
                    "ratio": {
                      "type": "number"
                    },
                    "required": {
                      "type": "number"
                    },
                    "pass": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "slides": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "n",
                    "title",
                    "readingOrder",
                    "minTextPt",
                    "words",
                    "images",
                    "visuals",
                    "notes"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "title": {
                      "type": "string"
                    },
                    "readingOrder": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "minTextPt": {
                      "type": "number"
                    },
                    "words": {
                      "type": "integer"
                    },
                    "images": {
                      "type": "integer"
                    },
                    "visuals": {
                      "type": "integer"
                    },
                    "notes": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "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"
              }
            }
          }
        }
      },
      "DiagramFlowchartMakerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "source": {
            "title": "Diagram text",
            "description": "First line: \"flowchart TD\" (or LR, BT, RL), \"sequenceDiagram\" or \"mindmap\". See the examples.",
            "type": "string",
            "maxLength": 50000,
            "default": "flowchart TD\n  start([Order received]) --\u003e pay{Paid?}\n  pay --\u003e|Yes| pick[Pick items]\n  pay --\u003e|No| remind[/Send reminder/]\n  remind --\u003e pay\n  pick --\u003e stock{In stock?}\n  stock --\u003e|Yes| ship[[Ship parcel]]\n  stock --\u003e|No| back[(Backorder list)]\n  back -.-\u003e pick\n  ship --\u003e done((Done))"
          },
          "title": {
            "title": "Title",
            "description": "Shown above the diagram and used as its accessible name.",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "source"
        ]
      },
      "DiagramFlowchartMakerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "title",
              "width",
              "height",
              "nodes",
              "edges",
              "ignoredLines",
              "layout",
              "svg",
              "png"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "flowchart",
                  "sequence",
                  "mindmap"
                ]
              },
              "title": {
                "type": "string"
              },
              "direction": {
                "type": "string"
              },
              "width": {
                "type": "integer"
              },
              "height": {
                "type": "integer"
              },
              "nodes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "label"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "shape": {
                      "type": "string"
                    },
                    "depth": {
                      "type": "integer"
                    }
                  }
                }
              },
              "edges": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "from",
                    "to",
                    "label"
                  ],
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "style": {
                      "type": "string"
                    }
                  }
                }
              },
              "ignoredLines": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "line",
                    "text"
                  ],
                  "properties": {
                    "line": {
                      "type": "integer"
                    },
                    "text": {
                      "type": "string"
                    }
                  }
                }
              },
              "layout": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "layers": {
                    "type": "integer"
                  },
                  "crossings": {
                    "type": "integer"
                  },
                  "reversedEdges": {
                    "type": "integer"
                  },
                  "dummyNodes": {
                    "type": "integer"
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "CsvExcelChartStudioInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file": {
            "title": "CSV, TSV or Excel file",
            "description": "CSV/TSV/TXT or .xlsx, max 20 MB. The format is detected from the content. Old .xls files: save as .xlsx first. Upload as {filename, contentType?, contentBase64}. Max 20480 KiB. Accepts .csv,.tsv,.txt,.xlsx,text/csv,text/tab-separated-values,text/plain,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "data": {
            "title": "Or paste data",
            "description": "Comma-, semicolon-, tab- or pipe-separated, first row = headers. Used when no file is uploaded.",
            "type": "string",
            "maxLength": 2000000
          },
          "sheet": {
            "title": "Excel sheet",
            "description": "Sheet name or number; default: the first sheet.",
            "type": "string",
            "maxLength": 120
          },
          "hasHeader": {
            "title": "First row contains column names",
            "type": "boolean",
            "default": true
          },
          "chartType": {
            "title": "Chart type",
            "type": "string",
            "enum": [
              "auto",
              "line",
              "area",
              "bar",
              "stacked",
              "scatter",
              "pie",
              "donut",
              "histogram"
            ],
            "default": "auto"
          },
          "x": {
            "title": "X column (categories or dates)",
            "description": "Column name, letter (A, B …) or number. Empty: first date or text column.",
            "type": "string",
            "maxLength": 200
          },
          "y": {
            "title": "Y columns (values)",
            "description": "One or more column names, comma-separated. Empty: the numeric columns. No numeric column: rows are counted.",
            "type": "string",
            "maxLength": 1000
          },
          "group": {
            "title": "Group / series column",
            "description": "Optional: split the first Y column into one series per value of this column (e.g. Region) – ideal for stacked bars.",
            "type": "string",
            "maxLength": 200
          },
          "aggregation": {
            "title": "Combine repeated X values",
            "type": "string",
            "enum": [
              "auto",
              "sum",
              "avg",
              "count",
              "min",
              "max",
              "median",
              "none"
            ],
            "default": "auto"
          },
          "sort": {
            "title": "Sort",
            "type": "string",
            "enum": [
              "auto",
              "none",
              "x",
              "value-desc",
              "value-asc"
            ],
            "default": "auto"
          },
          "topN": {
            "title": "Top N categories",
            "description": "0 = all (very long category lists are cut automatically).",
            "type": "integer",
            "minimum": 0,
            "maximum": 200,
            "default": 0
          },
          "otherBucket": {
            "title": "Combine the rest into \"Other\"",
            "type": "boolean",
            "default": true
          },
          "bins": {
            "title": "Histogram bins",
            "description": "0 = automatic (Sturges’ rule).",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 0
          },
          "title": {
            "title": "Chart title",
            "type": "string",
            "maxLength": 140
          },
          "png": {
            "title": "Also create a PNG image",
            "type": "boolean",
            "default": true
          }
        },
        "required": []
      },
      "CsvExcelChartStudioResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "source",
              "columns",
              "chart",
              "table",
              "svg",
              "png"
            ],
            "properties": {
              "source": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "format",
                  "rows",
                  "columns",
                  "sheet",
                  "truncated"
                ],
                "properties": {
                  "format": {
                    "type": "string"
                  },
                  "rows": {
                    "type": "integer"
                  },
                  "columns": {
                    "type": "integer"
                  },
                  "sheet": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "sheets": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "delimiter": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "truncated": {
                    "type": "boolean"
                  }
                }
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "type",
                    "nonEmpty",
                    "distinct"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "number",
                        "date",
                        "category",
                        "empty"
                      ]
                    },
                    "nonEmpty": {
                      "type": "integer"
                    },
                    "distinct": {
                      "type": "integer"
                    }
                  }
                }
              },
              "chart": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "type",
                  "title",
                  "x",
                  "y",
                  "group",
                  "aggregation",
                  "sort",
                  "topN",
                  "categories",
                  "series",
                  "points"
                ],
                "properties": {
                  "type": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "x": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "y": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "group": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "aggregation": {
                    "type": "string"
                  },
                  "sort": {
                    "type": "string"
                  },
                  "topN": {
                    "type": "integer"
                  },
                  "categories": {
                    "type": "integer"
                  },
                  "series": {
                    "type": "integer"
                  },
                  "points": {
                    "type": "integer"
                  }
                }
              },
              "table": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "header",
                  "rows",
                  "totalRows"
                ],
                "properties": {
                  "header": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "rows": {
                    "type": "array",
                    "items": {
                      "type": "array"
                    }
                  },
                  "totalRows": {
                    "type": "integer"
                  }
                }
              },
              "svg": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string",
                    "description": "Download path on the same site (valid for about 2 hours)."
                  }
                }
              },
              "png": {
                "anyOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}