openapi: 3.0.3

info:
  title: Slicer API
  version: 1.0.0
  description: |
    REST API that computes print statistics (estimated print time, filament
    usage, model volume) for 3D models (`.stl`, `.3mf`, `.obj`) by slicing
    them with the **PrusaSlicer CLI**.

    **Flow: upload → slice → return the statistics as JSON → delete.** The
    G-code is only an intermediate artifact: its footer comments are parsed
    for the statistics and then it is deleted together with the per-request
    temp directory. No user file is ever kept on the server, and no G-code
    is ever returned.

servers:
  - url: /
    description: Same origin as this documentation page

paths:
  /slice:
    post:
      summary: Slice a 3D model and return print statistics
      description: |
        Upload a model and receive the print statistics (time, filament,
        volume) as a JSON body. The G-code generated during slicing is
        discarded — it never leaves the server.

        Slicing is CPU-bound: at most `MAX_CONCURRENT_SLICES` jobs run in
        parallel, extra requests queue FIFO, and a job is killed after
        `SLICER_TIMEOUT_MS`.
      operationId: sliceModel
      tags: [Slicing]
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [model]
              properties:
                model:
                  type: string
                  format: binary
                  description: >
                    The 3D model file (`.stl`, `.3mf` or `.obj`).
                    Maximum size is `MAX_FILE_SIZE_MB` (default 100 MB).
                layerHeight:
                  type: number
                  default: 0.2
                  minimum: 0.05
                  maximum: 0.6
                  description: Layer height in millimetres.
                infill:
                  type: number
                  default: 20
                  minimum: 0
                  maximum: 100
                  description: Infill density in percent.
                infillPattern:
                  type: string
                  default: grid
                  enum:
                    - rectilinear
                    - alignedrectilinear
                    - grid
                    - triangles
                    - stars
                    - cubic
                    - line
                    - concentric
                    - honeycomb
                    - 3dhoneycomb
                    - gyroid
                    - hilbertcurve
                    - archimedeanchords
                    - octagramspiral
                    - adaptivecubic
                    - lightning
                  description: Infill pattern (case-insensitive).
                printSpeed:
                  type: number
                  default: 60
                  minimum: 5
                  maximum: 300
                  description: Print speed in mm/s.
                support:
                  type: boolean
                  default: false
                  description: Generate support material.
                material:
                  type: string
                  default: PLA
                  enum: [PLA, PETG, ABS, ASA, TPU]
                  description: Filament material (case-insensitive).
                printerProfile:
                  type: string
                  default: Prusa MK4
                  enum: [Prusa MK4, Prusa MK3S, Prusa MINI]
                  description: Target printer (case-sensitive).
      responses:
        '200':
          description: The print statistics for the sliced model.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SliceResult'
        '400':
          description: Missing file, invalid parameter value, or unknown material / pattern / profile.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { success: false, error: '"layerHeight" must be between 0.05 and 0.6' }
        '413':
          description: File exceeds `MAX_FILE_SIZE_MB`.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { success: false, error: File too large }
        '415':
          description: File extension is not `.stl`, `.3mf` or `.obj`.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { success: false, error: 'Unsupported file format ".step". Allowed: .stl, .3mf, .obj' }
        '500':
          description: PrusaSlicer failure (e.g. model outside print volume) or timeout.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { success: false, error: 'PrusaSlicer failed: Objects could not fit on the bed' }

  /health:
    get:
      summary: Liveness probe
      operationId: health
      tags: [Health]
      responses:
        '200':
          description: Service is up.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, example: ok }
                  uptime: { type: number, example: 123.45 }

components:
  schemas:
    SliceResult:
      type: object
      description: Print statistics extracted from the (discarded) G-code.
      properties:
        success: { type: boolean, example: true }
        printTimeSeconds: { type: integer, nullable: true, example: 1327 }
        printTimeFormatted: { type: string, example: 22m }
        filamentUsedMm: { type: number, nullable: true, example: 1625.04 }
        filamentUsedMeters: { type: number, nullable: true, example: 1.63 }
        filamentUsedGrams: { type: number, nullable: true, example: 4.96 }
        modelVolumeCm3: { type: number, nullable: true, example: 8 }
    Error:
      type: object
      properties:
        success: { type: boolean, example: false }
        error: { type: string, example: Something went wrong }
