Parse engineering files. Optimize material cutting. Export CNC-ready output.
https://api.tetricut.com/v1
curl -X POST https://api.tetricut.com/v1/account/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com", "name":"Your Name", "password":"secret"}'
Save the api_key from the response. It's shown only once.
curl -X POST https://api.tetricut.com/v1/parse/dxf \
-H "X-API-Key: na_live_YOUR_KEY" \
-F "file=@your_part.dxf"
curl -X POST https://api.tetricut.com/v1/solve/cut-1d \
-H "X-API-Key: na_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"stocks": [{"id": "6m-bar", "length": 6000, "quantity": 20, "cost": 25}],
"pieces": [
{"id": "piece-A", "length": 2500, "quantity": 8},
{"id": "piece-B", "length": 1200, "quantity": 15}
],
"kerf": 3
}'
Pass your API key via the X-API-Key header or ?api_key= query parameter.
| Param | Type | Description |
|---|---|---|
file | multipart/form-data | DXF file (max 10MB) |
{
"status": "success",
"data": {
"name": "bracket",
"bounds": {"min_x": 0, "min_y": 0, "max_x": 150.5, "max_y": 200.3},
"dimensions": {"width": 150.5, "height": 200.3, "unit": "mm"},
"area": 12500.75,
"perimeter": 680.2,
"geometry": {
"exterior": [[0,0], [150.5,0], [150.5,200.3], [0,200.3], [0,0]],
"holes": [[[50,50], [60,50], [60,60], [50,60], [50,50]]]
},
"layers": ["0", "OUTER", "HOLES"],
"cut_paths": [...],
"bend_lines": null,
"entity_count": 12,
"has_holes": true,
"hole_count": 1
},
"meta": {"processing_time_ms": 45, "engine_version": "1.0.0"}
}
| Param | Type | Description |
|---|---|---|
file | multipart/form-data | DXF file |
width | query int | SVG width in px (default: 800) |
height | query int | SVG height in px (default: 600) |
stroke_color | query string | Hex color (default: #000000) |
background | query string | Background color (default: #ffffff) |
{
"parts": [
{
"id": "bracket",
"exterior": [[0,0],[150,0],[150,80],[0,80],[0,0]],
"holes": [[[40,20],[110,20],[110,60],[40,60],[40,20]]],
"quantity": 10
},
{
"id": "plate",
"exterior": [[0,0],[200,0],[200,200],[0,200],[0,0]],
"quantity": 4
}
],
"sheet": {"width": 1220, "height": 2440},
"config": {
"spacing": 3.0,
"edge_margin": 5.0,
"rotation_step": 90,
"kerf": 0.2
}
}
| Field | Type | Description |
|---|---|---|
parts[].id | string | Unique part identifier |
parts[].exterior | float[][] | Closed polygon coordinates [[x,y], ...] |
parts[].holes | float[][][] | Optional holes in the polygon |
parts[].quantity | int | Number of copies to nest |
sheet.width | float | Sheet width in mm |
sheet.height | float | Sheet height in mm |
config.spacing | float | Gap between parts (default: 3mm) |
config.kerf | float | Tool cutting width (default: 0) |
config.rotation_step | float | Rotation angles: 90 = 0/90 only, 45 = 0/45/90 |
{
"status": "success",
"data": {
"summary": {
"sheets_used": 2,
"total_parts": 14,
"placed_parts": 14,
"unplaced_parts": 0,
"total_utilization": 68.5,
"total_waste_percent": 31.5
},
"sheets": [{
"index": 0,
"utilization": 72.3,
"placements": [{
"part_id": "bracket",
"instance": 0,
"x": 5.0, "y": 5.0,
"rotation": 0,
"bounds": {"min_x": 5, "min_y": 5, "max_x": 155, "max_y": 85}
}]
}],
"unplaced": []
},
"meta": {"processing_time_ms": 1200, "engine_version": "1.0.0"}
}
{
"stocks": [
{"id": "6m-bar", "length": 6000, "quantity": 50, "cost": 25.00},
{"id": "3m-bar", "length": 3000, "quantity": 100, "cost": 14.00}
],
"pieces": [
{"id": "long-piece", "length": 2500, "quantity": 8},
{"id": "medium", "length": 1200, "quantity": 15},
{"id": "short", "length": 800, "quantity": 24}
],
"kerf": 3,
"optimize": "waste"
}
| Field | Type | Description |
|---|---|---|
stocks[].id | string | Stock identifier |
stocks[].length | float | Stock length in mm |
stocks[].quantity | int | Available quantity |
stocks[].cost | float | Cost per stock unit |
pieces[].id | string | Piece identifier |
pieces[].length | float | Required piece length |
pieces[].quantity | int | Number needed |
kerf | float | Blade/saw width per cut (default: 0) |
optimize | string | "waste" or "cost" |
{
"status": "success",
"data": {
"summary": {
"stocks_used": 11,
"total_stock_length": 66000,
"total_cut_length": 57100,
"total_waste": 8900,
"waste_percent": 13.3,
"total_cost": 275.00,
"all_pieces_placed": true
},
"layouts": [{
"stock_id": "6m-bar",
"stock_index": 0,
"cuts": [
{"piece_id": "long-piece", "length": 2500, "position": 0},
{"piece_id": "long-piece", "length": 2500, "position": 2503},
{"piece_id": "short", "length": 800, "position": 5006}
],
"used_length": 5806,
"waste": 194,
"utilization": 96.8
}],
"unplaced": []
},
"meta": {"processing_time_ms": 2, "engine_version": "1.0.0"}
}
{
"sheet_width": 1220,
"sheet_height": 2440,
"placements": [
{
"exterior": [[5,5],[155,5],[155,85],[5,85],[5,5]],
"holes": [],
"x": 5, "y": 5, "rotation": 0
}
],
"config": {
"feed_rate": 1000,
"travel_rate": 3000,
"laser_power": 100,
"kerf": 0.2
}
}
All errors follow this format:
{
"detail": {
"code": "ERROR_CODE",
"message": "Human-readable description"
}
}
| Code | HTTP | Meaning |
|---|---|---|
AUTH_REQUIRED | 401 | No API key provided |
INVALID_API_KEY | 401 | Key is invalid or revoked |
RATE_LIMIT_EXCEEDED | 429 | Too many requests per minute |
USAGE_LIMIT_EXCEEDED | 402 | Monthly quota reached |
INVALID_DXF | 400 | File is not valid DXF |
INVALID_INPUT | 400 | Bad request data |
FILE_TOO_LARGE | 413 | File exceeds 10MB |
Every response includes:
| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Requests remaining |
X-RateLimit-Reset | Unix timestamp when limit resets |
Coming soon: Python, JavaScript, and Go client libraries.
For now, use any HTTP client. The API accepts standard JSON and multipart/form-data.
TetriCut API by tetricut.com