A Headless Commerce API

We will design the API for a small shop like the mug business. Our goal is to support a storefront with several clients that have different needs, such as a website and a phone app.

Functional requirements

The merchant owns the products and sets their prices. A shopper chooses products and submits orders. The API must satisfy these functional requirements:

  • When a merchant adds a product, the API must record its name, description, price, and quantity in stock, and assign it a stable identifier. For now, every product is a plain mug: there is no way to record a size, color, or other variant. Prices are in one currency, US dollars.
  • A merchant must be able to change a product’s name, description, and price, add or remove stock by an amount, and delete a product.
  • The API must let only a merchant change products.
  • A shopper must be able to list the products for sale and read one product’s details.
  • A shopper must be able to create a cart, add a product, set its quantity, and remove it.
  • A shopper must be able to read the contents and current total of their cart.
  • A shopper must be able to place an order from their cart. The API must accept the order only if there is enough stock for every item. When it accepts the order, three things must take effect together: the order is recorded, the stock is reduced, and the cart is marked as ordered.
  • A shopper must be able to retrieve their order afterward, including the product names, quantities, purchase prices, and total.
  • The API must let a shopper access only their own carts and orders.

Think of the cart as what the shopper is considering. The order is what the shop has accepted. The shopper may edit an open cart. Once ordered, that cart cannot be edited or submitted as another purchase. A new purchase starts with a new cart.

Putting two mugs in a cart does not reserve them. If the shop has only two left, another shopper may order them first. Reserving a product when adding it to a cart would require decisions about how long a reservation lasts and how abandoned carts release stock. We leave reservations out of this version, so stock must be checked again when an order is placed.

The cart shows the price of each product when the cart is read. An order records the price at the time it was placed. If a price changes between reading the cart and placing the order, the shopper pays the new price. We leave handling price changes out of this version.

System quality attributes

We assume about 500 products, 50 shoppers browsing at peak, and 200 orders a day, with up to 20 orders a minute during a promotion. The API must also meet these requirements for system quality attributes:

  • Performance: Ninety-five percent of requests must get a response within 500 milliseconds, measured at the API. Ninety-five percent of order placements must get a response within two seconds, measured at the API.
  • Correctness under concurrency: No matter how many orders arrive at the same time, a product’s stock must never go below zero.
  • Reliability: Placing an order must be idempotent. If a request to place an order times out or the response never arrives, sending the same request again must return the existing order, not create a second one.
  • Availability: During each calendar month, clients must be able to use the API at least 99.9 percent of the time.

System constraints

The API must also respect these system constraints:

  • Technical: Each request carries credentials that identify the merchant or a shopper. Accounts, login, and credential issuance are separate design work.
  • Business: Payment processing, taxes, shipping, refunds, and order cancellation by the shopper are outside this version.