{
  "openapi": "3.0.3",
  "info": {
    "termsOfService": "https://smartcut.dev/terms",
    "license": {
      "name": "MIT (specification document only — API use governed by the Terms)",
      "url": "https://github.com/jgmedialtd/smartcut-api/blob/main/LICENSE"
    },
    "x-logo": {
      "url": "https://smartcut.dev/images/logo.svg",
      "altText": "SmartCut"
    },
    "title": "SmartCut API V1",
    "version": "V1",
    "description": "A modern, performant cut cutlist optimization API\n\n**V1 Features:**\n- Saw configuration embedded in stock items\n- API coordinate system (x1/x2/y1/y2)\n- Banding split into separate objects\n\n**Note:** V1 is in maintenance mode. Consider upgrading to V2 or V3.",
    "contact": {
      "name": "SmartCut",
      "url": "https://api.smartcut.dev"
    }
  },
  "externalDocs": {
    "description": "Specification, runnable examples and MCP configuration",
    "url": "https://github.com/jgmedialtd/smartcut-api"
  },
  "paths": {
    "/calculate": {
      "post": {
        "summary": "Kick off the calculations",
        "description": "The response will contain a calculation ID, which you can then use to obtain the results. Results may not be available immediately.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalculateRequestV1"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Calculation accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jobId": {
                      "type": "number",
                      "description": "Calculation job identifier used to obtain result"
                    }
                  },
                  "required": [
                    "jobId"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "You have not been correctly authenticated."
          },
          "403": {
            "description": "Not allowed - see the response body for more information."
          },
          "429": {
            "description": "You are making requests too quickly - retry this calculation."
          },
          "500": {
            "description": "There has been a server error."
          },
          "503": {
            "description": "Server undergoing maintenance."
          }
        }
      }
    },
    "/result-ready": {
      "get": {
        "summary": "Check if the calculation has finished",
        "description": "Once you have received the job id, you can check if the result is ready by polling this end point.\nWe suggest polling every couple of seconds - please do not hammer the server with poll requests.\n\nThe time taken for a calculation to be ready depends on the calculation complexity and the server load.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Job identifier returned from /calculate"
          }
        ],
        "responses": {
          "200": {
            "description": "The result is ready."
          },
          "400": {
            "description": "Bad request."
          },
          "401": {
            "description": "You have not been correctly authenticated."
          },
          "404": {
            "description": "We cannot find your record - it may have expired or failed."
          },
          "429": {
            "description": "You are making requests too quickly - retry after the indicated time."
          },
          "500": {
            "description": "There has been a server error."
          }
        }
      }
    },
    "/result": {
      "get": {
        "summary": "Retrieve the calculation result",
        "description": "Once ready, fetch the complete optimization result including all stock layouts, cuts, and metadata.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Job identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Result retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultResponseV1"
                }
              }
            }
          },
          "404": {
            "description": "Result not found"
          },
          "500": {
            "description": "Server error"
          }
        }
      }
    },
    "/export": {
      "get": {
        "summary": "Export result in various formats",
        "description": "Export the calculation result as PDF, CSV, PTX, DXF, or SVG file.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Job ID to export"
          },
          {
            "name": "format",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "csv",
                "ptx",
                "dxf",
                "svg"
              ]
            },
            "description": "Export format"
          },
          {
            "name": "option",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "layout",
                "parts",
                "machining",
                "cuts"
              ]
            },
            "description": "Export variant: layout (full optimization), parts (parts list), machining (machining details), cuts (cut list)"
          },
          {
            "name": "units",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Unit system for DXF/SVG exports (e.g., mm, in)"
          },
          {
            "name": "numberFormat",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "decimal",
                "fraction"
              ]
            },
            "description": "Number format for PDF exports (also accepts unitType or units as aliases)"
          },
          {
            "name": "credit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Custom credit text for PDF exports (requires whiteLabel option)"
          },
          {
            "name": "cropLength",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "y",
                "n"
              ]
            },
            "description": "Crop stock length in PDF exports (y = crop, n = full length)"
          },
          {
            "name": "tables",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "y",
                "n"
              ]
            },
            "description": "Show/hide tables in PDF exports (n = hide tables)"
          }
        ],
        "responses": {
          "200": {
            "description": "File export successful"
          },
          "404": {
            "description": "Result not found"
          }
        }
      }
    },
    "/labels": {
      "post": {
        "summary": "Generate printable part labels",
        "description": "Generate customizable PDF labels for parts with options for layout, formatting, and content",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Job ID to generate labels for"
                  },
                  "units": {
                    "type": "string",
                    "enum": [
                      "pt",
                      "px",
                      "in",
                      "mm",
                      "cm",
                      "ex",
                      "em",
                      "pc"
                    ],
                    "default": "mm",
                    "description": "Measurement units for labels"
                  },
                  "format": {
                    "type": "string",
                    "default": "a4",
                    "description": "Paper size (e.g., a4, letter)"
                  },
                  "orientation": {
                    "type": "string",
                    "enum": [
                      "portrait",
                      "landscape"
                    ],
                    "default": "portrait",
                    "description": "Page orientation"
                  },
                  "cols": {
                    "type": "number",
                    "default": 4,
                    "description": "Number of columns per page"
                  },
                  "rows": {
                    "type": "number",
                    "default": 4,
                    "description": "Number of rows per page"
                  },
                  "pageMarginH": {
                    "type": "number",
                    "default": 14,
                    "description": "Horizontal page margin"
                  },
                  "pageMarginW": {
                    "type": "number",
                    "default": 14,
                    "description": "Vertical page margin"
                  },
                  "padding": {
                    "type": "number",
                    "default": 0,
                    "description": "Padding around each label"
                  },
                  "fontSize": {
                    "type": "number",
                    "default": 10,
                    "description": "Base font size"
                  },
                  "largeFontSize": {
                    "type": "number",
                    "default": 12,
                    "description": "Large text font size"
                  },
                  "banding": {
                    "type": "boolean",
                    "default": true,
                    "description": "Show edge banding information"
                  },
                  "showId": {
                    "type": "boolean",
                    "default": true,
                    "description": "Show part IDs"
                  },
                  "stockId": {
                    "type": "boolean",
                    "default": true,
                    "description": "Show stock IDs"
                  },
                  "boxes": {
                    "type": "boolean",
                    "default": true,
                    "description": "Draw boxes around labels"
                  },
                  "includeOffcuts": {
                    "type": "boolean",
                    "default": true,
                    "description": "Include offcut labels"
                  },
                  "newStockNewPage": {
                    "type": "boolean",
                    "default": false,
                    "description": "Start new page for each stock item"
                  },
                  "materials": {
                    "type": "boolean",
                    "default": true,
                    "description": "Show material names"
                  },
                  "companyName": {
                    "type": "string",
                    "description": "Company name to display on labels"
                  },
                  "numberFormat": {
                    "type": "string",
                    "enum": [
                      "decimal",
                      "fraction"
                    ],
                    "description": "Number format for dimensions"
                  },
                  "decimalPlaces": {
                    "type": "number",
                    "description": "Number of decimal places (for decimal format)"
                  },
                  "fractionRoundTo": {
                    "type": "number",
                    "description": "Fraction denominator to round to (for fraction format)"
                  }
                },
                "required": [
                  "id",
                  "companyName",
                  "numberFormat",
                  "decimalPlaces",
                  "fractionRoundTo"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Labels PDF generated successfully - returns URL to download the PDF",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string",
                  "description": "URL to download the generated labels PDF"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing ID, no parts found, etc.)"
          },
          "500": {
            "description": "Error generating labels"
          }
        }
      }
    },
    "/calls": {
      "get": {
        "summary": "Get API usage statistics",
        "description": "Retrieve your API usage metrics and limits.",
        "responses": {
          "200": {
            "description": "Usage statistics retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "used": {
                      "type": "number",
                      "description": "Calls used this month"
                    },
                    "limit": {
                      "type": "number",
                      "description": "Monthly call limit"
                    },
                    "remaining": {
                      "type": "number",
                      "description": "Remaining calls"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Example: `Authorization: <your-api-key>`. Obtain your key from https://smartcut.dev/account"
      }
    },
    "schemas": {
      "CalculateRequestV1": {
        "type": "object",
        "description": "V1 API calculation request",
        "properties": {
          "stock": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StockV1"
            },
            "description": "Array of stock items (at least 1 required)"
          },
          "stockList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StockV1"
            },
            "description": "Legacy alias for stock array"
          },
          "parts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartV1"
            },
            "description": "Array of parts to cut (at least 1 required)"
          },
          "partList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartV1"
            },
            "description": "Legacy alias for parts array"
          }
        },
        "required": []
      },
      "StockV1": {
        "type": "object",
        "description": "Stock item with embedded saw configuration (V1 format)",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Stock name or identifier"
          },
          "l": {
            "type": "number",
            "description": "Length (x-axis)",
            "minimum": 0
          },
          "w": {
            "type": "number",
            "description": "Width (y-axis)",
            "minimum": 0
          },
          "t": {
            "type": "number",
            "nullable": true,
            "description": "Thickness",
            "minimum": 0
          },
          "q": {
            "type": "integer",
            "description": "Quantity",
            "minimum": 1,
            "default": 1
          },
          "autoAdd": {
            "type": "boolean",
            "description": "Allow automatic addition of more stock",
            "default": false
          },
          "blade": {
            "type": "object",
            "description": "Saw blade configuration (embedded in V1)",
            "properties": {
              "width": {
                "type": "number",
                "description": "Blade kerf width",
                "minimum": 0
              }
            },
            "required": [
              "width"
            ]
          },
          "grain": {
            "type": "string",
            "enum": [
              "l",
              "w",
              ""
            ],
            "nullable": true,
            "description": "Grain direction (l=length, w=width)",
            "default": null
          },
          "trim": {
            "$ref": "#/components/schemas/TrimV1"
          },
          "allowExactFitShapes": {
            "type": "boolean",
            "description": "Allow shapes that exactly fit the stock dimensions",
            "default": false
          },
          "type": {
            "type": "string",
            "enum": [
              "sheet",
              "linear"
            ],
            "description": "Stock type"
          },
          "cutPreference": {
            "type": "string",
            "enum": [
              "efficiency",
              "length",
              "width",
              "beam"
            ],
            "description": "Cutting algorithm preference (embedded in V1)"
          },
          "cost": {
            "type": "number",
            "description": "Stock cost per unit",
            "minimum": 0
          }
        },
        "required": [
          "l",
          "w",
          "blade",
          "type"
        ]
      },
      "PartV1": {
        "type": "object",
        "description": "Part to be cut (V1 format)",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Part name or identifier"
          },
          "l": {
            "type": "number",
            "description": "Length (x-axis)",
            "minimum": 0
          },
          "w": {
            "type": "number",
            "description": "Width (y-axis)",
            "minimum": 0
          },
          "q": {
            "type": "integer",
            "description": "Quantity",
            "minimum": 1,
            "default": 1
          },
          "banding": {
            "$ref": "#/components/schemas/BandingV1"
          },
          "bandingType": {
            "$ref": "#/components/schemas/BandingTypeV1"
          },
          "stockLock": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "nullable": true,
            "description": "Lock part to specific stock indices",
            "default": null
          },
          "orientationLock": {
            "type": "string",
            "enum": [
              "l",
              "w",
              ""
            ],
            "nullable": true,
            "description": "Lock part orientation (l=length, w=width)",
            "default": null
          }
        },
        "required": [
          "l",
          "w"
        ]
      },
      "TrimV1": {
        "type": "object",
        "description": "Trim allowances in API coordinate system (x1/x2/y1/y2)",
        "properties": {
          "x1": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Left trim (x-axis start)"
          },
          "x2": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Right trim (x-axis end)"
          },
          "y1": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Bottom trim (y-axis start)"
          },
          "y2": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Top trim (y-axis end)"
          }
        }
      },
      "BandingV1": {
        "type": "object",
        "description": "Edge banding boolean flags (V1 format)",
        "properties": {
          "x1": {
            "type": "boolean",
            "default": false,
            "description": "Left edge"
          },
          "x2": {
            "type": "boolean",
            "default": false,
            "description": "Right edge"
          },
          "y1": {
            "type": "boolean",
            "default": false,
            "description": "Bottom edge"
          },
          "y2": {
            "type": "boolean",
            "default": false,
            "description": "Top edge"
          }
        }
      },
      "BandingTypeV1": {
        "type": "object",
        "description": "Edge banding material types (V1 format)",
        "properties": {
          "x1": {
            "type": "string",
            "nullable": true,
            "default": null,
            "description": "Left edge material"
          },
          "x2": {
            "type": "string",
            "nullable": true,
            "default": null,
            "description": "Right edge material"
          },
          "y1": {
            "type": "string",
            "nullable": true,
            "default": null,
            "description": "Bottom edge material"
          },
          "y2": {
            "type": "string",
            "nullable": true,
            "default": null,
            "description": "Top edge material"
          }
        }
      },
      "ResultResponseV1": {
        "type": "object",
        "description": "Complete V1 API response",
        "properties": {
          "jobId": {
            "type": "number",
            "description": "Job identifier"
          },
          "metadata": {
            "$ref": "#/components/schemas/MetadataV1"
          },
          "parts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultPartV1"
            },
            "description": "Placed parts with coordinates"
          },
          "stock": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultStockV1"
            },
            "description": "Used stock with layouts"
          },
          "saw": {
            "$ref": "#/components/schemas/SawV1"
          },
          "stockList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultStockV1"
            },
            "description": "Legacy field (deprecated, use \"stock\" instead)"
          },
          "partList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultPartV1"
            },
            "description": "Legacy field (deprecated, use \"parts\" instead)"
          }
        },
        "required": [
          "jobId",
          "stock",
          "parts"
        ]
      },
      "ResultStockV1": {
        "type": "object",
        "description": "Result stock item (V1 format)",
        "properties": {
          "issues": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Validation issues"
          },
          "id": {
            "type": "string",
            "description": "Stock identifier"
          },
          "name": {
            "type": "string",
            "description": "Stock name"
          },
          "l": {
            "type": "number",
            "description": "Length"
          },
          "w": {
            "type": "number",
            "description": "Width"
          },
          "t": {
            "type": "number",
            "nullable": true,
            "description": "Thickness"
          },
          "material": {
            "type": "string",
            "description": "Material name"
          },
          "cost": {
            "type": "number",
            "description": "Stock cost"
          },
          "used": {
            "type": "boolean",
            "description": "Whether stock was used"
          },
          "grain": {
            "type": "string",
            "enum": [
              "l",
              "w",
              ""
            ],
            "nullable": true
          },
          "trim": {
            "$ref": "#/components/schemas/TrimV1"
          },
          "efficiency": {
            "type": "number",
            "description": "Stock utilization efficiency (0-1)"
          },
          "blade": {
            "type": "object",
            "properties": {
              "width": {
                "type": "number"
              }
            }
          },
          "cutPreference": {
            "type": "string",
            "enum": [
              "length",
              "width",
              "efficiency",
              "beam"
            ]
          },
          "analysis": {
            "type": "object",
            "properties": {
              "partArea": {
                "type": "number"
              },
              "totalParts": {
                "type": "number"
              },
              "areaEfficiency": {
                "type": "number"
              },
              "cutLength": {
                "type": "number"
              },
              "bandingLength": {
                "type": "number"
              },
              "numberOfCuts": {
                "type": "number"
              },
              "rollLength": {
                "type": "number"
              }
            }
          },
          "q": {
            "type": "integer",
            "description": "Quantity"
          }
        },
        "required": [
          "id",
          "l",
          "w",
          "used",
          "efficiency",
          "parts"
        ]
      },
      "ResultPartV1": {
        "type": "object",
        "description": "Result part with placement coordinates (V1 format)",
        "properties": {
          "issues": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "id": {
            "type": "string"
          },
          "duplicate": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "l": {
            "type": "number"
          },
          "w": {
            "type": "number"
          },
          "t": {
            "type": "number",
            "nullable": true
          },
          "material": {
            "type": "string"
          },
          "grain": {
            "type": "string",
            "enum": [
              "l",
              "w",
              ""
            ],
            "nullable": true
          },
          "q": {
            "type": "integer"
          },
          "x": {
            "type": "number",
            "description": "X coordinate on stock"
          },
          "y": {
            "type": "number",
            "description": "Y coordinate on stock"
          },
          "r": {
            "type": "boolean",
            "description": "Rotated 90 degrees"
          },
          "stock": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              }
            }
          },
          "bandingType": {
            "type": "string"
          },
          "orientationLock": {
            "type": "string",
            "enum": [
              "l",
              "w",
              ""
            ],
            "nullable": true
          }
        },
        "required": [
          "id",
          "l",
          "w",
          "x",
          "y",
          "r",
          "stock"
        ]
      },
      "MetadataV1": {
        "type": "object",
        "description": "Calculation metadata and summary metrics (V1 format)",
        "properties": {
          "totalEfficiency": {
            "type": "number",
            "default": 0
          },
          "totalStockArea": {
            "type": "number",
            "default": 0
          },
          "totalStockUsedArea": {
            "type": "number",
            "default": 0
          },
          "totalPartsArea": {
            "type": "number",
            "default": 0
          },
          "totalOffcutsArea": {
            "type": "number",
            "default": 0
          },
          "totalStockCost": {
            "type": "number",
            "default": 0
          },
          "bandingLengthByType": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "default": {},
            "description": "Banding length per material type"
          },
          "totalBandingLength": {
            "type": "number",
            "default": 0
          },
          "totalCutLength": {
            "type": "number",
            "default": 0
          },
          "totalCuts": {
            "type": "number",
            "default": 0
          },
          "totalRollLength": {
            "type": "number",
            "description": "For roll stock types"
          }
        }
      },
      "SawV1": {
        "type": "object",
        "description": "Saw configuration (V1 format)",
        "properties": {
          "stockType": {
            "type": "string"
          },
          "bladeWidth": {
            "type": "number"
          },
          "cutPreference": {
            "type": "string"
          },
          "guillotineOptions": {
            "type": "object"
          },
          "efficiencyOptions": {
            "type": "object"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Error response",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message"
          },
          "details": {
            "type": "object",
            "description": "Detailed error information"
          }
        },
        "required": [
          "error"
        ]
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "servers": [
    {
      "url": "https://api.smartcut.dev",
      "description": "Production"
    },
    {
      "url": "http://localhost:5000",
      "description": "Local development"
    }
  ]
}