REST API Tutorial: Build and Use Your First API Step-by-Step
10 min read
A simple visual of how a client sends requests and receives JSON responses from a REST API.
Last updated: February 2026 ✅
REST APIs are how most apps “talk” to each other.
If you’ve ever used a mobile app to log in, a website to load products, or a game launcher to fetch your profile — there’s a very good chance a REST API was behind it.
This tutorial is for beginners who want a calm, practical, step-by-step path to:
- Understand what a REST API is (without confusing theory)
- Build a real API from scratch
- Test it with the right tools
- Use it from a frontend (browser) and from the command line
- Avoid common mistakes that break APIs
You don’t need to be advanced.
If you know basic JavaScript and how to run a terminal command, you can follow along.
✅ Key Takeaways
🌐 REST = Clear Rules
Resources + URLs + HTTP methods make APIs predictable.
🧪 Test Like a Pro
Use Postman, Insomnia, curl, and browser fetch to verify behavior.
🧱 Build CRUD Safely
Good status codes, validation, and error handling make APIs reliable.
🧭 Quick Navigation (Accordion)
👉 Click to open navigation
- 🌍 What Is a REST API?
- 🧠 How REST Works (Simple Mental Model)
- 🧰 Tools You’ll Use (Editor + Runtime + Tester)
- 🏗️ Build a REST API Step-by-Step (Node + Express)
- 🧪 Test Your API (Postman, curl, browser)
- 🖥️ Use Your API from a Frontend (fetch)
- 🧱 API Design Best Practices (Beginner Rules)
- ⚠️ Common REST API Mistakes
- 🧩 Exercises / Mini Projects
- ✅ REST API Checklist
- 🧠 Mini Quiz
- ❓ FAQ
🌍 What Is a REST API?
A REST API is a way for apps to exchange data over the internet using HTTP.
Think of it like a restaurant:
- You (client) order something
- The kitchen (server) prepares it
- The waiter (API) brings the result back in a predictable format
In API terms:
- Client = browser, mobile app, another server, or a tool like Postman
- Server = the backend that owns the data
- API = the agreed “menu” of endpoints (URLs) and rules
Most REST APIs return data as JSON, because it’s lightweight and easy to parse.
🧠 How REST Works (Simple Mental Model)
REST is easiest when you think in resources.
A resource is “a thing” your API manages:
- users
- posts
- products
- orders
Each resource has a URL, and you use HTTP methods to interact with it.

