# Checkout API — GoCommerce’s Idempotent, Guest-First Checkout

> GoCommerce checkout: one idempotent call that returns 409 rather than charge a changed price, permanent guest checkout, nine gateways plus cash on delivery.

- Canonical: https://kitcommerce.store/features/checkout/
- Last updated: 2026-09-25

---

Features · Checkout

## A checkout that refuses to charge the wrong price

One call turns a cart into an order and tells the client how to pay. Retry it and you get the same order back; change a price underneath it and it answers 409 with the new figures instead of charging something the shopper never saw.

- **1** call from cart to order
- **9** gateway modules, plus cash on delivery
- **0** accounts a shopper needs

### The call that places the order

The four things this checkout does that a buyer never sees and an operator depends on.

- **Single-call, idempotent checkout**

  POST /api/checkout/{code} takes the cart, contact, address, shipping rate and payment data, creates the order and returns what the client must do to pay. An Idempotency-Key retry resumes the same order instead of making a second.

  `core/checkout.go`

- **No silent repricing**

  A price that changed or stock that ran out returns 409 with per-line detail and the current values. The order is never charged at a figure the shopper did not see.

  `core/checkout.go · LineConflict`

- **Guest checkout, for good**

  An order needs an email, not an account; its access token is the guest’s handle. With the identity module a shopper can later claim a guest order into an account by presenting that token.

  `core/orders.go · ext/identity`

- **Operator-placed orders**

  Staff with orders.write place an order for a customer through the same checkout a shopper uses: the same stock reservation, numbering, discount checks and order.created event.

  `POST /api/admin/orders`

### Payments

- **Nine gateway modules**

  Stripe, Razorpay, Adyen, Paddle, Lemon Squeezy, Creem, Hyperswitch, Helcim and RevenueCat, each configured from the admin’s payment methods screen.

  `ext/payments-*/`

- **Cash on delivery by default**

  The built-in cod method confirms the order and takes stock off the shelf at once; payment stays pending until an operator marks it paid.

  `core/payments.go · codProvider`

- **Several gateways side by side**

  Any number of providers run at once, each at its own checkout route with a webhook route the core owns. Writing your own is a two-method interface.

  `core/ports.go · PaymentProvider`

### Customers and prices

- **Order history for shoppers**

  With the identity module, signed-in shoppers list and read their orders.

  `ext/identity`

- **Address book** — Partial

  Signed-in shoppers keep labelled addresses with a default. Missing: separate billing and shipping addresses, and staff editing a customer’s book.

  `ext/identity`

- **Discount codes** — Partial

  Percentage, fixed or free shipping; scoped to the order, products, collections or a category; with minimum spend, dates, usage limits and once-per-email. Missing: automatic discounts at checkout, more than one code per cart, buy-X-get-Y.

  `core/discounts.go`

- **Price lists** — Partial

  A line’s price resolves by customer group, channel, date window, priority and quantity break. Missing: a hook for your own pricing logic, and overriding one line’s price by hand.

  `core/pricing.go`

### Stock, tax and shipping

- **Stock reservation** — Partial

  Checkout reserves stock per location when the order is created and holds it until payment or until the unpaid-order window (24 hours by default) runs out. Missing: holding stock at the cart stage.

  `core/inventory.go · reserveStock`

- **Shipping in parts** — Partial

  An order can ship in several parcels by line and quantity, each through any carrier module. Missing: several payments on one order.

  `core/fulfillment.go`

- **Stock allocation** — Partial

  Each line is reserved at the first active location, by priority, that can cover it all. Missing: other strategies, and splitting one line across locations.

  `core/inventory.go · pickLocation`

- **Tax rates** — Partial

  Flat rates by country, state and category, the most specific winning, prices tax-inclusive or not, each line’s tax recorded. Missing: tax classes apart from categories, and per-channel rates.

  `core/taxes.go`

- **Shipping zones and rates** — Partial

  Zones by country and state, with named rates priced by basket subtotal (“free over 2,000”). Missing: weight-based rates and postal-code zones.

  `core/shipping.go`

- **Address checks** — Partial

  Checkout requires line one, city, postal code and country. Missing: format rules and a validation hook.

  `core/types.go · Address.Validate`

### Storefront

- **A Svelte Commerce connector** — Partial

  @misiki/gocommerce-connector 0.1.0, published on npm, covers catalogue, cart, shipping rates, checkout and order lookup. Missing: customer accounts and a search index.

  `connectors/svelte-commerce`

- **Several carts at once** — Partial

  Carts are anonymous tokens, so a client can hold any number. Missing: carts owned by a customer account.

  `core/cart.go`

### Not in GoCommerce yet

Named here so nobody has to find out at launch. Each is absent from the code today.

- **Recurring payments** — No stored cards, subscriptions or off-session charges.
- **Split payments** — An order carries exactly one payment provider.
- **Gift cards and store credit** — No balance, issuing or redemption.
- **Multi-currency** — A store settles in one currency; channels carry none.
- **Tax exemptions** — No exempt flag on customers, groups or orders.
- **Tax or rate providers** — No hook for Avalara-style tax or live carrier rates at checkout.
- **Click-and-collect** — No pickup option at checkout.
- **Per-product quantity limits** — A cart line is capped only by stock.
- **Reorder** — Nothing turns a past order into a new cart.

FAQ

### Questions about checkout

**What happens if a price changes while someone is checking out?**

The checkout call answers 409 with the line that changed and its current price, and no order is charged. The client shows the new figure and the shopper decides. The engine never reprices an order silently.

**Can shoppers buy without an account?**

Always. Guest checkout is a permanent guarantee in the core: an order needs an email, and the access token returned at checkout reads it back. Accounts are the identity module, added when you want them.

**Which payment gateways work in India?**

Razorpay is a module, and cash on delivery is built in and on by default. Hyperswitch and Stripe are also modules; whether a gateway serves your business is between you and it.

**Can a cash-on-delivery order be refunded?**

Not through the engine — the cod method has no refund call, so the API answers 409. The money goes back however you collected it, outside GoCommerce. Gateway orders refund through their gateway.

**Does it calculate tax automatically?**

From your own rate table: flat rates by country, state and product category, applied at checkout and recorded per line. There is no connection to a tax service yet.

### Read the code behind every tile

Each file named on this page is in the GoCommerce repository, MIT licensed. Run it and check.

[Deploy in minutes](https://kitcommerce.store/#one-command) · [GoCommerce on GitHub](https://github.com/itswadesh/gocommerce) · [All features](https://kitcommerce.store/features/)
