Build Websites and Apps with AI
ProjectBeginner 30 min· Project: coffee shop backend · 12 of 21

Design the order API with AI

Design the Brew & Bean order API before writing code: endpoints, data, rules, status codes and security, with AI as your assistant. You finish with an API contract that every later lesson builds from.

In the website lessons you built Brew & Bean, a coffee shop site where the cart and order form work but the order goes nowhere. In this project you build the other half: a small API (a program that other programs talk to over the internet) that serves the menu and receives orders. Then you add a database, write tests and connect the website to it.

This first lesson is about design before code. You will use AI to design the API, but you make the decisions. Nothing to install yet. You need the finished website (or at least its cart and order form) and a free AI assistant such as ChatGPT, Gemini or Claude.

What you will have at the end of this project

A working order system, live on the internet:

- A FastAPI server (Python) with four endpoints: GET /menu, POST /orders, GET /orders/{id} and PATCH /orders/{id}/status. - Orders saved in a database: SQLite on your laptop, Postgres in production. - An automated test suite of about 27 tests that run in under a second. - The website now loads the menu from the API and sends real orders to it. - Both parts deployed on free plans.

The five lessons

LessonWhat you doYou end with
Design the order API (this one)Decide endpoints, data and rules; write an API contractAPI.md
Build the API with FastAPIWrite the server with orders in memoryA running API you can try in the browser
Add a databaseSQLAlchemy models, SQLite, then PostgresOrders that survive a restart
Test the APIAI-written pytest tests, reviewed by youA green test run
Connect and deployWebsite talks to API, both go liveA live shop you can share

What you will do in this lesson

  1. 1Understand why an API needs a design.
  2. 2Ask AI to list the resources and endpoints.
  3. 3Define the data and the validation rules.
  4. 4Choose the status flow and the error codes.
  5. 5Review the design for security holes.
  6. 6Write the API contract (API.md) that the next lessons build from.

Why design the API first

Think of an API as a restaurant menu plus a kitchen window. The menu lists what you may ask for and in what form. The kitchen window is where you hand over the order. If the menu is vague, orders come back wrong.

Two programs will depend on your API: the website you already built, and the tests you will write. If you change an endpoint later, both break. A page of design now saves hours later, and it gives the AI a precise target. A prompt like "build an order API" makes the AI guess the field names, the status codes and the rules. A prompt that includes the contract makes it follow them.

Backend means the part that runs on a server and holds the data and the rules. The browser is not trusted: anyone can open DevTools and send any request they like. So every rule that matters, such as the price, must be enforced on the server. You will see this idea again and again in this project.

Step 1: Resources and endpoints

A resource is a thing your API manages: here, the menu and orders. An endpoint is a URL plus an HTTP method (GET, POST, PATCH) that does one job on a resource. The coffee shop needs only four. Let AI propose them, then compare with your own idea.

Prompt · Design the endpoints
I am building the order API for a small coffee shop called Brew & Bean (Indiranagar, Bengaluru). Customers order from a React website for pickup. There is no delivery, no payment and no user accounts in version 1. Staff need a way to mark orders as preparing, ready or picked up.

Propose the smallest REST API that supports this. For each endpoint give: method, path, what it does, who may call it (customer or staff), request body and the HTTP status codes it can return. Keep it to 4 or 5 endpoints. Explain in one line why each exists, and list anything you left out on purpose.

What to expect: A good answer has GET /menu, POST /orders, GET /orders/{id} and a status update for staff. If the AI adds users, payments or a cart endpoint, ask it to remove them: the cart lives in the browser until the customer places the order.

Our four endpoints

Method and pathWhoJobSuccess code
GET /menuCustomerList all menu items200
POST /ordersCustomerPlace an order201
GET /orders/{id}CustomerCheck an order200
PATCH /orders/{id}/statusStaffMove an order along200

Why PATCH and not PUT for the status? PUT replaces a whole resource. PATCH changes part of it, and we change only the status. Why 201 and not 200 for a new order? 201 Created tells the caller that something new now exists. The word after the slash, {id}, is a path parameter: the caller puts the order's id there.

What you leave out is a design decision

Notice what is missing: there is no GET /orders that lists every order. That would expose every customer's name and phone number to anyone. When you add a staff screen later, add it behind the admin key.

Step 2: The data

Now decide what an order looks like. Ask yourself two questions for every field: who provides it (the customer or the server) and can it change later?

Fields of an order

FieldWho provides itNotes
idServerRandom and hard to guess, because it works like a ticket number
customer_name, phoneCustomerValidated on the server
items: item_id and qtyCustomerOnly ids and quantities, never prices
items: name and priceServerCopied from the menu at order time
totalServerSum of price x qty. Never trust a total from the browser
statusServerStarts as received, changes only through the staff endpoint
pickup_timeServerWorked out from the customer's pickup choice
created_atServerTime the order was placed, in UTC