🔥 The 4 actions you’ll build (CRUD)
CRUD is the basic set of operations for most APIs:
- Create (add something new)
- Read (get data)
- Update (change data)
- Delete (remove data)
Here’s what CRUD usually looks like for a “tasks” resource:
| Action | HTTP Method | Endpoint Example | Meaning |
|---|---|---|---|
| Create | POST | /tasks | Create a new task |
| Read (all) | GET | /tasks | List tasks |
| Read (one) | GET | /tasks/:id | Get one task |
| Update | PUT / PATCH | /tasks/:id | Update a task |
| Delete | DELETE | /tasks/:id | Remove a task |
This pattern is what makes REST easy to learn and easy to maintain.
🧰 Tools You’ll Use (Editor + Runtime + Tester)
To build and test a REST API smoothly, you need three things:
1) Code editor
Use VS Code (simple and widely used).
2) Runtime to run JavaScript outside the browser
Use Node.js (it lets you run a server on your computer).
3) API testing tool
Use one of these:
- Postman (popular, beginner-friendly UI)
- Insomnia (simple UI, very clean)
- curl (built-in terminal tool)
You can use all three, but you only need one to start.
🏗️ Build a REST API Step-by-Step (Node + Express)
In this tutorial, we’ll build a simple Tasks API.
It will support CRUD:
- Create task
- List tasks
- Get task by id
- Update task
- Delete task
We’ll start with in-memory storage (an array) so you learn the API logic first.
Later, you can upgrade to a database.
Step 1: Create a project folder
Create a folder like:
rest-api-tutorial
Open it in VS Code.
Step 2: Initialize Node project
In your terminal inside the folder:
npm init -y
This creates a package.json file.
Step 3: Install Express
Express is a small framework for building APIs quickly.
npm install express
Step 4: Create server.js
Create a file named server.js and paste this:
const express = require("express");
const app = express();
const PORT = 3000;
// Middleware: allow JSON in request bodies
app.use(express.json());
// Health check route
app.get("/", (req, res) => {
res.json({ status: "ok", message: "REST API is running" });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
Now run:
node server.js
Open in your browser:
http://localhost:3000/
You should see JSON.
✅ Your API server is running.
🧪 Test Your API (Postman, curl, browser)

Before building real endpoints, learn a simple rule:
✅ Always test every route immediately after you create it.
Test with browser (GET only)
The browser is good for GET requests, like your / route.
Test with curl (fast terminal)
Try:
curl http://localhost:3000/
Test with Postman / Insomnia (best for CRUD)
Use Postman when you need:
- POST body JSON
- PUT/PATCH updates
- DELETE requests
- headers
🧩 Build CRUD Endpoints (Tasks API)
Now let’s create a simple in-memory “database” with an array.
Add this under the express.json() line:
let tasks = [
{ id: 1, title: "Learn REST basics", done: false },
{ id: 2, title: "Build my first API", done: false }
];
let nextId = 3;
✅ Endpoint list
| Goal | Method | Endpoint |
|---|---|---|
| List tasks | GET | /tasks |
| Get one task | GET | /tasks/:id |
| Create task | POST | /tasks |
| Update task | PUT | /tasks/:id |
| Delete task | DELETE | /tasks/:id |
1) GET /tasks (list all tasks)
Add:
app.get("/tasks", (req, res) => {
res.json(tasks);
});
What it does:
Returns an array of tasks as JSON.
Test:
curl http://localhost:3000/tasks
2) GET /tasks/:id (get one)
Add:
app.get("/tasks/:id", (req, res) => {
const id = Number(req.params.id);
const task = tasks.find(t => t.id === id);
if (!task) {
return res.status(404).json({ error: "Task not found" });
}
res.json(task);
});
Why 404 matters:
If something doesn’t exist, don’t return 200.
3) POST /tasks (create)
Add:
app.post("/tasks", (req, res) => {
const { title } = req.body;
if (!title || typeof title !== "string") {
return res.status(400).json({ error: "Title is required (string)" });
}
const newTask = { id: nextId++, title: title.trim(), done: false };
tasks.push(newTask);
res.status(201).json(newTask);
});
Key ideas here:
- We validate input
- We return 201 Created for a new resource
- We return the created object
Test with curl:
curl -X POST http://localhost:3000/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Write my API notes"}'
4) PUT /tasks/:id (update)
Add:
app.put("/tasks/:id", (req, res) => {
const id = Number(req.params.id);
const task = tasks.find(t => t.id === id);
if (!task) {
return res.status(404).json({ error: "Task not found" });
}
const { title, done } = req.body;
if (title !== undefined) {
if (typeof title !== "string" || !title.trim()) {
return res.status(400).json({ error: "Title must be a non-empty string" });
}
task.title = title.trim();
}
if (done !== undefined) {
if (typeof done !== "boolean") {
return res.status(400).json({ error: "Done must be boolean" });
}
task.done = done;
}
res.json(task);
});
Beginner note:
PUT often means “replace/update the resource.”
Many real APIs use PATCH for partial updates.
Here we allow partial updates for simplicity.
5) DELETE /tasks/:id (delete)
Add:
app.delete("/tasks/:id", (req, res) => {
const id = Number(req.params.id);
const index = tasks.findIndex(t => t.id === id);
if (index === -1) {
return res.status(404).json({ error: "Task not found" });
}
const deleted = tasks.splice(index, 1)[0];
res.json({ message: "Deleted", task: deleted });
});
📬 HTTP Status Codes You Actually Need

