HandyLay API

HandyLay publishes one public HTTP address that plans a tile or floor-panel layout for a room you describe. It answers with the number of tiles the layout needs, split into whole and cut, how much of the material ends up as offcut, a scale drawing, and a link that opens the finished plan in the planner. No key and no account.

The whole API is one address

A request is an ordinary GET, so it can be pasted into a browser or handed to an assistant that can fetch a page. The address below plans a 60 × 60 cm tile with a 2 mm joint in a 420 × 360 cm room.

GET https://handylay.app/api/plan?outline=E420 S360 W420 N360&pattern=squares&tileSize=600&joint=2

A room with a notch or an alcove is written the same way, with a longer walk. This example is an L-shape with a 40 × 40 cm pillar in the middle, laid in herringbone from 90 × 600 mm planks.

GET https://handylay.app/api/plan?outline=E500 S300 W200 S200 W300 N500&subtract=200,150,40,40&pattern=herringbone&tileWidth=90&tileHeight=600

The same fields are accepted as a JSON body on POST, if calling it from code is more convenient.

POST /api/plan

Rooms in centimetres, tiles in millimetres

Room dimensions and the layout origin are given in centimetres; tile sizes and the joint width in millimetres. The split follows where the numbers come from: walls are measured with a tape, and a tile is read off a manufacturer's spec sheet.

A mistaken unit passes without complaint, because a 20 mm tile is as valid as a 200 mm one. When a result looks absurd, that is usually the first thing to check.

A room is described by walking its walls

The outline parameter lists the walls in the order you pass them. Each wall is a direction and a length in centimetres: E right, S down, W left, N up. A 420 × 360 cm rectangle is written E420 S360 W420 N360.

The walk has to come back to where it started, and the response says how far off it is when it does not. An L-shape is E500 S300 W200 S200 W300 N500, and any other shape made of straight walls is built by adding further segments. A wall at an angle is written as A bearing colon length, where the bearing is degrees clockwise from east.

Pillars, shafts and other cutouts are taken out with rectangles in the subtract parameter. A room that no walk describes can be given directly as a list of vertices in the polygon parameter.

Everything but the room description is optional

Names outside the list below are passed to the pattern as its own parameters, such as tileWidth for herringbone. Where to get that list is covered in the section on patterns.

NameMeaning
outlineThe room's walls in the order they are walked, e.g. E420 S360 W420 N360.
polygonOutline vertices as x,y pairs separated by spaces. An alternative to outline.
holesHoles in the floor, written like polygon; separate rings with a semicolon.
subtractRectangular cutouts as x,y,width,height in centimetres, separated by semicolons.
patternThe layout to lay. Defaults to squares.
jointJoint width in millimetres. Defaults to the pattern's own.
colorOne hex colour for every tile of the motif.
gapColorJoint colour, in hex.
startLayout origin as x,y in centimetres. This is the parameter that decides how the cuts fall along the walls.
widthWidth of the drawing in pixels.
wallsDraws the wall band and the wall lengths around the room. On by default.
formatjson returns the numbers, svg the drawing itself.
inlineSvgAdds the drawing to the JSON response.
creditThe handylay.app credit in the margin of the drawing. On by default.
linkCreates the planner link. Turn it off while comparing options.
langLanguage for pattern names and the planner link: en, pl, es or zh.

The response carries numbers, not only a picture

JSON comes back by default. The drawing is an address in it rather than its contents, so the response can be read without scrolling past a few kilobytes of markup. The inlineSvg parameter embeds it, and format=svg returns the image on its own from the same address.

The warnings field is the part worth acting on before showing the plan to anyone. It reports slivers along the walls, or waste running high. Moving start by half a tile and asking again usually settles it.

NameMeaning
surface.areaM2Floor area once cutouts are taken out, in square metres.
surface.perimeterMRoom perimeter in metres.
surface.wallsCmLength of each wall in centimetres, in order.
pattern.parametersThe pattern parameters actually used, defaults included.
pattern.jointMmJoint width in millimetres.
pattern.startCmLayout origin in centimetres.
tiles.totalTiles to buy for this layout.
tiles.wholeOf those, laid whole.
tiles.cutOf those, needing a cut.
tiles.wastePercentShare of the bought material that ends up as offcut.
tiles.narrowestCutMmShortest side of any cut piece. A small number means a sliver.
tiles.sliverCountCut tiles coming out under a tenth of a whole tile.
warningsWhat is wrong with this layout, and what usually fixes it.
svgUrlThe same drawing at an address of its own.
plannerUrlOpens the finished plan in the planner, where the starting point can be dragged.
GET https://handylay.app/api/plan?outline=E420 S360 W420 N360&pattern=bricks&format=svg

Patterns describe their own parameters

Each pattern takes its own parameters: herringbone accepts tileWidth, tileHeight and direction. Rather than guessing a name, fetch them from a separate address that lists every pattern with its ranges, defaults and translated labels.

GET /api/plan/patterns

Patterns available right now:

  • squares-pattern
  • bricks-pattern
  • vertical-bricks-pattern
  • hexagons-pattern
  • flat-top-hexagons-pattern
  • diamonds-pattern
  • rhombus-pattern
  • isometric-cubes-pattern
  • herringbone-pattern
  • chevron-pattern

No key, but there are limits

The endpoint is open because an assistant following a link has nowhere to keep a key. What bounds the cost is the input limits: at most 20,000 tiles in one plan, 64 walls in a walk, 32 cutouts, and a ceiling on room size. Passing any of them returns a message saying what to send instead.

Requests from one address are capped at thirty a minute. When comparing several starting points, add link=false, because every request that returns a planner link stores a project. Take the link from the call whose plan you actually pass on.

Two addresses carry the machine-readable description

The OpenAPI description is what to point an assistant or your own code at when wiring the endpoint up as a tool. The llms.txt file summarises what HandyLay is and what this API does, in a form meant to be read by a model.