{
  "openapi": "3.1.1",
  "info": {
    "title": "Threadsmith Stitch File Writer API",
    "version": "1.0.0",
    "summary": "Write DST, PES, JEF or EXP embroidery machine files from a stitch list or a Threadsmith project.",
    "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://threadsmithstitchfile.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Write DST, PES, JEF or EXP embroidery machine files from a stitch list or a Threadsmith project.",
        "description": "Encodes stitches as a Tajima DST (512-byte header, balanced-ternary 3-byte records, jumps split to ≤ 12.1 mm, colour changes, trims as zero-sum jumps, END), Brother PES (v1 wrapper around the PEC stitch block with thread palette indices and thumbnails, real trim flags), Janome JEF (header with hoop, extents and Janome thread indices) or Melco EXP file. The file is decoded again to verify every stitch position before you download it.\n\nMethodology:\n- Coordinates are rounded to 0.1 mm on absolute positions, so rounding never accumulates; each move becomes the difference to the previous rounded position.\n- DST: each axis is written in balanced ternary with digits for 1, 3, 9, 27 and 81 (±121 max). Byte 3 = 0x03 | flags: 0x80 jump, 0xC0 colour change; END = 00 00 F3. Longer moves are split into equal records. Y is inverted (DST is y-up).\n- Trims are written as three jumps (+2,+2) (−4,−4) (+2,+2) that cancel out — the convention machines use to trigger a trim after a run of jumps.\n- Header: LA label, ST record count, CO colour changes, ±X/±Y extents in 0.1 mm, AX/AY end offset, MX/MY 0, PD ******, 0x1A, padded with spaces to 512 bytes.\n- EXP: 2 signed bytes per stitch (±127), 0x80 0x04 dx dy jump, 0x80 0x01 colour change; trims as three zero-sum jumps.\n- PES: \"#PES0001\" + PEC offset + empty v1 object section, then the PEC block every Brother/Babylock machine reads: 512-byte header with label, colour count and the nearest of the 64 PEC palette threads per colour block; stitches as 7-bit short or 12-bit long moves (0x1000 jump, 0x2000 trim flag), FE B0 colour change, FF end; 48×38 1-bit thumbnails. Y is down.\n- JEF: 116-byte little-endian header (stitch offset, date, colour and point counts, hoop code, extents, edge distances to the 110×110 / 50×50 / 140×200 / custom hoops) + nearest Janome thread index per colour; stitches as 2 signed bytes (y up), 80 02 jump, 80 01 colour change, 80 10 end; trims as a zero jump.\n\nDST and EXP carry no thread colours; PES and JEF store the nearest colour of the machine’s own thread chart, which is only an approximation. Use the colour list from Threadsmith to thread the needles. Test on scrap fabric first.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "threadsmith_stitch_file",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadsmithStitchFileInput"
              },
              "examples": {
                "example1": {
                  "summary": "Tiny square outline with a jump and a colour change → DST",
                  "value": {
                    "format": "dst",
                    "label": "SQUARE",
                    "stitches": "[[0,0],[10,0],[10,10],[0,10],[0,0],[30,0,\"jump\"],[30,0,\"color\"],[30,0],[40,5],[30,10]]"
                  }
                },
                "example2": {
                  "summary": "Template project (name tag) → Melco EXP",
                  "value": {
                    "format": "exp",
                    "project": "{\"format\":\"threadsmith\",\"version\":1,\"name\":\"Name tag\",\"hoop\":\"130x180\",\"palette\":[{\"id\":\"sapphire\",\"name\":\"Sapphire\",\"hex\":\"#0f4c81\"},{\"id\":\"coral\",\"name\":\"Coral\",\"hex\":\"#e8705a\"},{\"id\":\"ivory\",\"name\":\"Ivory\",\"hex\":\"#fffbf0\"}],\"objects\":[{\"id\":\"frame\",\"name\":\"Frame\",\"kind\":\"rect\",\"color\":\"sapphire\",\"x\":-45,\"y\":-22,\"w\":90,\"h\":44,\"r\":8,\"stitch\":{\"type\":\"satin\",\"mode\":\"border\",\"width\":3,\"density\":0.4},\"underlay\":{\"center\":true}},{\"id\":\"hello\",\"name\":\"Hello\",\"kind\":\"text\",\"color\":\"coral\",\"text\":\"Hello, my name is\",\"x\":0,\"y\":-7,\"size\":6,\"font\":\"single\",\"align\":\"center\",\"stitch\":{\"type\":\"running\",\"length\":1.8,\"bean\":true}},{\"id\":\"name\",\"name\":\"Name\",\"kind\":\"text\",\"color\":\"sapphire\",\"text\":\"Ada\",\"x\":0,\"y\":14,\"size\":16,\"font\":\"single\",\"align\":\"center\",\"spacing\":1,\"stitch\":{\"type\":\"satin\",\"width\":2.4,\"density\":0.36},\"underlay\":{\"center\":true}}]}"
                  }
                },
                "example3": {
                  "summary": "Template project (botanical leaf) → Brother PES with thread colours",
                  "value": {
                    "format": "pes",
                    "label": "LEAF",
                    "project": "{\"format\":\"threadsmith\",\"version\":1,\"name\":\"Botanical leaf\",\"hoop\":\"100x100\",\"palette\":[{\"id\":\"emerald\",\"name\":\"Emerald\",\"hex\":\"#0b7a4b\"},{\"id\":\"malachite\",\"name\":\"Malachite\",\"hex\":\"#1f5c3f\"},{\"id\":\"walnut\",\"name\":\"Walnut\",\"hex\":\"#6d4a33\"}],\"objects\":[{\"id\":\"leaf\",\"name\":\"Leaf\",\"kind\":\"path\",\"color\":\"emerald\",\"d\":\"M0 -38C24 -24 26 14 0 36C-26 14 -24 -24 0 -38Z\",\"stitch\":{\"type\":\"tatami\",\"angle\":60,\"spacing\":0.4,\"length\":4,\"stagger\":\"1/3\",\"pullComp\":0.2},\"underlay\":{\"edge\":true,\"tatami\":true,\"inset\":0.5}},{\"id\":\"vein\",\"name\":\"Centre vein\",\"kind\":\"path\",\"color\":\"malachite\",\"d\":\"M0 -32C2 -10 2 12 0 33\",\"stitch\":{\"type\":\"running\",\"length\":2.2,\"bean\":true}},{\"id\":\"veins\",\"name\":\"Side veins\",\"kind\":\"path\",\"color\":\"malachite\",\"d\":\"M1 -18L12 -26M1 -6L15 -13M1 6L15 0M1 18L12 13M-1 -18L-12 -26M-1 -6L-15 -13M-1 6L-15 0M-1 18L-12 13\",\"stitch\":{\"type\":\"running\",\"length\":2,\"bean\":true}},{\"id\":\"stem\",\"name\":\"Stem\",\"kind\":\"path\",\"color\":\"walnut\",\"d\":\"M0 35C1 40 3 43 7 46\",\"stitch\":{\"type\":\"satin\",\"width\":2.2,\"density\":0.35},\"underlay\":{\"center\":true}}]}"
                  }
                },
                "example4": {
                  "summary": "Template project (heart appliqué) → Janome JEF",
                  "value": {
                    "format": "jef",
                    "project": "{\"format\":\"threadsmith\",\"version\":1,\"name\":\"Heart appliqué\",\"hoop\":\"100x100\",\"sequence\":\"manual\",\"palette\":[{\"id\":\"silver\",\"name\":\"Silver grey\",\"hex\":\"#b9bcc0\"},{\"id\":\"magenta\",\"name\":\"Magenta\",\"hex\":\"#b5266f\"},{\"id\":\"plum\",\"name\":\"Plum\",\"hex\":\"#5b2a52\"}],\"objects\":[{\"id\":\"placement\",\"name\":\"Placement line\",\"kind\":\"path\",\"color\":\"silver\",\"d\":\"M0 30C-44 2 -30 -38 0 -16C30 -38 44 2 0 30Z\",\"stitch\":{\"type\":\"running\",\"length\":3}},{\"id\":\"tack\",\"name\":\"Tack-down\",\"kind\":\"path\",\"color\":\"magenta\",\"d\":\"M0 30C-44 2 -30 -38 0 -16C30 -38 44 2 0 30Z\",\"stitch\":{\"type\":\"running\",\"length\":2.5,\"repeats\":1}},{\"id\":\"finish\",\"name\":\"Blanket finish\",\"kind\":\"path\",\"color\":\"plum\",\"d\":\"M0 30C-44 2 -30 -38 0 -16C30 -38 44 2 0 30Z\",\"stitch\":{\"type\":\"motif\",\"motif\":\"estitch\",\"motifSize\":2.5,\"motifLength\":2.5,\"length\":3}},{\"id\":\"love\",\"name\":\"Lettering\",\"kind\":\"text\",\"color\":\"plum\",\"text\":\"love\",\"x\":0,\"y\":4,\"size\":9,\"font\":\"single\",\"align\":\"center\",\"stitch\":{\"type\":\"satin\",\"width\":1.4,\"density\":0.35},\"underlay\":{\"center\":true}}]}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadsmithStitchFileResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "ThreadsmithStitchFileInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "format": {
            "title": "File format",
            "type": "string",
            "enum": [
              "dst",
              "pes",
              "jef",
              "exp"
            ],
            "default": "dst"
          },
          "stitches": {
            "title": "Stitch list (JSON)",
            "description": "[[x, y], [x, y, \"jump\"], [x, y, \"trim\"], [x, y, \"color\"], …] in mm (y down), or {\"cmds\": […], \"colors\": [{\"name\", \"hex\"}]} from threadsmith-digitize.",
            "type": "string",
            "maxLength": 8000000
          },
          "project": {
            "title": "Or: Threadsmith project JSON",
            "description": "If given, the project is digitized first.",
            "type": "string",
            "maxLength": 2000000
          },
          "label": {
            "title": "Design label (DST/PES header, 8 characters)",
            "type": "string",
            "maxLength": 16,
            "default": "DESIGN"
          }
        },
        "required": []
      },
      "ThreadsmithStitchFileResult": {
        "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": [
              "format",
              "filename",
              "bytes",
              "records",
              "stitchRecords",
              "jumpRecords",
              "colorChanges",
              "splitStitches",
              "verified",
              "maxErrorMm",
              "sha256",
              "artifactUrl",
              "base64",
              "firstRecords"
            ],
            "properties": {
              "format": {
                "type": "string",
                "enum": [
                  "dst",
                  "exp",
                  "pes",
                  "jef"
                ]
              },
              "filename": {
                "type": "string"
              },
              "bytes": {
                "type": "integer"
              },
              "records": {
                "type": "integer"
              },
              "stitchRecords": {
                "type": "integer"
              },
              "jumpRecords": {
                "type": "integer"
              },
              "colorChanges": {
                "type": "integer"
              },
              "splitStitches": {
                "type": "integer",
                "description": "Stitches longer than the format limit that were split into several records."
              },
              "verified": {
                "type": "boolean",
                "description": "The written file was decoded again and every stitch landed within 0.08 mm of the input."
              },
              "maxErrorMm": {
                "type": "number"
              },
              "sha256": {
                "type": "string"
              },
              "artifactUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "base64": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "File content (only when no artifact store is available or the file is ≤ 64 KiB)."
              },
              "header": {
                "type": "object"
              },
              "firstRecords": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "machineThreads": {
                "type": "array",
                "description": "PES/JEF: the machine palette colour chosen for every colour block (nearest match).",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "name": {
                      "type": "string"
                    },
                    "hex": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}