{"openapi":"3.1.0","info":{"title":"HandyLay plan API","version":"1.0.0","description":"Plans a tile or floor-panel layout for a described room and returns the tile count, the waste, a scale drawing and a link that opens the plan in the HandyLay planner. Room dimensions and the layout origin are in centimetres; tile sizes and joints are in millimetres. Call /api/plan/patterns first to see the layouts and the parameters each one takes.","contact":{"url":"https://handylay.app"}},"servers":[{"url":"https://handylay.app"}],"externalDocs":{"description":"Full reference, with worked examples","url":"https://handylay.app/en/api"},"paths":{"/api/plan":{"get":{"operationId":"planLayout","summary":"Plan a tile layout for a room","parameters":[{"name":"outline","in":"query","description":"The walls in order around the room, one token each: a direction (E, S, W, N) followed by a length in centimetres, or A<bearing>:<length> for a wall at an angle, where the bearing is degrees clockwise from east. The walk has to come back to where it started. Use this or \"polygon\", not both.","required":false,"schema":{"type":"string"},"example":"E500 S300 W200 S200 W300 N500"},{"name":"polygon","in":"query","description":"The outer wall as explicit points, \"x,y\" pairs separated by spaces, in centimetres. For a room no walk describes.","required":false,"schema":{"type":"string"},"example":"0,0 420,0 420,360 0,360"},{"name":"holes","in":"query","description":"Rings cut out of the floor, as in \"polygon\"; several rings separated by \";\".","required":false,"schema":{"type":"string"}},{"name":"subtract","in":"query","description":"Rectangles cut out of the floor — a pillar, a shaft, a hearth — as \"x,y,w,h\" in centimetres, several separated by \";\".","required":false,"schema":{"type":"string"},"example":"200,150,40,40"},{"name":"pattern","in":"query","description":"Which layout to lay.","required":false,"schema":{"type":"string","enum":["squares-pattern","squares","bricks-pattern","bricks","vertical-bricks-pattern","vertical-bricks","hexagons-pattern","hexagons","flat-top-hexagons-pattern","flat-top-hexagons","diamonds-pattern","diamonds","rhombus-pattern","rhombus","isometric-cubes-pattern","isometric-cubes","herringbone-pattern","herringbone","chevron-pattern","chevron"],"default":"squares"}},{"name":"joint","in":"query","description":"Joint (grout) width in millimetres. Defaults to the pattern’s own.","required":false,"schema":{"type":"number","minimum":0,"maximum":100},"example":3},{"name":"color","in":"query","description":"One hex colour for every tile.","required":false,"schema":{"type":"string"},"example":"#c9b79c"},{"name":"gapColor","in":"query","description":"Hex colour of the joint.","required":false,"schema":{"type":"string"}},{"name":"start","in":"query","description":"Where the layout starts on the floor, \"x,y\" in centimetres. This is the lever worth trying again: moving it changes how the cuts fall along the walls.","required":false,"schema":{"type":"string"},"example":"30,15"},{"name":"width","in":"query","description":"Width of the drawing in pixels.","required":false,"schema":{"type":"integer"},"example":900},{"name":"walls","in":"query","description":"Draw the wall band and the wall lengths.","required":false,"schema":{"type":"boolean","default":true}},{"name":"format","in":"query","description":"json for the numbers, svg for the drawing itself.","required":false,"schema":{"type":"string","enum":["json","svg"],"default":"json"}},{"name":"inlineSvg","in":"query","description":"Put the drawing in the JSON response as well.","required":false,"schema":{"type":"boolean","default":false}},{"name":"credit","in":"query","description":"Draw \"handylay.app\" in the bottom margin of the plan, linked to the planner. Set false for a plain drawing.","required":false,"schema":{"type":"boolean","default":true}},{"name":"link","in":"query","description":"Create the planner permalink. Every link stores a project, so set false while comparing starting points and leave it on for the call whose plan you hand over.","required":false,"schema":{"type":"boolean","default":true}},{"name":"lang","in":"query","description":"Language for pattern names and the planner link.","required":false,"schema":{"type":"string","enum":["en","pl","es","zh"],"default":"en"}}],"responses":{"200":{"description":"The plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"}},"image/svg+xml":{"schema":{"type":"string"}}}},"400":{"description":"The request could not be planned. \"error\" says what was wrong and what to send instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"planLayoutJson","summary":"The same, with the request as JSON","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"outline":{"type":"string"},"polygon":{"type":"array","items":{"$ref":"#/components/schemas/Point"}},"holes":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/Point"}}},"subtract":{"type":"array","items":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"}},"required":["x","y","w","h"]}},"pattern":{"type":"string","enum":["squares-pattern","squares","bricks-pattern","bricks","vertical-bricks-pattern","vertical-bricks","hexagons-pattern","hexagons","flat-top-hexagons-pattern","flat-top-hexagons","diamonds-pattern","diamonds","rhombus-pattern","rhombus","isometric-cubes-pattern","isometric-cubes","herringbone-pattern","herringbone","chevron-pattern","chevron"]},"parameters":{"type":"object","additionalProperties":true},"color":{"type":"string"},"gapColor":{"type":"string"},"gapMm":{"type":"number"},"start":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}}},"width":{"type":"integer"},"walls":{"type":"boolean"},"lang":{"type":"string"}}}}}},"responses":{"200":{"description":"The plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"}}}}}}},"/api/plan/patterns":{"get":{"operationId":"listPatterns","summary":"The available layouts and the parameters each one takes","parameters":[{"name":"lang","in":"query","description":"Language for the labels.","required":false,"schema":{"type":"string","enum":["en","pl","es","zh"],"default":"en"}}],"responses":{"200":{"description":"The layouts."}}}}},"components":{"schemas":{"Point":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2,"description":"[x, y] in centimetres."},"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"Plan":{"type":"object","properties":{"surface":{"type":"object","properties":{"areaM2":{"type":"number"},"perimeterM":{"type":"number"},"wallsCm":{"type":"array","items":{"type":"number"}},"boundingBoxCm":{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}}}}},"pattern":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parameters":{"type":"object","additionalProperties":true},"derived":{"type":"object","additionalProperties":true,"description":"Read-only figures the layout implies, such as a repeat width."},"jointMm":{"type":"number"},"startCm":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}}}}},"tiles":{"type":"object","properties":{"total":{"type":"integer","description":"Tiles to buy for this layout."},"whole":{"type":"integer"},"cut":{"type":"integer"},"wastePercent":{"type":"number","description":"Share of the bought material that ends up as offcut."},"laidAreaM2":{"type":"number"},"purchasedAreaM2":{"type":"number"},"narrowestCutMm":{"type":["number","null"],"description":"Shortest side of any cut piece. A small number means a sliver."},"sliverCount":{"type":"integer","description":"Cut tiles coming out under a tenth of a whole tile."}}},"warnings":{"type":"array","items":{"type":"string"},"description":"Things wrong with this layout that a different starting point usually fixes. Worth acting on before showing the plan to anyone: call again with a few values of \"start\" a tile apart and compare wastePercent and sliverCount."},"svg":{"type":"string","description":"Present when inlineSvg is set, or on POST."},"svgUrl":{"type":["string","null"],"description":"The same drawing as an image URL."},"plannerUrl":{"type":["string","null"],"description":"Opens this plan in the HandyLay planner, where the starting point can be dragged and each tile’s cut read off. Worth passing on to the user."}}}}}}