Two choices here are worth explaining.

Copy the price into the order. If you only stored the item id, then changing the price of a cappuccino next month would silently change the total of last month's orders. Real shops keep the price the customer actually paid. So each order line stores name and price as they were at that moment.

Pickup as a code, not free text. The website's dropdown has four choices. The API accepts asap, in_15, in_30 and in_60 and turns them into a real pickup_time. A code is easy to validate. A string such as "around 6ish" is not.

Step 3: Rules and error codes

Rules are what make an API safe. Write them down as numbers and patterns so a test can check each one. Use the same rules as the website's form (a phone must be a 10-digit Indian mobile number starting with 6, 7, 8 or 9), because the API must not depend on the website being well behaved.

Validation rules

RuleIf broken
Name has 2 to 60 characters422
Phone matches 10 digits starting 6 to 9422
1 to 20 order lines, each qty 1 to 20, no item twice422
Every item_id is on the menu422
Order id exists404 if not
Status change follows the allowed flow409
Staff key present and correct401 if not

The status codes we use

CodeMeaningExample here
200OKMenu returned, status updated
201CreatedOrder placed
401Not allowed: who are you?Wrong or missing admin key
404Not foundUnknown order id
409Conflict with the current stateMoving an order from received straight to picked_up
422The request body is invalidPhone number too short

401 vs 422 vs 409 confuses many learners. Use this test. If the request is badly formed (wrong shape or value), it is 422. If the request is fine but this caller may not do it, it is 401. If the request is fine and allowed, but the thing is in the wrong state for it, it is 409.

Step 4: The status flow

An order moves through a small set of states, a state machine. Writing it as a table shows the allowed moves and catches mistakes such as reviving a cancelled order.

Allowed status changes

FromMay move to
receivedpreparing, cancelled
preparingready, cancelled
readypicked_up
picked_upnothing (final)
cancellednothing (final)
Prompt · Find the missing cases
Here is the status flow for a coffee shop pickup order:

received -> preparing -> ready -> picked_up
An order can be cancelled while it is received or preparing. picked_up and cancelled are final.

List realistic situations this flow does not handle (customer never comes, staff press the wrong button, two staff update at the same time). For each, say whether version 1 should handle it or leave it out, and why.

What to expect: Expect ideas such as no-shows, undo, and concurrent updates. Version 1 should leave most of them out. A design is finished when you decide what is out, not when you include everything.

Step 5: Review the design like an attacker

Before any code exists, ask what a curious or dishonest user could do. This is cheap now and expensive later. Ask the AI to play the attacker, then read its answer critically. AI often invents risks that do not apply and misses real ones, so check each point against your design.

Prompt · Review the API design for security and mistakes
Below is the design of a small order API. Act as a careful security reviewer. List the 8 most likely problems, ordered by how bad they would be for a small shop. For each: what could go wrong, and one concrete change to the design. Do not suggest features outside the design (payments, accounts).

[paste your API contract here]

What to expect: A good review mentions: trusting the total or prices from the browser, guessable order ids, no limit on order size, anyone being able to change status, a public list of orders leaking phone numbers, and missing CORS or rate limits. Compare with the checklist below.

Design review checklist

  1. The client never sends a price or a total.
  2. Order ids are random, not 1, 2, 3.
  3. Status changes need a secret key, kept in an environment variable and not in the code.
  4. Order size is limited (20 lines, quantity 20 each).
  5. No endpoint lists all orders or phone numbers.
  6. The API allows requests only from the shop's website (CORS).
  7. Error messages do not reveal internals such as file paths.

Know the limits of your version 1

Our simple admin key is enough for a learning project but not for a real business. It is one shared password. A real shop would use staff accounts with login. Also, the API as designed has no rate limiting, so someone could flood it with fake orders. You will note both as stretch goals rather than build them now. Say what you are not doing, out loud, in the README.

Step 6: Write the API contract

Now put all the decisions in one page. This API contract is the document you paste into the AI in the next lesson, and the thing your tests check. Save it as API.md in a new folder called brew-and-bean-api. Here is the reference version. Your AI's wording will differ, and that is fine, as long as the decisions are the same.

API.md (reference)
# Brew & Bean order API: contract

Local address: http://localhost:8000
All requests and responses are JSON. Prices are whole rupees.

## Objects

MenuItem
  id           text, for example "cold-brew"
  name         text
  category     "coffee" | "tea" | "bakery" | "food"
  price        whole number (rupees)
  description  text

