# Cancel while building

October 2, 2026 · API

A cancel your application sends while a cart is still building is kept and honoured. A request whose `placeId` and `restaurantName` disagree is refused instead of quietly ordering from the `placeId`'s store. And the store's address now travels with its name everywhere you and the person see it.

## What changed

- `POST /v1/carts/:id/cancel` on a cart that is still building answers `202 { "cart": { "id": "crt_…", "status": "canceling" } }` instead of `409 cart_not_ready`. Layout releases the cart the moment the build lands, never offers it to the person, and never sends Layout's cart-ready text for it. `GET /v1/carts/:id` reads `canceling`, then `canceled`. A confirm on a `canceling` or `canceled` cart is `409 cart_closed`.
- A cancel on a cart that was already confirmed is still `409 cart_closed`, now with `error.order`: the order and its state now (`placing`, `placed`, `unconfirmed` or `refunded`).
- The MCP `order` tool's `cancel: true` takes the build's `idempotencyKey` while the cart is still building, and answers `cancel.status: "canceling"`.
- `POST /v1/carts` and `/answer` with a `placeId` and a `restaurantName` that name different stores answer `409 store_mismatch`. Nothing is built. `error.store` is `{ placeId, name, address }` for the store the `placeId` names, and `candidates`, when Layout could find them, are stores matching the name. Over MCP, the build answers `storeMismatch`.
- The cart's `store` carries the address whenever Layout knows it, on ready, failed, answered and closed carts. `GET /v1/orders/:id` and every webhook payload add `store_address`, null when unknown. A sandbox cart's `confirmationCard` names the address.
- Layout's cart-ready text names the store and its address, and for a cart your application built it opens with your application's name from the console: `Acme Assistant built your order at Layout test kitchen, 1 Sandbox Way, San Francisco, CA 94107:`.

```
409 {
  "error": {
    "code": "store_mismatch",
    "message": "placeId names Layout Test Kitchen North, which does not match restaurantName. Nothing was built. Ask the person which store they mean and send only that store's placeId, or only restaurantName with near or geo.",
    "store": { "placeId": "test_place_branch_north", "name": "Layout Test Kitchen North", "address": "31 Sandbox Way, San Francisco, CA 94107" }
  }
}
```

## Why it matters

A cancel sent while a cart was building used to be refused, and the person was then texted to confirm a cart your application had abandoned. A `placeId` and a name that disagree now stop the build instead of ordering from the wrong store, and the address lets the person tell two branches apart before they pay.

## What to do

Treat `canceling` as on its way to `canceled`, and never confirm it. On `store_mismatch`, ask the person which store they mean and build again with only that store's `placeId`. Show `store.address` beside the store's name. See [POST /v1/carts/:id/cancel](https://docs.layout.link/carts#cancel) and [Errors](https://docs.layout.link/errors).

## Breaking changes

None under the [versioning policy](https://docs.layout.link/versioning): `canceling` is a new cart status, `store_mismatch` a new error code on a 409, and `store_address` a new field. One answer moves: a cancel on a building cart used to answer `409 cart_not_ready` and now answers `202 canceling`. A request that used to build at the `placeId`'s store despite naming another now answers `409 store_mismatch`.