Beginners often return 200 for everything.
Don’t do that.
Here’s the practical beginner set:
| Code | Meaning | When to use |
|---|---|---|
| 200 | OK | Successful GET/PUT/DELETE |
| 201 | Created | Successful POST that created resource |
| 400 | Bad Request | Validation fails / missing required fields |
| 401 | Unauthorized | Missing/invalid auth |
| 403 | Forbidden | Auth ok, but not allowed |
| 404 | Not Found | Resource doesn’t exist |
| 500 | Server Error | Unexpected crash / unhandled error |
If you use these consistently, your API becomes easier to consume.
🖥️ Use Your API from a Frontend (fetch)
Now let’s use your API from a browser page.
Create a file: index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Tasks API Test</title>
</head>
<body>
<h1>Tasks</h1>
<button id="load">Load Tasks</button>
<pre id="out"></pre>
<script>
const out = document.getElementById("out");
document.getElementById("load").addEventListener("click", async () => {
const res = await fetch("http://localhost:3000/tasks");
const data = await res.json();
out.textContent = JSON.stringify(data, null, 2);
});
</script>
</body>
</html>
Open the HTML file in your browser.
If it fails due to CORS, add CORS support.
🧱 Fix CORS (Common Beginner Issue)
Browsers block requests between different origins by default.
To allow frontend calls, install CORS:
npm install cors
Then in server.js:
const cors = require("cors");
app.use(cors());
Now your frontend fetch should work.
🧱 API Design Best Practices (Beginner Rules)
These rules make your API clean and “future-proof.”
1) Use nouns for resources
Good:
/tasks/users
Avoid:
/getTasks/createTask
2) Keep responses consistent
If errors are JSON, keep them always JSON:
{ "error": "Task not found" }
3) Validate inputs every time
Never assume client sends correct JSON.
4) Don’t leak internal details
Avoid returning stack traces to users.
5) Version your API when it grows
Example:
/api/v1/tasks
You don’t need it today, but it’s a good habit later.
🧩 Exercises / Mini Projects
Practice makes APIs “stick” in your brain.
Try It Yourself: Add filtering
Goal: allow filtering by done status:
/tasks?done=true/tasks?done=false
Instructions:
- Read
req.query.done - If it exists, filter tasks
- Otherwise, return all
👉 Click here to see the solution
app.get("/tasks", (req, res) => { const done = req.query.done; if (done === undefined) { return res.json(tasks); } const doneBool = done === "true"; const filtered = tasks.filter(t => t.done === doneBool); res.json(filtered); }); Try It Yourself: Add a GET /stats
Goal: return how many tasks are done vs not done.
👉 Click here to see the solution
app.get("/stats", (req, res) => { const doneCount = tasks.filter(t => t.done).length; const pendingCount = tasks.length - doneCount; res.json({ total: tasks.length, done: doneCount, pending: pendingCount }); }); ⚠️ Common REST API Mistakes
| Mistake | Why it happens | Fix |
|---|---|---|
| Returning 200 for errors | “It works on my machine” mindset | Use correct status codes (400/404) |
| No validation | Trusting the client | Validate body and types |
| Inconsistent JSON | Random response shapes | Standardize success + error formats |
Forgetting express.json() | Body becomes undefined | Add app.use(express.json()) |
| CORS issues in browser | Different origins | Add cors() middleware |
| IDs treated as strings | Params are strings by default | Convert to Number() |
✅ REST API Checklist
✅ Click to open the checklist
- API runs locally on
http://localhost:3000 GET /returns a health JSONGET /tasksreturns an arrayGET /tasks/:idreturns 404 if missingPOST /tasksvalidates input and returns 201PUT /tasks/:idvalidates updatesDELETE /tasks/:iddeletes and returns confirmation- Status codes are correct (200/201/400/404)
- Errors return JSON consistently
- CORS is enabled if you use a browser frontend
🧠 Mini Quiz
❓ Which HTTP method is used to create a new resource?
POST
❓ What status code should you return after creating something?
201
❓ What does 404 mean?
The requested resource was not found.
❓ FAQ
Quick answers to common questions about this topic.
❓ What is the difference between REST API and a normal website?
A website returns HTML for humans to see. A REST API usually returns JSON for apps to consume.
❓ Do I need a database to build a REST API?
No. You can start with in-memory arrays to learn routes and logic, then upgrade to a database later.
❓ Is Express required to build REST APIs?
No, but Express makes routing and request handling much simpler for beginners.
❓ What is the best tool to test APIs?
Postman or Insomnia for full CRUD tests, and curl for quick terminal checks.
❓ What should I learn after this tutorial?
Input validation, environment variables, authentication, logging, and connecting a real database.
📚 Recommended Reading
- Frontend Basics Hub: HTML, CSS & JavaScript (Beginner Roadmap)
- React Beginner Guide: Learn React Step-by-Step from Scratch
- Git & Version Control Hub: Git, GitHub, Branching & Collaboration
- GitHub Tutorial for Beginners: How to Use GitHub Step-by-Step
- JavaScript Minifier Tool: Compress JS Safely for Faster Websites