Learning Goals
3 minBy the end of this lesson you will be able to:
- Explain in one sentence what an API is and what REST means.
- Name a resource and give it a tidy endpoint like
/api/students. - Build a read-only API that returns an array as JSON and one item by id.
- Open both endpoints in the browser and read the JSON that comes back.
Warm-Up · Which URLs Look RESTful?
5 minLast lesson you moved secrets into a .env file. Now look at four candidate URLs for a students API. Read them, then predict:
GET /api/students
GET /getStudents
GET /api/students/7
GET /fetchStudentById?id=7Predict together
Two of these look like a thing you can point at. Two read like a command. Which two feel neat and predictable — and why?
Reveal
The neat pair is /api/students and /api/students/7. Both name a noun — the students, and one student. REST likes nouns in the URL. The action word lives in the HTTP method (GET here), not the path. So /getStudents and /fetchStudentById double up the verb — REST leaves that out.
New Concept · A Library Catalogue for Your Data
12 minThink of a library catalogue. Every book has a fixed address on a shelf, and you interact with it using a small set of standard actions — borrow, return, look up. You never invent a new verb per book.
A REST API works the same way. Each kind of data is a resource — a noun like students or dishes. Each resource has a fixed address — an endpoint — and you reach it with the same small set of standard actions.
Two plain-English definitions to hold onto:
- API — a doorway one program uses to ask another program for data or actions.
- REST — an agreed style for building web APIs: resources as nouns, reached over HTTP, swapping JSON.
The syntax box
A resource route names a noun and returns its data as JSON. Here is the smallest useful shape:
const students = [
{ id: 1, name: 'Aisyah', form: 3 },
{ id: 2, name: 'Wei Jie', form: 4 },
]
app.get('/api/students', (req, res) => {
res.json(students)
})One endpoint, one noun, one JSON reply. The verb GET means “read” — it lives in the method, not the URL.
Verbs and JSON, side by side
The resource (noun)
Lives at an endpoint, e.g. /api/students.
All students together; one student at /api/students/1.
Named with a plural noun, never a verb.
The exchange (JSON)
The server replies with res.json(...).
Same format the client already knows how to read.
Today only GET (read); other verbs come next lesson.
Why it matters
The apps you use every day are built this way. Shopee and GrabFood are front-ends — a React site or a phone app — talking to REST APIs like this one. Learn the pattern once, and every backend you meet reads the same.
Worked Example · A Students Resource
12 minWe will build one read-only resource end to end. Make a file called server.js and follow along. Run it any time with node server.js.
Step 1 — An in-memory list of students
Set up Express and a plain array. Each student is an object with an id, a name, and a school form:
const express = require('express')
const app = express()
const students = [
{ id: 1, name: 'Aisyah', form: 3 },
{ id: 2, name: 'Wei Jie', form: 4 },
{ id: 3, name: 'Priya', form: 3 },
]
app.listen(3000, () => {
console.log('Server on http://localhost:3000')
})Add the two routes below above the app.listen line.
Step 2 — GET the whole resource
One endpoint returns the full array as JSON:
app.get('/api/students', (req, res) => {
res.json(students)
})Open http://localhost:3000/api/students. You see:
[
{ "id": 1, "name": "Aisyah", "form": 3 },
{ "id": 2, "name": "Wei Jie", "form": 4 },
{ "id": 3, "name": "Priya", "form": 3 }
]Step 3 — GET one student by id
The :id part is a placeholder in the endpoint. We read it, find the matching student, and reply 404 if there is none:
app.get('/api/students/:id', (req, res) => {
const id = Number(req.params.id)
const student = students.find((s) => s.id === id)
if (!student) {
return res.status(404).json({ error: 'Student not found' })
}
res.json(student)
})Open http://localhost:3000/api/students/2:
{ "id": 2, "name": "Wei Jie", "form": 4 }Ask for a student who is not there, like /api/students/9:
{ "error": "Student not found" }Step 4 — Read the JSON in the browser
Open both endpoints in your browser and read the replies. The whole list sits at /api/students; one student sits at /api/students/1. Same noun, two useful views.
What changed? You have a working REST resource. One noun, students, lives at one endpoint, and GET reads it two ways — all of them, or one by id.
Try It Yourself
13 minModel a brand-new resource of your own — dishes. Keep working in server.js, restart with node server.js after each change, then check the browser.
Task 1 — A dishes resource, GET all
Add a second array called
dishes, each with anid, aname, and apricein RM. Then addGET /api/dishesreturning the whole array withres.json(...).const dishes = [ { id: 1, name: 'Nasi lemak', price: 5.5 }, { id: 2, name: 'Roti canai', price: 1.5 }, ]Task 2 — GET one dish by id
Add
GET /api/dishes/:id. Readreq.params.id, find the matching dish, and reply404with a JSON message when there is no match. Test a hit, like/api/dishes/1, and a miss.Task 3 — A count endpoint
Add
GET /api/dishes/countthat returns{ count: dishes.length }as JSON. Place it above the/api/dishes/:idroute, otherwise:idcatches the wordcountfirst.{ "count": 2 }
Mini-Challenge · The Canteen Menu API
8 minDesign and build a read-only REST resource for a canteen menu. First list your endpoints on paper as nouns, then implement GET all and GET one by id. This joins today's REST idea with res.json from earlier.
It works if: /api/menu returns the whole menu as a JSON array, and /api/menu/1 returns a single item.
Reveal a sample answer
First, the endpoint plan — nouns only, verb in the method:
| Method | Endpoint | Returns |
|---|---|---|
GET | /api/menu | The whole menu as a JSON array |
GET | /api/menu/:id | One item, or a 404 JSON message |
Then the implementation:
const menu = [
{ id: 1, name: 'Mee goreng', price: 4.0 },
{ id: 2, name: 'Kaya toast', price: 2.5 },
{ id: 3, name: 'Milo ais', price: 3.0 },
]
app.get('/api/menu', (req, res) => {
res.json(menu)
})
app.get('/api/menu/:id', (req, res) => {
const id = Number(req.params.id)
const item = menu.find((food) => food.id === id)
if (!item) {
return res.status(404).json({ error: 'Item not found' })
}
res.json(item)
})Opening /api/menu/2 shows:
{ "id": 2, "name": "Kaya toast", "price": 2.5 }Two endpoints, one noun. You designed the shape first, then let res.json do the sending.
Recap
3 min- An API is a doorway one program uses to ask another for data.
- REST is an agreed style for web APIs: nouns, HTTP, JSON.
- A resource is a noun (students, dishes) reached at an endpoint like
/api/students. - The client asks; the server answers with
res.json(...). - Today was read-only (
GET); the other verbs and full CRUD come next lesson.
New words
- API — a doorway one program uses to ask another for data or actions.
- REST — an agreed style for building web APIs around resources and HTTP.
- Resource — a kind of data, named as a noun (e.g. students).
- Endpoint — one URL your API answers, such as
/api/students. - Client / server — the asker and the answerer of each request.
Homework
4 min to brief · ~20 min to doRequired
- Pick an app you use — Shopee, GrabFood, Spotify. Write down five endpoints it might have, as nouns (for example
/api/orders,/api/restaurants/:id). - Build a small read-only resource API for one of them. Add
GETall andGETone-by-id withres.json(...). Take a screenshot of both JSON replies in the browser and bring it next lesson.
Optional stretch
- A REST API is often called stateless. In two sentences, write what you think that means for the server between two requests from the same client.