Finish an order in sandbox

Sandbox

Sandbox used to stop at a priced cart. You could build against real restaurant sites, but the last step, the one that turns a cart into an order, could only be exercised in production. Now a sandbox user can be taken all the way to a placed order, and every place that reports it marks it as simulated.

What changed

  • Verify sends nothing. With an sk_test_ key, verify/start texts nobody and answers with "sandbox": true. verify accepts the fixed code 000000.
  • A sandbox build session can confirm. The order tool's confirm action works on a sandbox build session. It answers "status": "placed" with "simulated": true. No code is needed.
  • The order says it was simulated. The order.placed webhook and GET /v1/orders/:id for that order carry simulated: true.

The whole flow

Provision a user on a reserved test number, +1 500 555 followed by four digits, then verify them with the sandbox code.

POST /v1/users/usr_4b8e/verify/start
200 OK
{ "ok": true, "id": "usr_4b8e", "phoneHint": "+1 (500) •••-0142", "expiresInSec": 180, "sandbox": true }

POST /v1/users/usr_4b8e/verify
{ "code": "000000" }
200 OK
{ "verified": true, "authorized": true, "status": "active", "claimed": true }

Mint a build grant, build over MCP as you already do, and confirm the carted build with its totalMinor and a fresh idempotency key.

order {
  "action": "confirm",
  "orderId": "0b6f2a54-…",
  "expectedTotalMinor": 1850,
  "idempotencyKey": "a7c1e0d2-…"
}

→ { "action": "confirm", "confirm": { "status": "placed", "orderId": "0b6f2a54-…", "subtotalMinor": 1850, "simulated": true } }
  • The total still has to match the cart. A stale one is refused with price_changed, exactly as in production, so a simulated order still proves the cart you built.
  • Asking for a code to be resent answers code_not_needed and places nothing, because sandbox has no code.
  • If Layout cannot check that the session is a sandbox one, the confirm answers with the error unavailable. Retry it: it is never a permanent refusal and never a real order.
  • Cancelling is not available on a build session, in sandbox or production.

Why it matters

You can test your whole integration before you have production keys: the confirm call, the order.placed handler, the order read and whatever your product does once an order exists. The cart is real, built on the restaurant's own site, so the test proves what production will do up to the moment the restaurant would receive it.

What to do

If your code treats every order.placed as food being made, check order.simulated first. Test for true: a real order never carries simulated: true.

Never describe a simulated order to a person as a real one. The sandbox session's own instructions tell your model the same.

Breaking changes

None. A production build session still cannot confirm: the person confirms the order themselves, by replying to Layout's text or in the Layout app. See Finishing an order in sandbox.

All changes