CutWeaver Public API Contract v1¶
This document is the canonical public contract for the hosted HTTP API under /api/v1/....
It is also the reference JSON shape for integrations that call the versioned solve surface through the C API.
Scope¶
Version v1 defines:
- canonical request field names,
- success and error envelopes,
- request and transport limits,
- additive versioning rules for the public service surface.
Request payloads are strict in v1: unknown, legacy, or snake_case aliases are rejected with invalid_schema.
Conventions¶
- All field names are camelCase.
- All linear dimensions are integers in millimetres.
- Areas are square millimetres.
- Request bodies use
application/json. - Every JSON response includes
contractVersion: "v1". - Supported public strategies in
v1aregreedyandalns.
Success Envelope¶
{
"ok": true,
"contractVersion": "v1",
"result": { }
}
When strategy is alns, the response may also include a top-level alnsStats object.
When includeSvg is true, the response may also include a top-level svg array.
Error Envelope¶
{
"ok": false,
"contractVersion": "v1",
"error": {
"code": "string",
"message": "human-readable"
}
}
For domain validation failures, error.validationErrors is included.
{
"ok": false,
"contractVersion": "v1",
"error": {
"code": "validation_failed",
"message": "Input validation failed",
"validationErrors": [
{
"code": "InvalidDimension",
"fieldPath": "pieces[0]",
"message": "Piece width must be positive"
}
]
}
}
Solve Request¶
Top-level fields¶
| Field | Type | Required | Notes |
|---|---|---|---|
pieces |
array | yes | Array of piece specifications |
sheets |
array | yes | Array of stock sheet specifications |
params |
object | no | Global cutting parameters |
builderConfig |
object | no | Advanced greedy/tree-builder knobs |
strategy |
"greedy" \| "alns" |
no | Defaults to "greedy" |
alnsConfig |
object | no | Parsed when present; used for strategy = "alns" |
includeSvg |
boolean | no | If true, response includes top-level svg array |
Legacy roots such as layout, production_params, and config are not supported in v1.
pieces[]¶
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
originalIndex |
int | no | array index | Returned in pieceId and unplacedIndices |
width |
int | yes | - | Piece width |
height |
int | yes | - | Piece height |
quantity |
int | no | 1 |
Number of identical pieces |
canRotate |
bool | no | true |
Piece-level rotation permission |
priority |
int | no | 0 |
Higher priority increases penalty when unplaced |
sheets[]¶
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
width |
int | yes | - | Sheet width |
height |
int | yes | - | Sheet height |
kerfWidth |
int | no | 0 |
Sheet-specific kerf width |
marginLeft |
int | no | 0 |
Reserved margin on the left edge |
marginRight |
int | no | 0 |
Reserved margin on the right edge |
marginTop |
int | no | 0 |
Reserved margin on the top edge |
marginBottom |
int | no | 0 |
Reserved margin on the bottom edge |
quantity |
int | no | 1 |
Expanded into repeated concrete sheets by the input layer |
defects |
array | no | [] |
Rectangular forbidden zones |
Each defects[] entry uses:
| Field | Type | Required | Notes |
|---|---|---|---|
x |
int | yes | Defect origin X |
y |
int | yes | Defect origin Y |
width |
int | yes | Defect width |
height |
int | yes | Defect height |
params¶
If omitted, the input layer uses the default glass profile.
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
maxStages |
int | no | 5 |
0 means unlimited stages |
alternateOrientation |
bool | no | true |
Alternate cut direction by stage |
firstCutVertical |
bool | no | true |
First cut direction |
kerfWidth |
int | no | 0 |
Global kerf width |
minTrimSize |
int | no | 0 |
Minimum accepted trim fragment |
marginLeft |
int | no | 0 |
Accepted by the v1 envelope |
marginRight |
int | no | 0 |
Accepted by the v1 envelope |
marginTop |
int | no | 0 |
Accepted by the v1 envelope |
marginBottom |
int | no | 0 |
Accepted by the v1 envelope |
allowRotation |
bool | no | true |
Global rotation permission |
params must not contain ALNS fields. For example, params.strategy, params.timeLimitMs, and params.threadCount are rejected.
builderConfig¶
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
beamWidth |
int | no | 10 |
Beam width per level |
beamWidthAtRoot |
int | no | 50 |
Beam width on the root level |
maxBuildCalls |
int | no | 0 |
0 means adaptive budget |
maxRecursionDepth |
int | no | 500 |
Safety limit for tree depth |
scoreNoise |
double | no | 0.0 |
Score diversification noise |
noiseSeed |
uint64 | no | 0 |
Seed for builder noise |
alnsConfig¶
All fields are optional. The public v1 parser accepts the following keys:
| Field | Type | Notes |
|---|---|---|
maxIterations |
int | Maximum number of ALNS iterations |
maxNoImprove |
int | Stop after N iterations without best improvement |
timeLimitMs |
double | Time budget in milliseconds |
numThreads |
int | 1 = single-threaded, 0 = hardware concurrency |
fullRebuildProbability |
double | Probability of full rebuild instead of partial repair |
earlyStopThreshold |
double | Multi-thread early-stop threshold |
earlyStopMinIter |
int | Earliest iteration for multi-thread early-stop |
coolingRate |
double | Simulated annealing cooling factor |
initialAcceptProb |
double | Initial probability for accepting worse candidates |
minTemperature |
double | Lower temperature floor |
minDestructionRate |
double | Minimum destruction fraction |
maxDestructionRate |
double | Maximum destruction fraction |
scoreNoise |
double | ALNS diversification noise |
seed |
int64 | Random seed for deterministic runs |
unplacedPenalty |
int64 | Cost penalty for unplaced pieces |
priorityPenalty |
int64 | Additional penalty for unplaced priority |
cutPenalty |
int64 | Penalty per cut |
directionChangePenalty |
int64 | Penalty for cut-direction changes |
liquidOffcutBonus |
double | Bonus for reusable offcuts |
reheatingInterval |
int | Stagnation interval before reheating |
reheatingFactor |
double | Temperature multiplier during reheating |
maxReheats |
int | Maximum reheating events |
returnToBestAfter |
int | Stagnation threshold before return-to-best |
returnToBestProb |
double | Probability of return-to-best |
weightDecay |
double | Operator-weight EMA decay |
initialOperatorWeight |
double | Initial weight of destroy operators |
minOperatorWeight |
double | Lower bound for operator weight |
maxNoBestImproveMs |
double | Optional time-based early stop |
maxInterSheetTransfersPerIter |
int | Local-search transfer attempts |
maxTreeOperatorsPerIter |
int | Tree-operator attempts |
repairStrategy |
string | fullRebuild, treeNative, or treeNativeRegret |
Successful Result Payload¶
result¶
| Field | Type | Notes |
|---|---|---|
sheetsUsed |
int | Number of concrete sheets used |
totalPlaced |
int | Number of placed piece instances |
totalUsedArea |
int64 | Sum of placed piece area |
totalWasteArea |
int64 | Sum of waste area |
totalUnplacedPriority |
int64 | Total priority penalty of unplaced pieces |
unplacedIndices |
array | originalIndex values that were not placed |
sheets |
array | Per-sheet result objects |
result.sheets[]¶
| Field | Type | Notes |
|---|---|---|
sheetIndex |
int | Index of the concrete sheet instance |
placedCount |
int | Number of placed pieces on this sheet |
usedArea |
int64 | Used area on this sheet |
wasteArea |
int64 | Waste area on this sheet |
largestOffcut |
int64 | Largest remaining offcut area |
maxDepth |
int | Maximum depth of the cut tree |
sheetRotated |
bool | Whether the sheet was rotated |
utilization |
double | Used area divided by sheet area |
placements |
array | Flattened piece placements |
cutTree |
object or null | Nested cut tree for normal-depth cases |
cutTreeFlat |
array | Flat cut-tree fallback for deep trees |
result.sheets[].placements[]¶
| Field | Type | Notes |
|---|---|---|
pieceId |
int | originalIndex of the placed piece |
width |
int | Final placed width |
height |
int | Final placed height |
x |
int | Placement origin X |
y |
int | Placement origin Y |
rotated |
bool | Whether the piece was rotated |
result.sheets[].cutTree¶
cutTree is a nested object when the tree depth is within the safe JSON limit.
| Field | Type | Notes |
|---|---|---|
type |
string | cut, piece, or waste |
x |
int | Absolute X coordinate of the node region |
y |
int | Absolute Y coordinate of the node region |
width |
int | Region width |
height |
int | Region height |
direction |
string | H or V |
stage |
int | Stage number |
depth |
int | Tree depth |
kerfSize |
int | Kerf consumed by this split |
piece |
object or null | Piece placement object for type = piece |
child |
object or null | First child region |
next |
object or null | Sibling region after the cut |
When piece is present inside cutTree, it uses:
| Field | Type | Notes |
|---|---|---|
pieceId |
int | originalIndex |
width |
int | Final width |
height |
int | Final height |
x |
int | Placement X |
y |
int | Placement Y |
rotated |
bool | Rotation flag |
priority |
int | Piece priority |
result.sheets[].cutTreeFlat[]¶
cutTreeFlat is used when the nested tree would become too deep for safe JSON serialization.
| Field | Type | Notes |
|---|---|---|
type |
string | cut, piece, or waste |
width |
int | Region width |
height |
int | Region height |
direction |
string | H or V |
stage |
int | Stage number |
depth |
int | Tree depth |
kerfSize |
int | Kerf consumed by this split |
piece |
object or null | Piece payload identical to cutTree.piece |
childIndex |
int | Index of the child node in the same array |
nextIndex |
int | Index of the sibling node in the same array |
Optional Top-level Extensions¶
alnsStats¶
Returned only when the request uses strategy: "alns".
| Field | Type | Notes |
|---|---|---|
iterations |
int | Iterations completed |
improvements |
int | Number of best-solution improvements |
elapsedMs |
double | Wall-clock solve time |
svg¶
Returned only when includeSvg is true.
| Field | Type | Notes |
|---|---|---|
svg |
string array | One SVG document per returned sheet, in sheet order |
Error Codes¶
| Code | Meaning |
|---|---|
invalid_json |
Request body is not valid JSON |
invalid_schema |
Unknown field, wrong type, or unsupported alias |
validation_failed |
Domain validation failed after parsing |
payload_too_large |
Request exceeds MAX_REQUEST_BYTES |
too_many_items |
pieces or sheets exceed MAX_ARRAY_ITEMS |
invalid_email |
POST /api/v1/request-key email is malformed |
unsupported_plan |
Public key issuance requested a non-free plan |
api_key_required |
Endpoint requires X-API-Key |
invalid_api_key |
API key is unknown or inactive |
unsupported_media_type |
Request is not application/json |
rate_limit_exceeded |
Daily or monthly hosted quota has been exhausted |
not_found |
HTTP route does not exist |
internal_error |
Unexpected server-side failure |
Hard Limits¶
| Constant | Value | Notes |
|---|---|---|
MAX_REQUEST_BYTES |
1,048,576 |
Maximum request body size in bytes |
MAX_ARRAY_ITEMS |
10,000 |
Maximum number of entries in pieces or sheets |
Strictness Rules¶
The v1 request parser rejects:
- snake_case aliases such as
alns_config, - legacy roots such as
layout,production_params, andconfig, - unsupported strategy values,
- unknown fields inside canonical objects.
Examples of request fields that are rejected in v1:
rotatableparams.kerfparams.strategyparams.threadCounthpgConfig
Versioning Policy¶
Current public version: v1.
- Additive response fields can be introduced without changing the version.
- New optional request fields require a documented additive change.
- Renaming, removing, or changing the meaning of existing fields requires a new contract version.