{
  "openapi": "3.1.1",
  "info": {
    "title": "Markdown to Slides (PDF and HTML) API",
    "version": "1.0.0",
    "summary": "Turn Markdown into a clean slide deck — PDF with embedded fonts and a single-file HTML presentation.",
    "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://deckwrightmarkdowntodeck.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "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/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "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"
              }
            }
          }
        }
      }
    }
  }
}