{
  "openapi": "3.1.1",
  "info": {
    "title": "Maths Worksheet Maker (Variants A/B/C with Answers) API",
    "version": "1.0.0",
    "summary": "Times tables, column sums, division and fractions — seeded variants with answer keys.",
    "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://printshopmathworksheet.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Times tables, column sums, division and fractions — seeded variants with answer keys.",
        "description": "Make maths worksheets for the classroom or home: times tables, column addition and subtraction with or without carrying, long multiplication, division with or without remainders, fractions, or a mix of facts. Up to six variants (A to F) give neighbours different problems of the same difficulty, each with its answer key.\n\nMethodology:\n- Each variant letter has its own seeded random stream (seed + letter), so variant B is always the same for the same seed and differs from A. Repeated problems are avoided within a variant.\n- Column addition without carrying keeps every digit sum below 10; subtraction without borrowing keeps every digit of the first number at least as large as the one below it (and the result never negative). With regrouping allowed, problems that actually need it are preferred.\n- Division problems are built backwards (divisor × quotient + remainder), so answers are whole numbers. Fraction answers are reduced with the greatest common divisor; subtraction never goes below zero.\n\nCheck that the exercise type fits the class level; the generator does not follow a particular curriculum.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "printshop_math_worksheet",
        "x-owner-app": "printshop",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintshopMathWorksheetInput"
              },
              "examples": {
                "example1": {
                  "summary": "Times tables 2–10, variants A–C",
                  "value": {
                    "kind": "times",
                    "tables": "2-10",
                    "count": 30,
                    "variants": 3,
                    "seed": "class-4b"
                  }
                },
                "example2": {
                  "summary": "Three-digit subtraction with borrowing",
                  "value": {
                    "kind": "sub",
                    "digits": 3,
                    "regroup": true,
                    "count": 24,
                    "variants": 2,
                    "seed": "sub-3"
                  }
                },
                "example3": {
                  "summary": "Adding fractions with like denominators",
                  "value": {
                    "kind": "fractions",
                    "fractionOps": "add",
                    "sameDenominator": true,
                    "maxDenominator": 12,
                    "count": 20,
                    "variants": 1,
                    "seed": "frac-1"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintshopMathWorksheetResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "PrintshopMathWorksheetInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kind": {
            "title": "Exercises",
            "type": "string",
            "enum": [
              "times",
              "add",
              "sub",
              "mul",
              "div",
              "fractions",
              "mixed"
            ],
            "default": "times"
          },
          "count": {
            "title": "Problems per variant",
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 30
          },
          "variants": {
            "title": "Variants (A, B, C …)",
            "type": "integer",
            "minimum": 1,
            "maximum": 6,
            "default": 3
          },
          "tables": {
            "title": "Times tables",
            "description": "For times tables and mixed facts, e.g. 2-10 or 3, 4, 7.",
            "type": "string",
            "maxLength": 60,
            "default": "2-10"
          },
          "maxFactor": {
            "title": "Largest factor",
            "type": "integer",
            "minimum": 2,
            "maximum": 20,
            "default": 10
          },
          "digits": {
            "title": "Digits per number (column sums, multiplication)",
            "type": "integer",
            "minimum": 1,
            "maximum": 6,
            "default": 3
          },
          "regroup": {
            "title": "Carrying and borrowing",
            "type": "boolean",
            "default": true
          },
          "digits2": {
            "title": "Digits of the second number (multiplication, division)",
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "default": 1
          },
          "remainder": {
            "title": "Division with remainders",
            "type": "boolean",
            "default": false
          },
          "maxDenominator": {
            "title": "Largest denominator (fractions)",
            "type": "integer",
            "minimum": 2,
            "maximum": 20,
            "default": 10
          },
          "fractionOps": {
            "title": "Fraction operations",
            "type": "string",
            "enum": [
              "add",
              "sub",
              "both"
            ],
            "default": "add"
          },
          "sameDenominator": {
            "title": "Same denominators only",
            "type": "boolean",
            "default": false
          },
          "seed": {
            "title": "Seed",
            "description": "The same seed and settings always give the same puzzles. Change it for new ones.",
            "type": "string",
            "maxLength": 80,
            "default": "class-1"
          },
          "title": {
            "title": "Title on the page (optional)",
            "type": "string",
            "maxLength": 120,
            "default": ""
          },
          "answers": {
            "title": "Answer-key pages",
            "type": "boolean",
            "default": true
          },
          "header": {
            "title": "Name and date line",
            "type": "boolean",
            "default": true
          },
          "paper": {
            "title": "Paper size",
            "type": "string",
            "enum": [
              "a3",
              "a4",
              "a5",
              "a6",
              "b5",
              "letter",
              "legal",
              "tabloid",
              "halfletter"
            ],
            "default": "a4"
          },
          "orientation": {
            "title": "Orientation",
            "type": "string",
            "enum": [
              "portrait",
              "landscape"
            ],
            "default": "portrait"
          }
        },
        "required": []
      },
      "PrintshopMathWorksheetResult": {
        "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",
              "variants",
              "seed",
              "pages",
              "puzzlePages",
              "answerPages",
              "pageWidthMm",
              "pageHeightMm",
              "warnings",
              "files",
              "openInApp"
            ],
            "properties": {
              "kind": {
                "type": "string"
              },
              "variants": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "variant",
                    "problems"
                  ],
                  "properties": {
                    "variant": {
                      "type": "string"
                    },
                    "problems": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "question",
                          "answer"
                        ],
                        "properties": {
                          "question": {
                            "type": "string"
                          },
                          "answer": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "seed": {
                "type": "string"
              },
              "pages": {
                "type": "integer"
              },
              "puzzlePages": {
                "type": "integer"
              },
              "answerPages": {
                "type": "integer"
              },
              "pageWidthMm": {
                "type": "number"
              },
              "pageHeightMm": {
                "type": "number"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "files": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "pdf",
                  "svg",
                  "png"
                ],
                "properties": {
                  "pdf": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "svg": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  },
                  "png": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "artifactId",
                      "filename",
                      "mime",
                      "bytes",
                      "sha256",
                      "path"
                    ],
                    "properties": {
                      "artifactId": {
                        "type": "string"
                      },
                      "filename": {
                        "type": "string"
                      },
                      "mime": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "integer"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string",
                        "description": "Download path on the same site (valid for about 2 hours)."
                      }
                    }
                  }
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}