Signed-in checkout
A signed-in shopper places an order in the storefront.
Every login requests the customer’s API token. Concurrent token acquisition is single-flight per sign-in within one isolate; separate isolates are not coordinated and can refresh at the same time.
A signed-in shopper’s browser never talks to the Shop API for checkout. The storefront’s server function runs the same
order workflow itself, against the shop database, for the admitted visitor (a customer, or an invited agent or Poppy
browser with the checkout permission).
Admit and convert
The storefront admits the visitor (Auth0 session, revocation list, /v1/me/identity) and converts it to a domain
actor. One operation wrapper (shopOperation) checks the account is active and an invited agent’s delegation is
unchanged, then logs one shop_operation line (checkout.place) however the call ends.
Check the permission
The permission to check out is checked first, for an invited agent against its current delegation.
Run the workflow
The shared order workflow places the order and returns it. Nothing remembers an earlier submission: the form disables while it submits, and a second submission after a paid order finds the cart empty and is refused. The storefront redirects to the confirmation page.
Stock that runs out while the shopper is paying is refused before any charge and shown on the form. Account lifecycle changes take effect on the next request, including for retries.
Bank challenge completion
When checkout returns nextAction.clientSecret, the webshop adds its publishable key and the browser completes
the Stripe challenge. The landing route, GET /checkout/complete, settles the order in the storefront. It reads the PaymentIntent the order recorded from Stripe and records a payment only when Stripe reports success, for an order that is this customer’s (or, for a guest, that the private order token opens); a foreign order is “not found”. It re-reads the order after settlement.
This route and the card-setup return are the only GET routes that change state: the bank sends the browser back with a redirect, so they cannot be form posts. They are safe because nothing in the request decides the outcome (only the order id and token choose which order to look at), repeating a visit changes nothing, the id and token are length-bounded, and the response is private and never cached.
A paid order sets fh_placed and redirects to /account/orders/<id>?placed=1. Pending payments return to
/checkout?payment=pending; failed payments return to /checkout?payment=failed. Missing orders return to
/checkout. A revoked web session is refused by the webshop before it reaches the shop, while a verified Stripe event can still settle an
already admitted payment. A fresh sign-in can read that order.
WebMCP customer checkout (place_order and its settle step) uses these same operations after validating the confirmed
quote, so an agent in the page and a person clicking agree. Quoting still reads the shared checkout preview from the Shop
API. Saved-card setup and changes are separate storefront card controls, open to the customer only.