Flip Kitchen API

You send a room.
We send back
a finished kitchen.

ONE POST · JSON IN · JSON OUT

POST the walls, doors, windows and appliances of a room. SW Design comes back with complete layouts — every cabinet chosen, sized, placed against the right wall and stamped with a real cabinet code — in the same JSON shape you sent. Not a picture of a kitchen: the parts list of one.

It is the engine that runs flipkitchen.ca and the free designer at design.flipkitchen.ca — the same code path, not a demo copy.

What you can call

Four endpoints, one key.

POST /api/v1/design

Lay out a kitchen

A design document in, several complete layouts out — base, wall, tall and corner cabinets placed, fillers closed, appliances respected.

Scope design · 3 free runs a day per account, then 1 GH Coin a run. Free for members. Nothing is charged when the engine cannot lay the room out.

POST /api/v1/agent

Talk to Emma

The design agent: she answers cabinet questions from our own knowledge base, runs a whole layout when you pass a design, and hands your client the edits she wants made as ops.

Scope agent · billed by model tokens — 1 GH Coin per 500,000, summed over the rounds a turn needs. A layout she runs bills like the endpoint above.

POST /api/v1/voice

Talk to her out loud

The same Emma, spoken both ways. You get a short-lived token; your client opens the live audio session with it and runs the tools she calls. Her persona and tool contract are locked into that token on our side.

Scope agent · sold by the clock: 1 GH Coin per 2-minute block, charged when the token is issued.

POST /api/photo-enhance

Photograph it

One rendered still in, one photographic interior out — grading, material micro-texture and a believable window view, with the geometry left alone.

Scope render · 1 GH Coin an image. Ask us about the design-aware Render Studio path.

Quickstart

From nothing to a kitchen in three steps.

  1. Step 1

    Mint a key

    Sign in, open Settings → API keys, name it after the thing that will use it and tick the scopes it needs. The key is shown once — store it in your server's secret manager.

  2. Step 2

    Get a room to send

    Fastest path: draw one in the free designer at design.flipkitchen.ca and press ⬇ Download JSON. That file is a valid design document — send it straight back to us.

  3. Step 3

    POST it

    Every variant that comes back is a whole design document again, so you can hand it to your own renderer, save it, or send it back in for another pass.

# Two walls, nothing in the room yet. The key lives in the environment —
# never in the file you commit.
curl -X POST https://www.flipkitchen.ca/api/v1/design \
  -H "Authorization: Bearer $FLIP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "design": {
      "name": "Demo kitchen",
      "layoutType": "DIY",
      "selectedDoorColor": "BW",
      "customWalls": [
        { "id": "cw1", "x1": 0,   "z1": 0, "x2": 144, "z2": 0,
          "height": 96, "thickness": 3, "designSide": "right" },
        { "id": "cw2", "x1": 144, "z1": 0, "x2": 144, "z2": 120,
          "height": 96, "thickness": 3, "designSide": "left"  }
      ],
      "openings": { "windows": [], "doors": [], "cutouts": [] },
      "kitchenElements": [
        { "type": "sink",  "wall": "cw1", "position": 60,  "width": 33 },
        { "type": "fridge","wall": "cw2", "position": 100, "width": 36 }
      ],
      "cabinets": []
    }
  }'
// 200 — abridged. Each variant is a full design document.
{
  "ok": true,
  "schema": "fk.design/1",
  "count": 4,
  "failed": 0,
  "variants": [
    {
      "name": "Demo kitchen — SW 1",
      "customWalls": [ /* what you sent, normalised */ ],
      "cabinets": [
        { "sku": "SB36", "wall": "cw1", "position": 43.5, "width": 36 },
        { "sku": "B18",  "wall": "cw1", "position": 79.5, "width": 18 }
      ]
    }
  ],
  "coin": { "charged": 1, "balance": 41 },
  "freeLeft": 0, "freePerDay": 3, "member": false
}

Cabinet codes, positions and counts above are illustrative — the engine picks them from the room you send.

The design document

One shape, both directions.

The thing you POST and the thing you get back are the same kind of object — the document our designer saves. Everything is in inches, in plan view: x runs left-right, z runs up-down on the drawing.

What the engine reads

FieldWhat it is
customWallsRequired. The room. Each wall: id, x1 z1 x2 z2, height, thickness, and designSide"right", "left" or "double": which side of the line the kitchen is on. Up to 40 walls.
openings{ windows, doors, cutouts }. Each entry sits on a wall: wall, position (inches along it), width. Cabinets are kept clear of them.
kitchenElementsAppliances and fixtures — sink, range, fridge, dishwasher and friends — as { type, wall, position, width }. These anchor the layout: the engine builds around them.
cabinetsCabinets that already exist. Send [] for a fresh layout.
island / pantryOptional blocks, when the room has them.
selectedDoorColorDoor colour code for the returned cabinets (default "BW").
wallCabHeight"auto" or a height in inches.
noWallCabstrue to lay out base cabinets only.
layoutType"DIY" for a room you drew yourself — the normal case.

Anything else in the document is carried along untouched. Unknown fields are never an error — that is how the schema grows without breaking you.

Request options

Body fieldWhat it does
designRequired. The design document.
designWallIdsArray of wall ids. Lay out only these walls and leave the rest of the room alone.
nameStampUp to 40 characters appended to each variant's name — handy for tracing a run.

Response

FieldWhat it is
okfalse with an error when the engine could not lay this room out. Not billed.
variantsThe layouts. Each is a full design document.
count / failedHow many came back, and how many of those the engine itself flagged.
inputThe engine input we derived from your document — useful when you are debugging why a room came out the way it did.
coin{ charged, balance } when a coin was spent.
freeLeft / freePerDayWhat is left of today's free runs.

