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=2A 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=600The same fields are accepted as a JSON body on POST, if calling it from code is more convenient.
POST /api/planRooms 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.
| Name | Meaning |
|---|---|
outline | The room's walls in the order they are walked, e.g. E420 S360 W420 N360. |
polygon | Outline vertices as x,y pairs separated by spaces. An alternative to outline. |
holes | Holes in the floor, written like polygon; separate rings with a semicolon. |
subtract | Rectangular cutouts as x,y,width,height in centimetres, separated by semicolons. |
pattern | The layout to lay. Defaults to squares. |
joint | Joint width in millimetres. Defaults to the pattern's own. |
color | One hex colour for every tile of the motif. |
gapColor | Joint colour, in hex. |
start | Layout origin as x,y in centimetres. This is the parameter that decides how the cuts fall along the walls. |
width | Width of the drawing in pixels. |
walls | Draws the wall band and the wall lengths around the room. On by default. |
format | json returns the numbers, svg the drawing itself. |
inlineSvg | Adds the drawing to the JSON response. |
credit | The handylay.app credit in the margin of the drawing. On by default. |
link | Creates the planner link. Turn it off while comparing options. |
lang | Language 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.
| Name | Meaning |
|---|---|
surface.areaM2 | Floor area once cutouts are taken out, in square metres. |
surface.perimeterM | Room perimeter in metres. |
surface.wallsCm | Length of each wall in centimetres, in order. |
pattern.parameters | The pattern parameters actually used, defaults included. |
pattern.jointMm | Joint width in millimetres. |
pattern.startCm | Layout origin in centimetres. |
tiles.total | Tiles to buy for this layout. |
tiles.whole | Of those, laid whole. |
tiles.cut | Of those, needing a cut. |
tiles.wastePercent | Share of the bought material that ends up as offcut. |
tiles.narrowestCutMm | Shortest side of any cut piece. A small number means a sliver. |
tiles.sliverCount | Cut tiles coming out under a tenth of a whole tile. |
warnings | What is wrong with this layout, and what usually fixes it. |
svgUrl | The same drawing at an address of its own. |
plannerUrl | Opens 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=svgPatterns 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/patternsPatterns available right now:
squares-patternbricks-patternvertical-bricks-patternhexagons-patternflat-top-hexagons-patterndiamonds-patternrhombus-patternisometric-cubes-patternherringbone-patternchevron-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.