The Shop’s REST API

Let’s start with a RESTful HTTP API for the shop. We will keep this short. Here are the endpoints, the HTTP methods they accept, what they do, and who can use them:

Request Who Effect
GET /products shopper List the products for sale
GET /products/42 shopper Read one product
POST /products merchant Create a product
PUT /products/42 merchant Replace name, description, price
PATCH /products/42 merchant Change some of those fields
POST /products/42/stock merchant Add or remove stock by an amount
DELETE /products/42 merchant Delete the product
POST /carts shopper Create an open cart
GET /carts/73 shopper Read a cart’s items and total
PUT /carts/73/items/42 shopper Add the item or set its quantity
DELETE /carts/73/items/42 shopper Remove the item
POST /orders shopper Place an order from a cart
GET /orders/91 shopper Read an order

DELETE /products/42 soft deletes the product. A request for a deleted product returns the same 404 as a request for an unknown one. Placing an order takes an Idempotency-Key header.

Requests and responses

Reading a product sends this request:

GET /products/42 HTTP/1.1
Host: api.shop.example

The response carries the product’s name, description, price, and stock:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "product_id": 42,
  "name": "Blue mug",
  "description": "Hand-thrown stoneware with a deep blue glaze. Holds 350 ml. Dishwasher safe.",
  "price_cents": 1800,
  "quantity": 5
}

Reading the cart sends the same kind of request:

GET /carts/73 HTTP/1.1
Host: api.shop.example

The response shows the cart’s representation:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "cart_id": 73,
  "status": "open",
  "items": [
    { "product_id": 42, "quantity": 2 },
    { "product_id": 43, "quantity": 1 },
    { "product_id": 44, "quantity": 1 }
  ],
  "total_cents": 7300
}

The cart holds product identifiers, quantities, and the total. It does not carry a product’s name or price, the way the product representation above does. A client that wants a product’s name or price reads the product separately. The cart’s quantity is how many the shopper wants, not the stock shown on the product.