{
  "openapi": "3.1.1",
  "info": {
    "title": "Threadsmith Pattern Block Drafter API",
    "version": "1.0.0",
    "summary": "Draft skirt, bodice, sleeve and trouser blocks from your measurements as tiled PDF, SVG or DXF.",
    "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://threadsmithpatternblock.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Draft skirt, bodice, sleeve and trouser blocks from your measurements as tiled PDF, SVG or DXF.",
        "description": "Enter your body measurements (only bust, waist and hip are required — the rest is derived) and get sewing-pattern blocks drafted to them: a straight skirt, a fitted bodice with bust and waist darts, a one-piece sleeve whose cap is solved to the bodice armhole plus cap ease, and trousers. Each piece gets seam and hem allowance (mitred or squared corners, folded-hem corners), notches, grainline and darts trued to equal legs. The tool checks that the waist and hip of the drafted pieces equal your measurements plus ease, can grade a size run from your measurements, and writes a home-printable tiled PDF (A4 or Letter with overlap, crosses and a test square), a full-size SVG for plotters and projectors, or a DXF R12 file.\n\nMethodology:\n- Measurements follow the landmark definitions of ISO 8559-1 (paraphrased). Missing measurements are derived from an own mid-range sample body: girths scale with your bust or hip, lengths with your height (or with the lengths you gave). No commercial size chart is used.\n- Blocks are an own geometric construction in the tradition of proportional drafting (Fales 1917, Vincent 1898, both public domain): skirt quarters with the side seam 5 mm towards the back; bodice back and front with back width, neck width neck/6 + 5 mm and armhole depth from the bust; a side bust dart whose intake makes the closed front side seam equal to the back; trousers with crotch extensions hip/16 (front) and hip/10 (back) and a 10° back seat angle.\n- Waist darts are solved numerically so the waist seam with darts closed equals waist + ease within 0.01 mm; darts are trued (shorter leg extended, dart cap on the closed seam line). The sleeve cap height is solved by bisection so the cap length equals the bodice armhole + cap ease.\n- Seam allowance: the seam line is flattened (0.05 mm tolerance) and every segment offset by its edge allowance (fold 0, hem, seam); convex corners mitred (squared off beyond 3× the allowance) or squared, concave corners trimmed, hem corners mirrored about the hem fold line, loops on tight inward curves removed.\n- Grading regenerates every size from measurements scaled by a grade rule (girths ± the step, neck/arm/lengths proportionally). Tiled print: printable area = paper − 10 mm margins, pages step by printable size − overlap, alignment crosses at the centre of each overlap strip, cover page with a 10 cm (or 4 in) test square and an assembly map.\n\nA block is a starting point, not a finished garment pattern: make a test garment (toile) from cheap fabric and adjust the fit before cutting good fabric. Print at 100 % and measure the test square. Cloth simulation is not part of this tool.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "threadsmith_pattern_block",
        "x-owner-app": "threadsmith",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadsmithPatternBlockInput"
              },
              "examples": {
                "example1": {
                  "summary": "Straight skirt from bust 92, waist 74, hip 100 cm (A4 tiles)",
                  "value": {
                    "units": "cm",
                    "blocks": [
                      "skirt"
                    ],
                    "bust": 92,
                    "waist": 74,
                    "hip": 100,
                    "skirtLength": 60
                  }
                },
                "example2": {
                  "summary": "Bodice + sleeve with own ease, full-size SVG",
                  "value": {
                    "units": "cm",
                    "blocks": [
                      "bodice",
                      "sleeve"
                    ],
                    "bust": 96,
                    "waist": 78,
                    "hip": 104,
                    "backWaist": 42,
                    "shoulder": 12.5,
                    "upperArm": 30,
                    "ease": "bodiceBust=8, capEase=1.2",
                    "output": "svg"
                  }
                },
                "example3": {
                  "summary": "Trousers in inches, graded one size up and down, DXF",
                  "value": {
                    "units": "in",
                    "blocks": [
                      "trousers"
                    ],
                    "bust": 38,
                    "waist": 31,
                    "hip": 41,
                    "crotchDepth": 11,
                    "outsideLeg": 41.5,
                    "gradeDown": 1,
                    "gradeUp": 1,
                    "gradeStep": 2,
                    "paper": "letter",
                    "output": "dxf"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadsmithPatternBlockResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "ThreadsmithPatternBlockInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "units": {
            "title": "Units of all lengths below",
            "type": "string",
            "enum": [
              "cm",
              "in"
            ],
            "default": "cm"
          },
          "blocks": {
            "title": "Blocks",
            "description": "The sleeve is fitted to the bodice armhole drafted from the same measurements.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "skirt",
                "bodice",
                "sleeve",
                "trousers"
              ]
            },
            "default": [
              "skirt"
            ]
          },
          "height": {
            "title": "Body height",
            "description": "Standing, barefoot, from the floor to the top of the head. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "bust": {
            "title": "Bust / chest girth",
            "description": "Horizontal girth over the fullest part of the bust (bust points) or chest, under the arms. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "waist": {
            "title": "Waist girth",
            "description": "Horizontal girth at the natural waist, the narrowest part between the lowest rib and the hip bone. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "hip": {
            "title": "Hip girth",
            "description": "Horizontal girth over the fullest part of the buttocks. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "neck": {
            "title": "Neck base girth",
            "description": "Around the base of the neck through the nape (cervicale), the side neck points and the front neck point. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "backWaist": {
            "title": "Back waist length",
            "description": "From the nape (cervicale) down the centre back to the waist line. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "frontWaist": {
            "title": "Front waist length",
            "description": "From the side neck point over the bust point straight down to the waist line. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "bustDepth": {
            "title": "Bust point depth",
            "description": "From the side neck point to the bust point. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "bustSpan": {
            "title": "Bust point separation",
            "description": "Horizontal distance between the two bust points. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "shoulder": {
            "title": "Shoulder length",
            "description": "From the side neck point to the shoulder point (acromion). Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "acrossBack": {
            "title": "Back width",
            "description": "Across the back between the armpit folds, about halfway between nape and underarm level. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "arm": {
            "title": "Arm length",
            "description": "From the shoulder point over the slightly bent elbow to the wrist bone. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "upperArm": {
            "title": "Upper arm girth",
            "description": "Horizontal girth of the upper arm at its fullest, just below the armpit. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "wrist": {
            "title": "Wrist girth",
            "description": "Around the wrist over the wrist bone. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "hipDepth": {
            "title": "Waist to hip",
            "description": "Vertical distance from the waist line to the hip line, at the side. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "crotchDepth": {
            "title": "Body rise (crotch depth)",
            "description": "Seated on a hard flat chair: vertical distance from the waist line at the side down to the seat. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "outsideLeg": {
            "title": "Waist to floor (outside leg)",
            "description": "At the side from the waist line down to the floor, barefoot. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "skirtLength": {
            "title": "Skirt length",
            "description": "Design measurement: from the waist at centre front down to the hem. Empty = derived from the measurements you give.",
            "type": "number",
            "minimum": 0,
            "maximum": 2200
          },
          "ease": {
            "title": "Ease (optional)",
            "description": "Wearing ease in the units above, as key=value. Keys: bodiceBust (bodice ease at the bust), bodiceWaist (bodice ease at the waist), skirtWaist (skirt ease at the waist), skirtHip (skirt ease at the hip), trousersWaist (trousers ease at the waist), trousersHip (trousers ease at the hip), crotch (ease in the body rise), upperArm (sleeve ease at the upper arm), wrist (sleeve ease at the wrist), capEase (sleeve cap ease).",
            "type": "string",
            "maxLength": 600
          },
          "seamAllowance": {
            "title": "Seam allowance",
            "description": "Empty = 1.5 cm or 5/8 in. Fold edges get none.",
            "type": "number",
            "minimum": 0,
            "maximum": 50
          },
          "hemAllowance": {
            "title": "Hem allowance",
            "description": "Empty = 4 cm or 1 1/2 in.",
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "corner": {
            "title": "Allowance corners",
            "type": "string",
            "enum": [
              "mitre",
              "square"
            ],
            "default": "mitre"
          },
          "hemCorner": {
            "title": "Hem corners",
            "type": "string",
            "enum": [
              "mirror",
              "mitre"
            ],
            "default": "mirror"
          },
          "gradeDown": {
            "title": "Sizes below yours",
            "type": "integer",
            "minimum": 0,
            "maximum": 4,
            "default": 0
          },
          "gradeUp": {
            "title": "Sizes above yours",
            "type": "integer",
            "minimum": 0,
            "maximum": 4,
            "default": 0
          },
          "gradeStep": {
            "title": "Girth step per size",
            "description": "Empty = 4 cm. Bust, waist and hip grow by this much per size; other measurements by a proportional rule.",
            "type": "number",
            "minimum": 0.5,
            "maximum": 8
          },
          "size": {
            "title": "Size in the files",
            "description": "Base, +1, +2 … or -1, -2 … of the size run.",
            "type": "string",
            "maxLength": 4,
            "default": "Base"
          },
          "hemWidth": {
            "title": "Trouser hem circumference",
            "description": "Empty = 42 cm.",
            "type": "number",
            "minimum": 0,
            "maximum": 900
          },
          "paper": {
            "title": "Paper for the tiled PDF",
            "type": "string",
            "enum": [
              "a4",
              "letter"
            ],
            "default": "a4"
          },
          "overlap": {
            "title": "Page overlap",
            "description": "Empty = 1.5 cm.",
            "type": "number",
            "minimum": 0,
            "maximum": 40
          },
          "output": {
            "title": "File",
            "type": "string",
            "enum": [
              "pdf",
              "svg",
              "dxf"
            ],
            "default": "pdf"
          }
        },
        "required": []
      },
      "ThreadsmithPatternBlockResult": {
        "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",
            "required": [
              "units",
              "blocks",
              "size",
              "sizes",
              "measurements",
              "derived",
              "checks",
              "allChecksOk",
              "pieces",
              "file",
              "appUrl"
            ],
            "properties": {
              "units": {
                "type": "string",
                "enum": [
                  "cm",
                  "in"
                ]
              },
              "blocks": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "size": {
                "type": "string"
              },
              "sizes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string"
                    },
                    "bust": {
                      "type": "number"
                    },
                    "waist": {
                      "type": "number"
                    },
                    "hip": {
                      "type": "number"
                    },
                    "checksOk": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "measurements": {
                "type": "object",
                "description": "Body measurements used (mm), including derived ones."
              },
              "derived": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Measurements filled in from the sample body (scaled)."
              },
              "checks": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "piece": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "target": {
                      "type": "number"
                    },
                    "actual": {
                      "type": "number"
                    },
                    "tolerance": {
                      "type": "number"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "allChecksOk": {
                "type": "boolean"
              },
              "pieces": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "size": {
                      "type": "string"
                    },
                    "cut": {
                      "type": "string"
                    },
                    "quantity": {
                      "type": "integer"
                    },
                    "pair": {
                      "type": "boolean"
                    },
                    "onFold": {
                      "type": "boolean"
                    },
                    "areaCm2": {
                      "type": "number"
                    },
                    "widthMm": {
                      "type": "number"
                    },
                    "heightMm": {
                      "type": "number"
                    },
                    "grain": {
                      "type": "number"
                    },
                    "measures": {
                      "type": "object"
                    },
                    "polygon": {
                      "type": "array",
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "number"
                        }
                      },
                      "description": "Cutting line, mm (0.1 mm), ready for threadsmith-marker-layout."
                    },
                    "fold": {
                      "type": [
                        "array",
                        "null"
                      ],
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              },
              "file": {
                "type": "object",
                "properties": {
                  "format": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "pages": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "artifactUrl": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "appUrl": {
                "type": "string",
                "description": "Opens these settings in the Threadsmith Pattern desk."
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}