---
title: "Draw Floor Plan"
method: POST
path: "/api/v1/tools/draw_floor_plan"
tags: ["Tools"]
---

# Draw Floor Plan

`POST /api/v1/tools/draw_floor_plan`

## Request

- Base URL: `https://pixly.app`
- URL: `https://pixly.app/api/v1/tools/draw_floor_plan`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://pixly.app/oauth/authorize`, token URL `https://pixly.app/api/oauth/token`, scopes: `tools`)

Free (no credits): draw a clean 2D floor plan from a layout YOU write — read the user's description, or look at their hand sketch or brochure plan, and send every room as a rectangle in metres (or feet) plus doors and windows. Returns the drawn plan (areas and dimensions on it) at once, saved so the user can fine-tune it in Pixly's floor plan editor. If the layout has problems (overlapping rooms, a door between rooms that don't touch) you get exactly what to fix — fix it and call again. To change a plan, call again with its planId and the whole updated layout; the new version is saved as its own plan and the earlier one is kept.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `title` string: Address or listing name for the plan's title block.
  - `units` 'm' | 'ft': Units of every number below, and of the labels on the plan.
  - `rooms` object[], required: Every room as an axis-aligned rectangle. Neighbouring rooms must share the wall exactly (one's right edge = the other's left edge) and must not overlap. An L-shaped space = two rectangles joined by a doorway. Lay out a typical sensible plan when the user gives only rough sizes.
    - `id` string, required: Your own short handle for the room ("kitchen", "bed1"); doors and windows refer to it.
    - `type` 'living' | 'kitchen' | 'dining' | 'bedroom' | 'bathroom' | 'wc' | 'hall' | 'office' | 'laundry' | 'storage' | 'garage' | 'balcony' | 'terrace' | 'utility' | 'other', required: What the room is; sets its colour and default label.
    - `name` string: Label on the plan when the type isn't enough ("Bedroom 2", "Master bedroom").
    - `x` number, required: Left edge. The plan's x runs to the right.
    - `y` number, required: Top edge. The plan's y runs DOWN (the top of the drawing is 0).
    - `width` number, required: Size along x.
    - `depth` number, required: Size along y.
  - `doors` object[]
    - `from` string, required: A room id.
    - `to` string, required: Another room id that shares a wall with it, or "outside".
    - `side` 'top' | 'right' | 'bottom' | 'left': Only for to = "outside": which wall of the room the entrance is on.
    - `kind` 'door' | 'doorway' | 'sliding': door = hinged door, doorway = open gap with no door, sliding = sliding/patio door.
    - `width` number
  - `windows` object[]
    - `room` string, required: A room id.
    - `side` 'top' | 'right' | 'bottom' | 'left', required: Which wall; it must be an outside wall (not shared with another room).
    - `count` integer
    - `width` number
    - `full` boolean: Floor-to-ceiling glass (French window, balcony door).
  - `planId` string: To CHANGE a plan you drew before: its planId from that result, with the whole updated layout — saved as a new plan beside it (nothing is overwritten). Omit for a new plan.

## Response `200`

Finished inline — resultUrls present (photo tools)

- Job
  - `jobId` string, required: Job id — pass to get_job to poll
  - `type` 'image_staging' | 'video_pair' | 'video_tour', required: Job family
  - `status` 'pending' | 'processing' | 'completed' | 'failed', required: Anything not completed/failed is still running
  - `creditsCharged` number, nullable, required: Credits debited for this job
  - `createdAt` string, date-time, required: Submission time
  - `completedAt` string, date-time: Present once finished
  - `resultUrls` string[]: Presigned download URLs (present when completed; valid 7 days)
  - `resultPaths` string[]: Storage path of each result, in resultUrls order — pass one as r2Path (or beforeR2Path, a photos[] item…) to run another tool on this result
  - `error` string: Failure reason; the message says whether the credit came back immediately or is in 24h refund review
  - `note` string: Hint for agents, e.g. poll again in a few seconds

## Other responses

- `202`: Accepted and running — poll GET /api/v1/jobs/{id} (video tools)
- `401`: Missing/invalid credential
- `402`: Out of credits, or no active subscription (error.required = credits needed) — POST /api/v1/checkout returns a payment link
- `409`: A request with the same Idempotency-Key is still running — retry in a few seconds for its result
- `410`: Source photo no longer available — re-upload
- `422`: Invalid input — error.issues lists the offending fields
- `429`: Rate limited — see Retry-After (120 req/min, 30/min for generations)

---

[API](https://skmtc.dev/pixly/apis/pixly-api.md) · [All operations](https://skmtc.dev/pixly/apis/pixly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pixly/apis/pixly-api/revisions/6f1aae1786ea?raw)
