How to Build a REST API in 10 Minutes: A Beginner's Guide
Learn how to build a REST API in 10 minutes with Node.js and Express. Step-by-step tutorial with code examples, testing tips, and best practices for beginners.
How to Build a REST API in 10 Minutes: A Beginnerβs Guide
If youβve been wondering how to build a REST API but donβt know where to start, youβre in the right place. In this tutorial, youβll go from zero to a fully working REST API in about 10 minutes β no prior backend experience required. Weβll use Node.js and Express, two of the most beginner-friendly tools for backend development, and walk through every step with complete working code.
By the end, youβll have a real API running on your machine that you can test, extend, and build on.
What Is a REST API?
Before we write any code, letβs make sure you understand what a REST API actually is β because the terminology can feel intimidating at first.
REST stands for Representational State Transfer. Itβs an architectural style for designing web services. A REST API (or RESTful API) is a way for two applications to talk to each other over HTTP β the same protocol your browser uses to load websites.
Think of a REST API as a waiter at a restaurant:
- You (the client) make a request β βIβd like the spaghetti carbonara.β
- The kitchen (the server) processes your request and sends back a response β your plate of pasta.
In technical terms:
- The client sends an HTTP request (GET, POST, PUT, DELETE) to a specific URL (called an endpoint).
- The server processes the request and returns data, usually in JSON format.
The Four Core HTTP Methods
REST APIs are built around four primary HTTP methods that map to four basic operations (often called CRUD):
| Method | Operation | Example |
|---|---|---|
| GET | Read | Fetch a list of users |
| POST | Create | Add a new user |
| PUT | Update | Update an existing user |
| DELETE | Delete | Remove a user |
Understanding these four methods is 80% of understanding REST APIs. Now letβs build one.
Prerequisites
To follow this tutorial, you need:
- Node.js installed β Download from nodejs.org. Install the LTS version.
- npm β It comes bundled with Node.js automatically.
- A code editor β VS Code is recommended.
- A terminal β Terminal on Mac/Linux, Command Prompt or PowerShell on Windows.
Thatβs it. No database setup, no cloud accounts, no complex configuration. Weβll keep everything simple and local.
To verify Node.js is installed, run:
node --version
npm --version
You should see version numbers printed. If you do, youβre ready to go.
Step 1: Set Up Your Project
Open your terminal and run the following commands to create a new project folder and initialize it:
mkdir my-rest-api
cd my-rest-api
npm init -y
The npm init -y command creates a package.json file with default settings. This file tracks your projectβs dependencies and configuration.
Next, install Express β the lightweight web framework weβll use to build our API:
npm install express
Youβll also want to install nodemon, a development tool that automatically restarts your server whenever you save a file:
npm install --save-dev nodemon
Now open your package.json file and add a start script under the scripts section:
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}
}
Your project structure should now look like this:
my-rest-api/
βββ node_modules/
βββ package.json
βββ package-lock.json
Step 2: Create Your First Express Server
Create a new file called index.js in your project root and add the following code:
const express = require('express');
const app = express();
const PORT = 3000;
// Middleware to parse JSON request bodies
app.use(express.json());
// Root route β just to confirm the server is running
app.get('/', (req, res) => {
res.json({ message: 'Welcome to my REST API!' });
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Now start the development server:
npm run dev
Open your browser and navigate to http://localhost:3000. You should see:
{ "message": "Welcome to my REST API!" }
Congratulations β you have a running server. Now letβs turn it into a real REST API.
Step 3: Build a Full CRUD REST API
Weβll build a simple Books API that lets you create, read, update, and delete books. In a production app, this data would come from a database β but for this tutorial, weβll store everything in memory (an array).
Replace the contents of index.js with the following complete implementation:
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json());
// In-memory "database"
let books = [
{ id: 1, title: 'The Pragmatic Programmer', author: 'Andrew Hunt', year: 1999 },
{ id: 2, title: 'Clean Code', author: 'Robert C. Martin', year: 2008 },
{ id: 3, title: 'You Don\'t Know JS', author: 'Kyle Simpson', year: 2015 },
];
let nextId = 4;
// βββββββββββββββββββββββββββββββββββββββββ
// GET /books β Retrieve all books
// βββββββββββββββββββββββββββββββββββββββββ
app.get('/books', (req, res) => {
res.json(books);
});
// βββββββββββββββββββββββββββββββββββββββββ
// GET /books/:id β Retrieve a single book
// βββββββββββββββββββββββββββββββββββββββββ
app.get('/books/:id', (req, res) => {
const id = parseInt(req.params.id);
const book = books.find(b => b.id === id);
if (!book) {
return res.status(404).json({ error: 'Book not found' });
}
res.json(book);
});
// βββββββββββββββββββββββββββββββββββββββββ
// POST /books β Create a new book
// βββββββββββββββββββββββββββββββββββββββββ
app.post('/books', (req, res) => {
const { title, author, year } = req.body;
if (!title || !author || !year) {
return res.status(400).json({ error: 'title, author, and year are required' });
}
const newBook = { id: nextId++, title, author, year };
books.push(newBook);
res.status(201).json(newBook);
});
// βββββββββββββββββββββββββββββββββββββββββ
// PUT /books/:id β Update an existing book
// βββββββββββββββββββββββββββββββββββββββββ
app.put('/books/:id', (req, res) => {
const id = parseInt(req.params.id);
const bookIndex = books.findIndex(b => b.id === id);
if (bookIndex === -1) {
return res.status(404).json({ error: 'Book not found' });
}
const { title, author, year } = req.body;
books[bookIndex] = { id, title, author, year };
res.json(books[bookIndex]);
});
// βββββββββββββββββββββββββββββββββββββββββ
// DELETE /books/:id β Delete a book
// βββββββββββββββββββββββββββββββββββββββββ
app.delete('/books/:id', (req, res) => {
const id = parseInt(req.params.id);
const bookIndex = books.findIndex(b => b.id === id);
if (bookIndex === -1) {
return res.status(404).json({ error: 'Book not found' });
}
books.splice(bookIndex, 1);
res.status(204).send();
});
// βββββββββββββββββββββββββββββββββββββββββ
// Start the server
// βββββββββββββββββββββββββββββββββββββββββ
app.listen(PORT, () => {
console.log(`Books API running at http://localhost:${PORT}`);
});
Save the file. Nodemon will automatically restart the server.
What This Code Does
Letβs walk through each endpoint:
GET /booksβ Returns the full list of books as a JSON array.GET /books/:idβ Returns a single book by its ID. Returns a 404 error if not found.POST /booksβ Accepts a JSON body withtitle,author, andyear. Validates the input, creates a new book, and returns it with a201 Createdstatus.PUT /books/:idβ Replaces a bookβs data entirely. Returns 404 if the book doesnβt exist.DELETE /books/:idβ Removes a book from the list and returns204 No Content.
Notice that weβre using proper HTTP status codes throughout. This is an important REST API convention. Not sure what a specific status code means? Check out the HTTP Status Codes reference β it covers every code with plain-English explanations.
Step 4: Test Your REST API
Now that your API is running, you need to test it. You have a few options.
Option 1: Use curl (Command Line)
If youβre comfortable with the terminal, curl is the fastest way to test endpoints:
# Get all books
curl http://localhost:3000/books
# Get a single book
curl http://localhost:3000/books/1
# Create a new book
curl -X POST http://localhost:3000/books \
-H "Content-Type: application/json" \
-d '{"title": "JavaScript: The Good Parts", "author": "Douglas Crockford", "year": 2008}'
# Update a book
curl -X PUT http://localhost:3000/books/1 \
-H "Content-Type: application/json" \
-d '{"title": "The Pragmatic Programmer", "author": "Andrew Hunt & David Thomas", "year": 2019}'
# Delete a book
curl -X DELETE http://localhost:3000/books/2
Option 2: Use the API Request Builder
If you prefer a visual interface, use the API Request Builder to test your API endpoints directly in the browser. It lets you configure HTTP methods, set headers, and write request bodies without touching the terminal β perfect for beginners learning how to build a REST API.
Option 3: Use Postman or Insomnia
For a more full-featured testing experience, tools like Postman and Insomnia let you save your requests, organize them into collections, and share them with teammates.
Expected Responses
Hereβs what you should see when you test each endpoint:
GET /books β returns an array:
[
{ "id": 1, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "year": 1999 },
{ "id": 2, "title": "Clean Code", "author": "Robert C. Martin", "year": 2008 },
{ "id": 3, "title": "You Don't Know JS", "author": "Kyle Simpson", "year": 2015 }
]
POST /books with a new book β returns the created object with status 201:
{
"id": 4,
"title": "JavaScript: The Good Parts",
"author": "Douglas Crockford",
"year": 2008
}
GET /books/99 (non-existent) β returns status 404:
{ "error": "Book not found" }
When youβre comparing API responses across different test runs, the JSON Diff Viewer is incredibly handy for spotting exactly what changed between two response bodies.
Step 5: Add Error Handling Middleware
A production-quality REST API needs a centralized error handler. Without one, unhandled errors will crash your server or leak stack traces to users.
Add this at the bottom of your index.js, just before app.listen:
// 404 handler for unknown routes
app.use((req, res) => {
res.status(404).json({ error: `Route ${req.method} ${req.path} not found` });
});
// Global error handler
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong. Please try again.' });
});
The 404 handler catches any request that doesnβt match your defined routes. The global error handler catches any uncaught exceptions thrown inside your route handlers β just pass the error to next(err) from any route and this middleware will handle it.
REST API Best Practices for Beginners
Now that you know how to build a REST API, letβs cover the principles that separate a good API from a bad one. These habits will save you hours of debugging down the road.
1. Use Nouns for Resource Names, Not Verbs
Bad:
GET /getBooks
POST /createBook
DELETE /deleteBook/1
Good:
GET /books
POST /books
DELETE /books/1
The HTTP method already describes the action. Your URL should describe the resource, not the action.
2. Always Return Appropriate HTTP Status Codes
Status codes communicate intent. Donβt return 200 OK for errors, and donβt return 400 Bad Request when something is missing on the server side.
Common codes to know:
200 OKβ Successful GET or PUT201 Createdβ Resource successfully created via POST204 No Contentβ Successful DELETE (no body to return)400 Bad Requestβ Client sent invalid data401 Unauthorizedβ Authentication required403 Forbiddenβ Authenticated but not allowed404 Not Foundβ Resource doesnβt exist500 Internal Server Errorβ Something broke on the server
Refer to the HTTP Status Codes reference whenever youβre unsure which code to use.
3. Version Your API
As your API evolves, youβll need to make breaking changes. Without versioning, youβll break existing clients the moment you change a response shape. Add a version prefix from day one:
/v1/books
/v1/books/:id
That way, when you release v2, old clients can keep using /v1 while new clients use /v2.
4. Validate Input Early
Never trust data coming from the client. Always validate request bodies before processing them. In the example above, we checked for required fields manually. For larger projects, consider a validation library like Joi or Zod:
npm install joi
const Joi = require('joi');
const bookSchema = Joi.object({
title: Joi.string().min(1).max(200).required(),
author: Joi.string().min(1).max(100).required(),
year: Joi.number().integer().min(1000).max(2100).required(),
});
app.post('/books', (req, res) => {
const { error, value } = bookSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
// proceed with validated `value`
});
5. Use Consistent JSON Response Shapes
Clients are much easier to write when your API always returns predictable shapes. Consider wrapping all responses in a consistent envelope:
{
"success": true,
"data": { ... },
"error": null
}
Or for errors:
{
"success": false,
"data": null,
"error": "Book not found"
}
Pick a shape and stick to it across your entire API.
6. Never Expose Sensitive Data
Never return passwords, API keys, or internal IDs in API responses. Even in development, build the habit of explicitly selecting which fields to return:
// Bad β returning everything from the database record
res.json(userFromDatabase);
// Good β explicitly selecting safe fields
const { id, name, email } = userFromDatabase;
res.json({ id, name, email });
Where to Go From Here
You now know how to build a REST API from scratch using Node.js and Express. The foundation youβve built β routes, HTTP methods, status codes, JSON responses, and input validation β applies to every REST API youβll ever build, regardless of language or framework.
Here are natural next steps to level up:
- Connect a real database β Try SQLite (easiest) or PostgreSQL with the
pglibrary. Replace the in-memory array with actual database queries. - Add authentication β Learn JWT (JSON Web Tokens) for stateless authentication. The
jsonwebtokenandbcryptlibraries make this straightforward. - Use environment variables β Never hardcode ports, database URLs, or secrets. Use the
dotenvpackage to load config from a.envfile. - Write automated tests β Learn Jest and Supertest to write tests that verify your API endpoints automatically.
- Deploy your API β Try Railway, Render, or Fly.io for free hosting. All three support Node.js with minimal configuration.
Try It Free at DevPlaybook.cc
Building and testing REST APIs is much smoother with the right tools in your corner. At devplaybook.cc, youβll find a free suite of developer tools built exactly for moments like this:
- API Request Builder β Send HTTP requests to any endpoint directly from your browser. No setup required. Perfect for testing the API you just built.
- HTTP Status Codes Reference β Look up any status code instantly with plain-English explanations and usage guidance.
- JSON Diff Viewer β Paste two JSON objects side by side and immediately see every difference. Essential when debugging API responses.
All tools are free, run in your browser, and require no account. Whether youβre just learning how to build a REST API or youβre a senior engineer who needs a quick reference, DevPlaybook has you covered.
Try it free at devplaybook.cc β no sign-up needed.
Summary
Hereβs what you accomplished in this tutorial:
- Learned what a REST API is and how the HTTP method + endpoint pattern works
- Set up a Node.js + Express project from scratch
- Built a complete CRUD API with GET, POST, PUT, and DELETE endpoints
- Added proper HTTP status codes and error handling
- Tested the API using curl and browser tools
- Learned six best practices that separate good APIs from bad ones
The same steps you followed here β create a server, define routes, handle requests, return JSON β are the foundation of every REST API in production today. Now go build something.
Free Newsletter
Level Up Your Dev Workflow
Get new tools, guides, and productivity tips delivered to your inbox.
Plus: grab the free Developer Productivity Checklist when you subscribe.
Found this guide useful? Check out our free developer tools.