The agent

Emma answers — and your app is her hands.

Two things happen on our side: she looks things up in the cabinet knowledge base, and she runs SW Design when you pass a design. Everything else she wants done comes back as ops for your client to execute — so an app with a canvas gets an assistant that edits the drawing, and a plain server still gets answers and whole layouts.

// Turn 1 — tell her what your client can do.
const r = await fetch("https://www.flipkitchen.ca/api/v1/agent", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.FLIP_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    messages: [{ role: "user", content: "Design my kitchen" }],
    design,                      // lets her run a layout
    capabilities: ["designer"],  // tools YOUR client can run
    canvas: "empty plan, two walls drawn",
    lang: "en"
  })
});
const { reply, ops, assistant_message, variants } = await r.json();
// Turn 2 — run her ops, report back, call again.
const results = ops.map(op => ({
  role: "tool",
  tool_call_id: op.id,
  content: JSON.stringify(runInYourApp(op.name, op.args))
}));

await fetch("https://www.flipkitchen.ca/api/v1/agent", {
  method: "POST",
  headers: { "Authorization": `Bearer ${process.env.FLIP_API_KEY}`,
             "Content-Type": "application/json" },
  body: JSON.stringify({
    messages: [...history, assistant_message, ...results],
    design, capabilities: ["designer"]
  })
});

capabilities is "draw" (a 2D plan) or "designer" (the full editor). Send none and she is never offered a tool your client cannot run.

Every reply carries usage — the model tokens this turn cost, summed over the rounds she needed. Nothing is charged for them today; when the agent leaves preview it is priced on exactly that number, and your key's running total is on the API keys page.

Keys, limits, errors

The rules, in full.

What a call costs

Everything is paid in GH Coins off the account the key belongs to — the same wallet, and the same prices, as the buttons in our own app. API calls have no free allowance: the free daily runs and free voice minutes belong to people using flipkitchen.ca, not to a product running on our engine. Top up at flipkitchen.ca/topup.

CallUnitPrice
/api/v1/designone run1 GH Coin
/api/v1/agentmodel tokens (prompt + completion, all rounds)1 GH Coin per 500,000 tokens — a fraction of a coin carries over to your next call, so a short turn is never rounded up
/api/v1/voicea 2-minute block1 GH Coin, charged when the token is issued and refunded if it could not be minted
/api/photo-enhanceone image1 GH Coin

Every agent reply carries usage and billing — what the turn cost in tokens, what was charged, and the balance left — so you can meter your own users without guessing. Per-key totals are on your API keys page.

Two kinds of key

A key on a server can stay secret. A key in a web page cannot — so there are two, and the browser one is built to survive being read.

fk_live_ · server key

  • Lives in your backend's environment. Works with no Origin — server to server.
  • Never put one in browser JavaScript, a mobile binary or a public repository.

fk_pub_ · browser key

  • Domain-locked. It only works from the domains you listed when you made it; a request with no Origin or Referer at all is refused, which is what stops someone replaying it from a script.
  • Daily ceiling. You set the most it may spend in a day (20 GH Coins by default), so a copied key costs you a day, not a wallet.
  • Paste it straight into your own page — that is what it is for.

What a key is

  • A key is the account that made it. It spends that account's GH Coins under the same rules the buttons in our app follow — there is no separate API price list.
  • Scopes design, render, agent. A key is refused on a route outside its scopes.
  • Five keys per account. Revoke one and it stops working immediately; usage per key is kept so you can see which integration spent what.
  • A key can never reach your saved designs, projects or account settings — only the three endpoints above.

Browser calls. The API refuses cross-origin requests from hosts it does not know, and a key in browser JavaScript is a key you have given away. Call us from your server. If you need a browser on your own domain to talk to us directly, ask us to allow-list it.

Rate and quota

/api/v1/design200 requests an hour per address. Three free runs a day per account, then 1 GH Coin each; members run it freely.
/api/v1/agent120 requests an hour per account (20 an hour without a key).
/api/v1/voice60 blocks an hour per address.
No key at allThree layouts a day per address, then 402. That is what the free public designer runs on.
Body size4 MB for a design, 16 KB for key management.

Errors

StatuscodeWhat happened
400bad_json · bad_design · no_walls · bad_wall · no_messagesThe body did not parse, or the document has no usable walls. Fix and resend — nothing was billed.
401signin_requiredNo key, an unknown key, or a key outside its scope.
402Out of GH Coins, or the free daily allowance is used up. Top up and retry.
403api_key_domain · api_key_scopeA browser key used from a domain it was not issued for (or with no origin at all), a key outside its scopes, or a browser request from an origin we do not know.
402api_key_day_capA browser key hit its daily coin ceiling. It resets tomorrow, or raise it in settings.
429Rate limited; retry_after_s says for how long.
503Our usage counters are down. We fail closed rather than give work away — retry in a minute.

Beyond the API

Put the designer itself in your product.

design.flipkitchen.ca is the free, public build of our designer: draw walls, drag cabinets in, see it in 3D, download the JSON. No account, no key, nothing to install.

The same designer can run on your domain with your key: make a browser key for design.yourbrand.com, and every layout your visitors generate there is billed to your account — no accounts for them, nothing to install, and you keep the daily ceiling.

Branding, your own catalogue and the rest of the embed programme is a conversation rather than a signup form. Tell us what you are building.

Versioning promise

  • A design document carries "schema": "fk.design/1". Read it, and migrate forward when it changes.
  • Inside a version, fields are only ever added — never renamed, never removed. Ignore what you do not recognise.
  • New behaviour arrives behind a new field, off by default.
  • Breaking changes get a new path (/api/v2/…), and v1 keeps working.