Carts confirmed elsewhere

API

The person can confirm your cart without you: a YES to Layout's cart-ready text, the Layout app, or Layout's tracking page. Your confirm on that cart now says so, names the order and its state now, and never sends a second order.

What changed

  • POST /v1/carts/:id/confirm and /confirm/resend-code on a cart whose order was already confirmed answer 409 already_confirmed. Nothing is confirmed or charged again. error.order is { id, status, confirmedVia? }, where status is placing, placed, unconfirmed or refunded, and error.userMessage is a sentence for the person.
  • confirmedVia is sms (a YES to Layout's text) or tracking_link (Layout's tracking page) when Layout knows, on the error and on GET /v1/carts/:id's order for a closed cart. It is absent for a confirm in the Layout app or through the API or MCP.
  • A retry of your own confirm with the same idempotencyKey still gets the answer that call earned.
  • The MCP order tool's confirm result carries alreadyConfirmed: true, orderState and, when known, confirmedVia, plus complete: false and nextAction: "order_status" while the order is placing or unconfirmed.
409 {
  "error": {
    "code": "already_confirmed",
    "message": "This cart was already confirmed by the person replying YES to Layout's text, so nothing was confirmed or charged again. It is placing now. Read GET /v1/orders/ord_7c21e4b9a0d3, and do not confirm or build this order again.",
    "orderId": "ord_7c21e4b9a0d3",
    "order": { "id": "ord_7c21e4b9a0d3", "status": "placing", "confirmedVia": "sms" },
    "userMessage": "This order was already confirmed and is being placed now. Nothing extra was charged."
  }
}

Why it matters

A confirm that lost to the person's own YES used to answer 202 placing as if your call had placed it, even once the order was placed. On an order whose placement Layout could not verify, it answered 409 cart_closed and suggested building a new cart, which is how a person ends up with two orders. Now your application can show the person what actually happened.

What to do

On already_confirmed, show error.userMessage, follow the order with GET /v1/orders/:id or the order.* webhooks, which go out whichever surface confirmed it, and do not confirm or build it again. Treat unconfirmed as pending, never as failed. See Already confirmed elsewhere and Errors.

Breaking changes

None under the versioning policy: already_confirmed is a new error code on a 409. One answer moves: a confirm that lost the race to another surface used to answer 202 placing, and an already confirmed cart whose order is unconfirmed or refunded used to answer 409 cart_closed. Both now answer 409 already_confirmed with the same order id.

All changes