{
  "openapi": "3.1.1",
  "info": {
    "title": "Flashcards from Markdown, CSV or Anki Text API",
    "version": "1.0.0",
    "summary": "Turn notes into flashcards: Q:/A: pairs, term :: definition lines, cloze gaps, CSV or Anki text.",
    "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://deckwrightcardsfrommarkdown.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Turn notes into flashcards: Q:/A: pairs, term :: definition lines, cloze gaps, CSV or Anki text.",
        "description": "Reads study notes and makes flashcards with stable ids: Markdown “Q:”/“A:” pairs, “term :: definition” lines (“:::” adds the reverse card), {{c1::cloze}} gaps with optional hints (one card per gap number, like Anki), # headings as tags, CSV or tab-separated rows, an Anki “Notes in Plain Text” export (HTML turned into text) or a Deckwright slide deck (slide titles become questions). Returns the cards, a CSV file, the cards as editable Markdown and a link that opens them in Deckwright’s Study view.\n\nMethodology:\n- Markdown: a line “Q:” starts a question, “A:” its answer (several lines; a blank line ends the card). “front :: back” lines make one card, “front ::: back” two (both directions). Paragraphs with {{cN::answer}} or {{cN::answer::hint}} make one cloze card per number N: that gap shows […] or [hint], the other gaps show their text. # headings tag the cards below them.\n- CSV and TSV follow RFC 4180 (quoted fields may hold commas, tabs and line breaks); a first row named front/back, question/answer or term/definition is a header, a third column or a column named tag becomes the tag. Anki text exports honour #separator, #html, #columns and the #notetype/#deck/#guid/#tags column headers; HTML line breaks are kept, bold and italic become Markdown, pictures become their file name.\n- A slide deck gives one card per content slide with a title: the title is the question, the slide text (lists, tables, quotes, chart and diagram descriptions) the answer; # section slides tag the cards after them; speaker notes stay out.\n- Card ids are “b-”, “r-” (reverse) or “cN-” (cloze) plus the FNV-1a hash of the question (of the full sentence for cloze cards), so editing an answer keeps the card’s review history; repeated questions get -2, -3 ….\n\nAnki .apkg packages (SQLite) are not read; export the notes from Anki as “Notes in Plain Text” instead. Pictures inside an Anki text export cannot be carried over.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "deckwright_cards_from_markdown",
        "x-owner-app": "deckwright",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeckwrightCardsFromMarkdownInput"
              },
              "examples": {
                "example1": {
                  "summary": "Spanish phrases with reverse cards and two cloze gaps",
                  "value": {
                    "text": "# Greetings\nhola ::: hello\nbuenos días ::: good morning\ngracias ::: thank you\n\n# Getting around\nQ: How do you ask where the station is?\nA: ¿Dónde está la estación?\n\nla estación :: the station\nel billete :: the ticket\n\n# At the café\nun café con leche :: a coffee with milk\n\nQ: How do you ask for the bill?\nA: la cuenta, por favor\n\nMadrid's main station is {{c1::Atocha}}; the fast train to Barcelona takes about {{c2::two and a half::how long?}} hours.\n",
                    "lang": "es"
                  }
                },
                "example2": {
                  "summary": "Cards from a lesson deck (slide titles become questions)",
                  "value": {
                    "text": "---\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",
                    "format": "deck"
                  }
                },
                "example3": {
                  "summary": "CSV with a header row, both directions",
                  "value": {
                    "text": "front,back,tag\nH2O,water,chemistry\nNaCl,table salt,chemistry\nCO2,carbon dioxide,chemistry\n",
                    "format": "csv",
                    "reverse": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeckwrightCardsFromMarkdownResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "DeckwrightCardsFromMarkdownInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "text": {
            "title": "Cards",
            "description": "Markdown: “Q:” and “A:” lines, “term :: definition” (“:::” also makes the reverse card), {{c1::cloze}} gaps, # headings as tags. Or CSV/TSV rows (front, back, tag), an Anki plain-text export, or a slide deck.",
            "type": "string",
            "maxLength": 200000,
            "default": "# Greetings\nhola ::: hello\nbuenos días ::: good morning\ngracias ::: thank you\n\n# Getting around\nQ: How do you ask where the station is?\nA: ¿Dónde está la estación?\n\nla estación :: the station\nel billete :: the ticket\n\n# At the café\nun café con leche :: a coffee with milk\n\nQ: How do you ask for the bill?\nA: la cuenta, por favor\n\nMadrid's main station is {{c1::Atocha}}; the fast train to Barcelona takes about {{c2::two and a half::how long?}} hours.\n"
          },
          "format": {
            "title": "Format",
            "type": "string",
            "enum": [
              "auto",
              "markdown",
              "csv",
              "tsv",
              "anki",
              "deck"
            ],
            "default": "auto"
          },
          "reverse": {
            "title": "Also make reverse cards (answer → question)",
            "type": "boolean",
            "default": false
          },
          "lang": {
            "title": "Card language (BCP 47, e.g. en, es, ja)",
            "description": "Used for answer checks and fonts; empty = English.",
            "type": "string",
            "maxLength": 20,
            "default": ""
          }
        },
        "required": []
      },
      "DeckwrightCardsFromMarkdownResult": {
        "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": [
              "format",
              "count",
              "kinds",
              "tags",
              "cards",
              "warnings",
              "skippedLines",
              "markdown",
              "files",
              "openInApp"
            ],
            "properties": {
              "format": {
                "enum": [
                  "markdown",
                  "csv",
                  "tsv",
                  "anki",
                  "deck"
                ]
              },
              "count": {
                "type": "integer"
              },
              "kinds": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "basic",
                  "reverse",
                  "cloze"
                ],
                "properties": {
                  "basic": {
                    "type": "integer"
                  },
                  "reverse": {
                    "type": "integer"
                  },
                  "cloze": {
                    "type": "integer"
                  }
                }
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "cards": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "n",
                    "id",
                    "kind",
                    "front",
                    "back",
                    "answer",
                    "tag",
                    "line"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "enum": [
                        "basic",
                        "reverse",
                        "cloze"
                      ]
                    },
                    "front": {
                      "type": "string"
                    },
                    "back": {
                      "type": "string"
                    },
                    "answer": {
                      "type": "string"
                    },
                    "tag": {
                      "type": "string"
                    },
                    "line": {
                      "type": "integer"
                    }
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "skippedLines": {
                "type": "integer"
              },
              "markdown": {
                "type": "string"
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "csv",
                  "markdown"
                ],
                "properties": {
                  "csv": {
                    "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)."
                      }
                    }
                  },
                  "markdown": {
                    "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"
              }
            }
          }
        }
      }
    }
  }
}