API Design | Apr 25, 2025 | 11 min read
Learn how to build a simple REST API that returns JSON responses using Node.js and Express. This step-by-step guide walks you through project setup, creating routes, handling different HTTP methods, and testing your endpoints—perfect for beginners diving into API development.
APIs are fundamental tools that allow diverse systems to interact and exchange data reliably. REST APIs, built upon HTTP standards, enable developers to create backend services that are both practical and maintainable. JSON, known for its concise and structured format, has become the preferred choice for data interchange.
In this post, you'll learn how to build a simple REST API with JSON responses, covering essential steps from project setup to dynamic endpoint creation. This guide is designed to provide you with clear, actionable insights to enhance your development workflow.
A REST (Representational State Transfer) API is an architectural style that uses HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on resources. These resources are often represented in JSON format.
JSON (JavaScript Object Notation) has become the standard response format due to its simplicity, readability, and compatibility with many languages and frameworks. It is lightweight and allows developers to exchange data easily between the server and the client.
💡
Want to go beyond the basics? Treblle gives you real-time API insights, auto-generated docs, and tools to spot issues fast—so you can focus on building, not debugging.
Before you begin, ensure that you have the following tools and knowledge:
Basic Coding Experience: Familiarity with JavaScript (or Python if you prefer a different framework) is recommended to grasp the concepts and code examples.
Development Environment Setup:
Command-Line Interface: Basic competence in using the terminal or command prompt for running commands and managing your project.
Code Editor: Use a text editor or an Integrated Development Environment (IDE), such as Visual Studio Code, Sublime Text, or a similar tool.
These prerequisites ensure that you will be ready to quickly set up and run your REST API project without unnecessary delays.
In this section, I will explain how to prepare your project for building a REST API. The steps include creating a project directory, initializing your configuration, and installing the necessary dependencies. Below are detailed instructions for both Node.js with Express and Python with Flask.
Create a Project Directory: Open your terminal and create a new folder for your project. This keeps your API files organized.
1. Initialize the Project with NPM: Use npm init -y to initialize your project with default settings. This command generates a package.json file that manages your project’s metadata and dependencies.
mkdir simple-rest-api
cd simple-rest-api
2. The package.json
file is crucial—it keeps track of your project’s configuration, version, and any packages you install.
npm install express
package.json
under dependencies, making it easier to manage and deploy your project.mkdir simple-rest-api
cd simple-rest-api
python -m venv venv
On macOS/Linux:
source venv/bin/activate
On Windows:
venv\Scripts\activate
pip install Flask
Flask is a lightweight web framework ideal for creating REST APIs. Installing it in a virtual environment ensures that your project’s dependencies remain contained and manageable.
Whether you choose Node.js with Express or Python with Flask, the steps to set up your project involve:
These steps lay the foundation for building and scaling your REST API, ensuring a clean, organized environment as you progress to writing server code and defining endpoints.
To start building your REST API, the next step is to create a simple web server. Below is an example using Node.js with the Express framework. This server listens on a designated port and includes a basic “Hello World” route to confirm that your setup works.
Create a file named server.js
and include the following code:
// server.js
// Import the Express module
const express = require('express');
// Initialize an Express application
const app = express();
// Add middleware to parse JSON request bodies
app.use(express.json());
// Define the port; it uses the PORT environment variable if set or defaults to 3000
const PORT = process.env.PORT || 3000;
// Create a default route that responds with a simple greeting
app.get('/', (req, res) => {
res.send('Hello World from your API!');
});
// Start the server and listen on the specified port
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
express
module is required to leverage Express’s functionality. Initializing app
prepares your application to handle HTTP requests.app.get()
method sets up a GET request handler at the root URL ("/"
). Accessing this route responds with a simple text message confirming that your server is up.app.listen()
function initiates the server and listens for incoming HTTP requests. Once the server is running, a confirmation message is logged to the console.This basic server setup provides a solid foundation for adding more complex API endpoints and features as you build your REST API.
Below is a minimal example showing how to wire up a GET
endpoint in Express that returns structured JSON data, using app.get()
for routing and res.json()
to automatically set the Content-Type header to application/json
.
This basic pattern establishes a clear convention you can extend across POST
, PUT, DELETE
, and PATCH
routes, ensuring consistency in how your API handles and delivers JSON payloads.
Add the following code to your existing server.js
file to support all primary REST methods with JSON responses:
// Enable JSON body parsing
app.use(express.json());
// GET /api/greeting
app.get('/api/greeting', (req, res) => {
res.json({ message: 'Hello from your API!' });
});
// POST /api/greeting
app.post('/api/greeting', (req, res) => {
const { name } = req.body;
res.json({
message: `Hello, ${name || 'Guest'}! This greeting was created via POST.`
});
});
// PUT /api/user/:id
app.put('/api/user/:id', (req, res) => {
const userId = req.params.id;
const updates = req.body;
res.json({
userId,
updatedWith: updates,
message: `User ${userId} has been updated via PUT.`
});
});
// DELETE /api/user/:id
app.delete('/api/user/:id', (req, res) => {
const userId = req.params.id;
res.json({
userId,
message: `User ${userId} has been deleted via DELETE.`
});
});
// PATCH /api/user/:id
app.patch('/api/user/:id', (req, res) => {
const userId = req.params.id;
const partial = req.body;
res.json({
userId,
patchedWith: partial,
message: `User ${userId} has been partially updated via PATCH.`
});
});
Citations:
app.use(express.json())
) enables handling of POST
, PUT
, and PATCH
requests with JSON bodies citeturn2view0res.json()
for sending JSON responses citeturn0search0POST
handling example sourced from a practical Node.js guide citeturn0search18DELETE
route pattern demonstrated by GeeksforGeeks citeturn0search1PATCH
implementation reference from a community tutorial citeturn0search2You can create endpoints that handle dynamic inputs to expand the functionality of your API. In this section, you'll learn how to add a route that accepts parameters, allowing your API to respond with customized data based on user input.
Add the following code to your existing server.js
file:
// Define a route with a dynamic parameter for user details
app.get('/api/user/:id', (req, res) => {
const userId = req.params.id;
// In a real-world application, you'd fetch user details from a database here.
res.json({ userId: userId, message: `User with ID ${userId} found.` });
});
/api/user/:id
uses a colon (:
) to define a dynamic segment. Here, id
acts as a placeholder that Express extracts from the URL.req.params.id
. This enables the API to tailor its response according to the user's input.res.json()
method returns a JSON object that includes the extracted parameter. This example sends a message confirming the user ID, mimicking how a real application might return a user's details.By incorporating dynamic parameters into your routes, you can create more responsive and versatile APIs that cater to varied client requests. This approach lays the groundwork for handling more complex data-fetching operations, such as querying a database for user-specific details.
Verifying that your API endpoints function as expected is a crucial step in the development process. Here are several methods you can use to test your API:
http://localhost:3000/api/greeting
The browser should display the JSON response:
{ "message": "Hello from your API!" }
http://localhost:3000/api/user/1
This should display the JSON response with the dynamic parameter included:
{ "userId": "1", "message": "User with ID 1 found." }
curl http://localhost:3000/api/greeting
http http://localhost:3000/api/user/1
There are several API testing tools that you can use to test your APIs. Here are the three best tools with a developer-first approach to try:
{ "message": "Hello from your API!" }
HTTP Status Codes: Ensure the API returns the correct HTTP status code (e.g., 200 for successful GET requests). Some API testing tools display these status codes, allowing you to confirm that the responses are as expected.
By applying these testing methods, you can confidently verify that your API endpoints return the correct data and handle different types of requests properly.
This step helps ensure a smooth and reliable experience when other applications or clients interact with your API.
In this tutorial, I explained how to build a simple REST API using Node.js and Express. I covered how to set up your project, create a basic server with a “Hello World” route, and define static and dynamic endpoints that return JSON responses.
Moving forward, consider enhancing your API with the following improvements:
By incorporating these enhancements, you will build a more resilient and scalable system, ready for real-world applications. Continue refining your skills and exploring advanced topics to further enhance your API development expertise.
💡
Ready to take your API from basic to brilliant? Treblle helps you track performance, catch errors, and ship with confidence—all in real time.
Shadow APIs are invisible threats lurking in your infrastructure—undocumented, unmanaged, and often unsecured. This article explores what they are, why they’re risky, how they emerge, and how to detect and prevent them before they cause damage.
APIs are the backbone of modern software, but speed, reliability, and efficiency do not happen by accident. This guide explains what API performance really means, which metrics matter, and how to optimize at every layer to meet the standards top platforms set.
MCP servers are the backbone of intelligent, context-aware AI applications. In this guide, you’ll learn what sets the best ones apart, explore practical use cases, and get tips for building and deploying your own high-performance MCP server.