Paths, field names, error codes, header names and code samples stay in English: they are the contract.
Fields
The tables below are generated from the JSON Schema itself; the same schema is embedded, unchanged, in the OpenAPI document.
The descriptions in this table come from the English contract (the JSON Schema or the OpenAPI document).
Order
| Field | Type | Required | Description |
|---|
| schemaVersion | 1 | yes | — |
| idempotencyKey | string | yes | The caller's replay key for POST /cfg/v1/order (P2-09): the same key returns the same order. |
| tenantId | string | yes | — |
| configVersion | integer | yes | The tenant-config snapshot this order was priced against. Capped at 2^53−1 (one JSON text per integer, so one hash / token claim per version). |
| workflow | Workflow | yes | — |
| customerRef | string | no | Opaque reference into the merchant's own customer records. Never a name or an address. |
| customerGroup | string | no | The tenant-config customer group the price list was chosen for. |
| locale | "en" | "de" | "it" | "fr" | "pl" | "cs" | "ro" | "hu" | "es" | "hr" | yes | — |
| unit | "mm" | "cm" | "in" | yes | Display unit at ordering time; every length in this document is millimetres. |
| currency | string | yes | — |
| pricingMode | "platform" | "external" | yes | — |
| createdAt | string | yes | — |
| expiresAt | string | yes | Quote validity; equals the token's exp. |
| source | Source | yes | — |
| cutList | CutPart[] | yes | MODE-DISCRIMINATED by workflow.mode (Order.allOf). One branch today: panel2d CutPart. |
| fullSheets | FullSheetItem[] | yes | Full stock units bought uncut. MODE-DISCRIMINATED; panel2d: whole sheets. |
| hardware | HardwareLine[] | yes | Mode-independent (catalogue hardware). |
| bondedPanels | BondedPanel[] | no | Glued multi-layer panels (P5-05). MODE-DISCRIMINATED; panel2d only today. Shape may gain optional fields there; this is the v1 minimum. |
| plan | Plan | yes | MODE-DISCRIMINATED; the plan carries its own `mode` tag (= workflow.mode), covered by planHash. |
| quote | Quote | yes | — |
| shipping | OrderShipping | no | — |
| files | FileRef[] | no | — |
| signature | Signature | no | — |
Workflow
The tenant workflow this order was made in (tenant-config.v1 workflows[].id, or `default` for the implicit workflow). `mode` and `profile` are repeated so a consumer can dispatch without fetching the config; the quote token binds `id` and `mode`.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| mode | "panel2d" | yes | A BUILT mode (x-cfg-modes.built). Reserved ⇒ `mode_unavailable`; unknown ⇒ `enum`. |
| profile | "furniture" | yes | — |
Source
Provenance: which embed build collected the list, which engine version produced the plan, which config snapshot priced it.
| Field | Type | Required | Description |
|---|
| embedVersion | string | yes | — |
| engineVersion | string | yes | = plan.engineVersion (the Engine API's engineVersion). |
| configVersion | integer | yes | = $.configVersion. |
CutPart
panel2d cut-list row = Engine API ApiPart2D (name, w, h, qty, rotatable, grain, grainGroup, priority, edgeBanding, material, meta) + the order's own id, group and machining. name/qty/material are REQUIRED here (optional on the API).
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| name | string | yes | No C0/C1 control characters (audit P7-01 F1: a newline in a name wrote DXF entities). |
| w | number | yes | The size the engine was given (after the tenant's dimension convention / edging deduction were applied). |
| h | number | yes | — |
| qty | integer | yes | — |
| material | string | yes | Catalogue MaterialItem.id (the API's material partition key). |
| rotatable | boolean | no | — |
| grain | "w" | "h" | no | — |
| grainGroup | string | no | — |
| priority | boolean | no | — |
| edgeBanding | EdgeBanding | no | — |
| meta | object | no | Opaque passthrough (= ApiPart2D.meta), ≤ 2048 bytes canonical. |
| group | string | no | Room / cabinet / project the customer assigned; printed on labels and exports. |
| machining | MachiningOp[] | no | — |
EdgeBanding
Per-edge banding TYPE references (catalogue EdgingItem.id); an absent side is not banded (= ApiPart2D.edgeBanding).
| Field | Type | Required | Description |
|---|
| top | string | no | — |
| right | string | no | — |
| bottom | string | no | — |
| left | string | no | — |
MachiningOp
A machining operation on the part (catalogue MachiningType.id). `params` stays open in v1; P5-04 types its known keys additively (see params).
| Field | Type | Required | Description |
|---|
| typeId | string | yes | — |
| qty | integer | yes | — |
| params | object | no | Open object; the KNOWN keys are typed (P5-04, additive): corner, measure, xMm, yMm, diameterMm, radiusMm, lengthMm, widthMm, depthMm. Per catalogue kind: hole/hinge = corner+measure+xMm+yMm+diameterMm[+depthMm]; groove = corner(top-left|top-right)+xMm+lengthMm[+widthMm+depthMm]; radius = corner+radiusMm. Any other key stays valid. |
FullSheetItem
| Field | Type | Required | Description |
|---|
| materialId | string | yes | — |
| w | number | yes | — |
| h | number | yes | — |
| qty | integer | yes | — |
HardwareLine
| Field | Type | Required | Description |
|---|
| hardwareId | string | yes | — |
| qty | integer | yes | — |
BondedPanel
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| w | number | yes | — |
| h | number | yes | — |
| qty | integer | yes | — |
| layers | BondedLayer[] | yes | — |
| name | string | no | — |
BondedLayer
| Field | Type | Required | Description |
|---|
| materialId | string | yes | — |
| thicknessMm | number | yes | — |
Plan
The panel2d production plan as the Engine API returned it (ApiOptimize2DResponse fields), plus the `mode` tag and planHash. Numbers are the engine's own, in millimetres; sheets[].price / metrics.totalPrice are the engine's unit-less price fields, NOT money (prices live in `quote`).
| Field | Type | Required | Description |
|---|
| mode | "panel2d" | yes | The mode tag — INSIDE the plan so planHash covers it; must equal $.workflow.mode (D15). |
| engine | "heuristic" | "balanced" | "max" | yes | — |
| engineVersion | string | yes | — |
| deterministic | boolean | yes | — |
| sheets | Sheet[] | yes | — |
| metrics | Metrics2D | yes | — |
| cutPlan | array | null | yes | null when the layout is not guillotine. |
| unplaced | Unplaced2D[] | yes | — |
| warnings | string[] | yes | — |
| guillotineValid | boolean | yes | — |
| planHash | string | yes | sha256 hex of canonicalize(plan without planHash) — RFC 8785; covers `mode`. |
Sheet
= ApiSheet (types.ts).
| Field | Type | Required | Description |
|---|
| w | number | yes | — |
| h | number | yes | — |
| price | number | null | yes | The engine's unit-less per-sheet price; the issuer passes null. |
| parts | PlacedPart2D[] | yes | — |
| offcuts | Rect[] | no | — |
| material | string | no | — |
| grain | "w" | "h" | no | — |
| meta | object | no | — |
PlacedPart2D
= ApiPlacedPart2D (types.ts).
| Field | Type | Required | Description |
|---|
| name | string | yes | — |
| x | number | yes | — |
| y | number | yes | — |
| w | number | yes | — |
| h | number | yes | — |
| rotated | boolean | yes | — |
| meta | object | no | — |
Rect
= ApiRect (types.ts).
| Field | Type | Required | Description |
|---|
| x | number | yes | — |
| y | number | yes | — |
| w | number | yes | — |
| h | number | yes | — |
Metrics2D
= ApiMetrics2D (types.ts), unchanged: cutLines (collinear cuts merged), sawPasses (every strip crossed), cutLength (mm, convention-independent).
| Field | Type | Required | Description |
|---|
| sheetCount | integer | yes | — |
| yieldPct | number | yes | — |
| placed | integer | yes | — |
| total | integer | yes | — |
| cutLines | integer | yes | — |
| sawPasses | integer | yes | — |
| cutLength | number | yes | — |
| totalPrice | number | yes | — |
CutStep
= ApiCutStep (types.ts): sheet is the 0-based index into plan.sheets, step restarts at 1 per sheet, stage is the 1-based machine pass.
| Field | Type | Required | Description |
|---|
| sheet | integer | yes | — |
| step | integer | yes | — |
| axis | "h" | "v" | yes | — |
| pos | number | yes | — |
| length | number | yes | — |
| stage | integer | yes | — |
Unplaced2D
= ApiUnplaced2D (types.ts).
| Field | Type | Required | Description |
|---|
| name | string | yes | — |
| w | number | yes | — |
| h | number | yes | — |
| qty | integer | yes | — |
Quote
| Field | Type | Required | Description |
|---|
| priced | boolean | yes | false under pricingMode = external: lines carry quantities, every amount is 0. |
| lines | QuoteLine[] | yes | — |
| totals | Totals | yes | — |
| quoteToken | string | yes | See x-cfg-quote-token. The merchant's server verifies it with the tenant's key (P4-02 /quote/verify). |
QuoteLine
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| type | "cutPart" | "fullSheet" | "hardware" | "machining" | "bondedPanel" | "edging" | "surcharge" | "shipping" | "tax" | yes | — |
| label | string | yes | — |
| qty | number | yes | Pieces, sheets, metres (edging) — the line's own unit. |
| unitAmount | Money | yes | — |
| amount | Money | yes | Line total after the tenant's rounding. Σ non-tax amounts = totals.net. |
| ref | LineRef | no | — |
| meta | object | no | — |
LineRef
What the line prices. At least one id when present.
| Field | Type | Required | Description |
|---|
| partId | string | no | — |
| materialId | string | no | — |
| edgingId | string | no | — |
| hardwareId | string | no | — |
| machiningId | string | no | — |
| zoneId | string | no | — |
| ruleId | string | no | — |
| bondedPanelId | string | no | — |
Money
| Field | Type | Required | Description |
|---|
| amountMinor | integer | yes | — |
| currency | string | yes | — |
OrderShipping
Ids only — the delivery address is the merchant shop's data, not the contract's.
| Field | Type | Required | Description |
|---|
| method | "delivery" | "pickup" | yes | — |
| zoneId | string | no | — |
| pickupLocationId | string | no | — |
FileRef
| Field | Type | Required | Description |
|---|
| kind | "pdf" | "labels" | "csv" | "dxf" | "svg" | "xlsx" | "json" | yes | — |
| url | string | yes | — |
| sha256 | string | no | — |
| bytes | integer | no | — |
Signature
HMAC-SHA256 over canonicalize(order without signature). keyId names the tenant key (P2-07: derived from a master, the DB holds only the id).
| Field | Type | Required | Description |
|---|
| alg | "HMAC-SHA256" | yes | — |
| keyId | string | yes | — |
| value | string | yes | — |