Checkout and addresses

A purchase is a cart the customer fills, presents for payment and pays in your page. Open one with POST /v1/stores/{store}/checkouts and a currency, put prices in it with PUT /checkouts/{checkout}/items (a quantity of zero takes a line out), and name a coupon with PUT /checkouts/{checkout}/coupon (null takes it off). POST /checkouts/{checkout}/freeze presents it for payment: every line must still price as it did, and the cart stops changing. When a line's refund policy is shorter than the statutory window, the customer must consent to it in your page and you send refund_waiver: true; without it the freeze is refused as invalid at args.refund_waiver, naming the policy.

A total above zero but under the payment processor's minimum charge is granted free, since the processor refuses to take it: the cart reads under_minimum with the amount waived and the processor's minimum, so your page can say why the customer pays nothing. The freeze discounts its lines whole, so totals.discount includes the waived amount and totals.total is zero, asks no refund_waiver, and the order carries the same statements.under_minimum for its receipt. A total the processor still refuses as too small when paid (in a currency whose minimum isn't known ahead, or one it settles in another currency) is granted free then: pay answers paid (or requires_setup, below, when a plan in it will charge its first renewal), and under_minimum.minimum is null.

POST /checkouts/{checkout}/pay starts the payment. A cart with nothing due answers paid with its order at once, unless it buys a plan whose first renewal will charge (a coupon or the processor's minimum making the first period free): the cart reads card_required (reason renewal, null otherwise, while it is open or frozen), and pay answers requires_setup with a setup. Tell the customer nothing is charged now and the card pays the first renewal, confirm it with Stripe.js's confirmSetup (same publishable_key, account and client_secret as a payment), then call confirm, which answers paid once the card is saved, setup_processing while Stripe checks it, or requires_setup to try again; the checkout can't complete without a card. Any other answers requires_payment with a payment: confirm it in your page with Stripe.js, loaded with its publishable_key and account as the connected account, using its client_secret. Then call POST /checkouts/{checkout}/confirm, which reads the payment back from Stripe, never from your page, and answers paid with the order once it went through, processing while it settles, or requires_payment when the customer has to try again. A payment called off answers cancelled, and one given back refunded, refund_pending (Stripe will let the refund through later) or refund_failed (the store settles it with the customer). Asking to pay again answers the same payment. POST /checkouts/{checkout}/abandon gives a cart up. These need checkout:write.

No write takes an idempotency key, so after a failed or unanswered call read the cart back (GET /checkouts) before trying again, rather than opening another.

The customer's email addresses are listed at GET /contacts. POST /contacts/add mails a code to a new address, POST /contacts/verify proves it with that code, and POST /contacts/remove takes one off, never the last proven one. A proven address signs the customer in, so these need contact:write, which the customer grants on its own; ask for it only where your app manages their addresses.