Order (what the server sends back)
  id           text, random, hard to guess
  customer_name, phone
  items        list of { item_id, name, price, qty }
               (name and price are copied from the menu when the order is placed)
  total        whole number (rupees), worked out by the server
  status       "received" | "preparing" | "ready" | "picked_up" | "cancelled"
  pickup_time  date and time in UTC, ISO 8601
  created_at   date and time in UTC, ISO 8601

## Endpoints

GET /menu
  200  list of MenuItem

POST /orders
  Body:  { customer_name, phone, items: [{ item_id, qty }], pickup }
         pickup is "asap" | "in_15" | "in_30" | "in_60" (default "asap")
  201  Order (status "received")
  422  validation error, or an item_id that is not on the menu

GET /orders/{id}
  200  Order
  404  no such order

PATCH /orders/{id}/status        (staff only: header X-Admin-Key)
  Body:  { status }
  200  Order with the new status
  401  missing or wrong key
  404  no such order
  409  status change not allowed
  422  status is not one of the five values
  503  server has no ADMIN_KEY configured

## Rules
- The client sends item ids and quantities only. The server finds the prices
  and works out the total.
- customer_name: 2 to 60 characters after trimming spaces.
- phone: 10 digits, starts with 6, 7, 8 or 9.
- items: 1 to 20 lines, no item twice, qty 1 to 20 each.
- Status flow: received -> preparing -> ready -> picked_up.
  An order can be cancelled only while it is received or preparing.
  picked_up and cancelled are final.
- pickup_time = now + 10 minutes for "asap", or 15 / 30 / 60 minutes.
- Only the website's address may call the API from a browser (CORS).

Every rule in this file becomes code in the next lesson and a test in lesson 4.

Prompt · Turn my decisions into a contract
Write an API contract in plain text (no code) for a coffee shop order API, using exactly these decisions. Do not add anything.

[paste the endpoint table, the field table, the rules and the status flow from this lesson]

Format: Objects, Endpoints (each with request body, response codes), Rules. Use short lines. Prices are whole rupees.

What to expect: Check the AI's contract against your decisions line by line. The most common errors are an invented field, a wrong status code, or a rule that quietly disappears.

The folder structure

Plan the files before writing them, so you can check that the AI follows your structure:

Project layout
brew-and-bean-api/
  API.md                 the contract
  requirements.txt       packages the server needs
  requirements-dev.txt   extra packages for tests
  app/
    __init__.py          empty file, marks a Python package
    main.py              the app and its endpoints
    schemas.py           Pydantic models: the shape of requests and responses
    menu.py              the menu data, held on the server
    db.py                database connection (lesson 3)
    models.py            database tables (lesson 3)
  tests/
    conftest.py          shared test setup (lesson 4)
    test_api.py          the tests (lesson 4)

The menu is kept in app/menu.py on the server, with the same eight items as the website's old src/data/menu.js. The server owns the prices. Moving the menu into the database is a stretch goal in lesson 3.

How this comes up in interviews

Junior backend interviews often ask "Design a simple ordering API" or "What status code would you return when...?". The strongest answers follow the order you used here: list the resources, the endpoints and methods, the data and who provides it, the validation rules, the error cases, and what you would add later. Being able to say "the total is computed on the server because the client cannot be trusted" is the single most common thing interviewers hope to hear.

Try it: Design a new endpoint

The shop wants customers to cancel their own order while it is still received, without the admin key. Design it: which method and path, what could go wrong (anyone who knows the id could cancel it), and which status codes it returns. Write it in the same format as the contract.

Try it: Stretch: add opening hours

The shop is open 8 am to 10 pm. Decide how the API should handle an order placed at midnight, or a pickup time after closing. Write the rule and the error code, and add it to API.md. You will not build it yet.

Key takeaways

  1. Design the API before you prompt: resources, endpoints, data, rules, errors. Then give the AI the contract.
  2. The server decides prices, totals, ids, status and times. The client sends only what the customer chooses.
  3. Use status codes precisely: 201 created, 401 not allowed, 404 missing, 409 wrong state, 422 bad input.
  4. A status flow written as a table prevents impossible states.
  5. Review the design for attacks while it is still cheap to change, and write down what you are leaving out.

Check yourself

Finishing the quiz marks the lesson as done.

1. A customer's order request includes "total": 1 along with valid items. What should the API do?

2. Why does each saved order line copy the item's name and price instead of only storing the item id?

3. Staff try to move an order from received straight to picked_up. The request is well formed and they have the right key. Which status code fits best?

4. Which design choice best protects customers' phone numbers?

5. Why write an API contract before asking AI to build the API?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free