Loading repository data…
Loading repository data…
hajdu-patrik / repository
An automated 3D slicing and pricing API built with Node.js and Python that seamlessly converts various 2D and 3D file formats (including CAD, images, and vectors) into ready-to-print models using PrusaSlicer or OrcaSlicer by your choice. It provides automated part orientation, slicing, and cost estimation for both FDM and SLA printing technologies.
An automated 3D slicing and pricing API built with Node.js and Python that converts supported 3D model and CAD inputs into printable outputs with validated pricing.
Built for zero-downtime rollout, this API now supports two slicer engines through separate public endpoints.
| Category | Extensions |
|---|---|
| Direct 3D | .stl, .obj, .3mf |
| NURBS / CAD | .stp, .step, .igs, .iges, .ply |
| Archive | .zip |
Admin-protected endpoints require:
x-api-key: <ADMIN_API_KEY>Public endpoints do not require admin key.
GET /healthGET /pricingPOST /prusa/slicePOST /orca/sliceGET /openapi.jsonGET /docsGET /GET /health/detailedPOST /pricing/FDMPOST /pricing/SLAPATCH /pricing/:technology/:materialDELETE /pricing/:technology/:materialGET /admin/output-filesGET /admin/download/:fileNameapp/server.js - Express bootstrap, startup guards, helmet/cors, request-id propagation, docs mounting, routes, and global error handling.app/config/constants.js - runtime defaults, layer presets, limits, and extension groups.app/config/paths.js - root-scoped runtime path resolution (input/, output/, configs/) and directory creation.app/config/python.js - secure Python executable resolver (PYTHON_EXECUTABLE + VIRTUAL_ENV fallbacks).app/middleware/rateLimit.js - in-memory IP throttling for slice and admin routes (Retry-After aware responses).app/middleware/requireAdmin.js - timing-safe x-api-key guard + unauthorized attempt logging.app/middleware/errorHandler.js - centralized request/upload/parser error normalization.app/routes/slice.routes.js - POST /prusa/slice, POST /orca/slice with rate-limit and single-file upload middleware.app/routes/pricing.routes.js - public pricing read + admin pricing mutations.app/routes/system.routes.js - health endpoints and admin artifact listing/download endpoints.app/services/pricing.service.js - pricing load/save/migration/lookup logic.app/services/admin-output.service.js - validated admin output listing/download helpers and ALL ZIP bulk limit checks.app/services/slice.service.js - end-to-end slicing orchestrator and queue error mapping.app/services/slice/command.js - subprocess execution via execFile with timeout and optional debug logs.app/services/slice/common.js - output naming, isolated Orca output dirs, cleanup utilities.app/services/slice/engine.js - slicer argument construction (Prusa vs Orca).app/services/slice/errors.js - error classification and API error responses.app/services/slice/input-processing.js - conversion/orientation preprocessing pipeline.app/services/slice/model-stats.js - metadata/stat parsing from slicer outputs.app/services/slice/number-utils.js - shared numeric parser helpers.app/services/slice/options.js - strict request option validation/parsing.app/services/slice/profiles.js - profile selection, runtime profile generation, build-volume limits.app/services/slice/queue.js - FIFO queue + per-client fairness + timeout enforcement.app/services/slice/transform.js - transform planning/execution and bounds validation.app/services/slice/value-parsers.js - safe parsing and profile filename sanitization.app/services/slice/zip.js - ZIP safety inspection and safe extraction.app/utils/client-ip.js - trust-proxy-aware client IP normalization.app/utils/logger.js - structured processing error logging.app/docs/swagger-docs.js - OpenAPI generation for /docs and /openapi.json.Both slicing endpoints accept multipart/form-data with required file field:
choosenFileOptional fields:
layerHeightmaterialinfill (0-100)sizeUnit (mm or inch)keepProportions (true/false, default true)targetSizeX, targetSizeY, targetSizeZ (target dimensions in selected unit)scalePercent (uniform scale; cannot be combined with targetSizeX/Y/Z)rotationX, rotationY, rotationZ (degrees)printerProfile (profile override filename)processProfile (Orca only process profile override filename)POST /prusa/sliceUses prusa-slicer.
layerHeight:
0.025, 0.05 → SLA0.1, 0.2, 0.3 → FDMlayerHeight values outside 0.025, 0.05, 0.1, 0.2, 0.3keepProportions=true)keepProportions=false)min/max build volume)printerProfile from configs/prusaExample:
curl -X POST http://localhost:3000/prusa/slice \
-H "Accept: application/json" \
-F "choosenFile=@/path/to/model.stl" \
-F "layerHeight=0.2" \
-F "material=PLA" \
-F "infill=20" \
-F "sizeUnit=mm" \
-F "keepProportions=true" \
-F "targetSizeZ=120"
POST /orca/sliceUses orca-slicer.
FDM processinglayerHeight: 0.1, 0.2, 0.3.env via ORCA_MACHINE_PROFILE (default: Bambu_P1S_0.4_nozzle.json)layerHeight (0.1/0.2/0.3) and can be overridden via .env:
ORCA_PROCESS_PROFILE_0_1ORCA_PROCESS_PROFILE_0_2ORCA_PROCESS_PROFILE_0_3printerProfile → machine profile from configs/orcaprocessProfile → process profile from configs/orcasizeUnit, keepProportions, targetSizeX/Y/Z, scalePercent, rotations)Example:
curl -X POST http://localhost:3000/orca/slice \
-H "Accept: application/json" \
-F "choosenFile=@/path/to/model.stl" \
-F "layerHeight=0.2" \
-F "material=PLA" \
-F "infill=20" \
-F "printerProfile=Bambu_P1S_0.4_nozzle.json" \
-F "processProfile=FDM_0.2mm.json" \
-F "sizeUnit=inch" \
-F "keepProportions=false" \
-F "targetSizeX=8.0" \
-F "targetSizeY=8.0" \
-F "targetSizeZ=5.0"
{
"success": true,
"slicer_engine": "prusa",
"technology": "FDM",
"material": "PLA",
"infill": "20%",
"profiles": {
"prusa_profile": "FDM_0.2mm.ini"
},
"model_transform": {
"size_unit": "mm",
"keep_proportions": true,
"requested_size": {
"x": null,
"y": null,
"z": 120
},
"scale_percent": null,
"scale_factors": {
"x": 1.5,
"y": 1.5,
"z": 1.5
},
"rotation_deg": {
"x": 0,
"y": 0,
"z": 0
},
"original_dimensions_mm": {
"x": 80,
"y": 60,
"z": 80
},
"final_dimensions_mm": {
"x": 120,
"y": 90,
"z": 120
}
},
"build_volume_limits_mm": {
"min": {
"x": 1,
"y": 1,
"z": 1
},
"max": {
"x": 256,
"y": 256,
"z": 210
},
"source_profile": "FDM_0.2mm.ini"
},
"hourly_rate": 800,
"stats": {
"print_time_seconds": 5400,
"print_time_readable": "1h 30m",
"material_used_m": 12.45,
"object_height_mm": 45.2,
"estimated_price_huf": 1350
}
}
INVALID_LAYER_HEIGHTINVALID_LAYER_HEIGHT_FOR_ENGINEINVALID_LAYER_HEIGHT_FOR_TECHNOLOGYINVALID_MATERIAL_FOR_TECHNOLOGYMATERIAL_TECHNOLOGY_MISMATCHRATE_LIMIT_EXCEEDEDADMIN_RATE_LIMIT_EXCEEDEDINVALID_SOURCE_ARCHIVEINVALID_SOURCE_GEOMETRYUNSUPPORTED_FILE_FORMATORCA_PROFILE_INCOMPATIBLEINVALID_SIZE_UNITINVALID_KEEP_PROPORTIONSINVALID_SIZE_OPTIONSINVALID_ROTATION_OPTIONSCONFLICTING_SIZE_OPTIONSINVALID_PROFILE_NAMEPROFILE_NOT_FOUNDMODEL_DIMENSIONS_UNAVAILABLEMODEL_OUT_OF_PRINTER_BOUNDSFILE_PROCESSING_TIMEOUTSLICE_QUEUE_FULLSLICE_QUEUE_CLIENT_LIMITSLICE_QUEUE_TIMEOUTQUEUE_INTERNAL_ERRORINTERNAL_PROCESSING_ERRORRATE_LIMIT_EXCEEDED -> HTTP 429, includes Retry-After and retryAfterSeconds.ADMIN_RATE_LIMIT_EXCEEDED -> HTTP 429, includes Retry-After and retryAfterSeconds.SLICE_QUEUE_FULL -> HTTP 503.SLICE_QUEUE_CLIENT_LIMIT -> HTTP 429.SLICE_QUEUE_TIMEOUT -> HTTP 503.FILE_PROCESSING_TIMEOUT -> HTTP 422.GET /pricingReturns full pricing object.
POST /pricing/FDM / POST /pricing/SLA (admin)Create new material for selected technology.
{
"material": "ASA",
"price": 1200
}
PATCH /pricing/:technology/:material (admin)Update existing material price only.
{
"price": 950
}
DELETE /pricing/:technology/:material (admin)Delete existing material from selected technology.
GET /admin/output-files (admin)Lists generated .gcode / .sl1 files from output/.
{
"success": true,
"total": 2,
"files": [
{
"fileName": "model-output-1741285245000.gcode",
"downloadUrl": "/admin/download/model-output-1741285245000.gcode",
"sizeBytes": 182734,
"createdAt": "2026-03-05T10:07:25.000Z",
"modifiedAt": "2026-03-05T10:07:27.000Z"
},
{
"fileName": "model-output-1741285301000.sl1",
"downloadUrl": "/admin/download/model-output-1741285301000.sl1",
"sizeBytes": 941282,
"createdAt": "2026-03-05T10:08:21.000Z",
"modifiedAt": "2026-03-05T10:08:24.000Z"
}
]
}
Generated artifacts are stored with the following convention for clarity and traceability:
InputName-output-<timestamp>.gcode