Stand Up a Node.js REST API in Just 9 Minutes

Quickly include CRUD operations, error handling, sorting, and filtering in your REST API today

Ryan Gleason
Jan 29 · 9 min read
Image for post
Image for post
Photo by nappy from Pexels

I’m going to try to make this as simple as possible. I’ve spent a ton of time trying to find a simple, working, easy to follow example of a REST API performing CRUD operations, error handling, sorting, and filtering in Node.js and have failed to do so.

Environment Setup

OK, let’s get started! First, let me explain the tools we’ll be using:

  • Node.js — an open-source JavaScript runtime environment that allows you to run code outside of a browser. We will be developing our RESTful API in JavaScript on a Node.js server
  • MongoDB — the database we will be writing our data to
  • Postman — the tool we will be using to test our API
  • VSCode — you can use any text editor you want but I will be using this because it’s my favorite

If you don’t have any of these tools set up, I have created an accompanying piece walking you through the steps: Node.js REST API Environment Setup

Table of Contents

Today we’re going to tackle all of the basics in creating a REST API. These basics include:

Introduction to REST API

You hear about REST API everywhere in today's technology world, but what is it? For starters, API stands for Application Programming Interface.

What is the point of an API? It allows two pieces of software to talk to one another. There are many types of APIs — SOAP, XML-RPC, JSON-RPC — but today we’ll be talking about REST.

What is REST? It stands for Representational State Transfer. It is a software architecture style that is used for creating web services. REST has made it easy for computer systems to communicate with one another via the internet.

How does it work? Pretty similar to how you type “rest api” into Google and the search results are returned. At the highest level, a client makes a call (request) in the form of a URL to a server requesting some data. Below is an example of a google search for “rest API”:

The server then responds with the data (response) over the HTTP protocol. This data appears in JSON notation and is converted into an aesthetically pleasing visual in your browser — your google search results.

In short, you send a request in the form of a URL and receive a response in the form of data.

How is this data normally received? JSON (Javascript Object Notation) describes your data in key-value pairs. JSON makes reading the data easy both machines and humans.

Let’s dive into the requests a little more.


First, it’s important to understand that requests are made of up four parts.

  • Endpoint The URL you are requesting for. Typically made up of a root and a path. E.g., where the root is and the path is /search?q=rest+api. More on this below.
  • Method— The type of request you send to the server, or “HTTP verb”. This is how we’re able to execute our CRUD (Create, Read, Update or Delete) operations. The five types are GET, POST, PUT, PATCH and DELETE.
  • Headers Additional information that can be sent to the client or server that is used to assist your data in some way. For example, it can be used to authenticate a user so the data can be viewed. Or it can tell you how the data should be received (application/JSON).
  • Data (body) — The information we want to receive from our request as a JSON.

More on endpoints: We will be dealing with these strings a lot, so it’s important that we understand them. Here are the kinds of things you may see in an endpoint:

  • Colon (:) — Used to indicate a variable in the string. In API docs you will see endpoints with :username (or something similar). Just know that when you test it out, you should replace that username with an actual username. Example of a fake medium endpoint: 
  • Question mark (?) — Begins the query parameters. Query parameters are sets of key-value pairs that can be used to modify your requests. Here’s an example of a Medium endpoint in which I want to see my articles and whether they’ve been published or not:
  • Ampersand (&) — Used to separate query parameters when you want to use multiple. For example, we can see articles by me that are published and posted today.

Enough of the conceptual stuff, let’s dive into the coding! I’ll first show you the basics of creating a REST API. It will be made up of four parts:

  • Server — Used to establish all of the connections we need, as well as defining important information such as endpoints, ports, and routing.
  • Model — What does our data look like?
  • Routes — Where do our endpoints go?
  • Controller — What do our endpoints do?

Setting Up Our Server


Let me explain what’s happening here:

  • Express — The web application framework for Node.js. This starts a server and listens for connections on port 3000.
  • Mongoose—Assists us in object modeling for MongoDB. It helps to manage relationships between data, validates schema, and is overall useful in communicating from Node.js to MongoDB.
  • bodyParser—Is needed to interpret requests. Works by extracting the body portion of an incoming request and exposes it as req.body and as a JSON.
  • Entry—This is the name of our schema. We need to include this in our server.js because the schema must be “registered” for each model we use.
  • mongoose.connect(uri string, {options}) — Establish a connection to our MongoDB Atlas database. We set these options to eliminate deprecation warnings.
  • routes(app): — Defines how an application’s endpoints will respond to client requests. This will point to the routes we define ourselves.

Now we’re going to create our model, routes, and controller. This is what my project directory structure looks like:

Image for post
Image for post

Create the Model


I’ve created a basic model, only containing three fields. It’s important to understand that we’re using a Mongoose schema. Each schema maps to a MongoDB collection and defines the structure of the documents within that collection. Then you will see at the end we are exporting our schema, called Entry, and exposing it to the rest of our application.

Each Entry will represent a different record in our leaderboard where an Entry is the player name, score and whether they’re registered.

Define our Routes


The routes will define what happens when a user hits one of our endpoints. It’s also how we determine which CRUD operation is used to interact with the data in our database.

  • POSTCreate an entry
  • GETRead an entry
  • PUTUpdate an entry
  • DELETEDelete an entry

Build the Controller

Our Controller

Here we have the logic. So WHAT is happening when our routes are hit. This is the bare minimum you need for a fully functioning API. Each one of these methods corresponds with a route — you’ll notice all of the names are the same as the routes.

Each of these methods takes in two parameters: the request and the response (req, res). We then use the Mongoose method that coincides with the operation we are trying to implement. For example, for a GET request, we want to find all the documents and return them as a response JSON object. To do so, we use the find() method.

The same goes for POST. We want to create a record so we use the Mongoose method, save(), to write that record to the database.

Checkpoint: To ensure that we are correctly writing to the database, let’s perform a POST request in Postman.

Image for post
Image for post

This is what my POST request will look like sent to localhost:3000/entries. Here’s the response you should get on hitting the Send button:

Image for post
Image for post

A GET request to localhost:3000/entries will receive all of the documents in our database as a response.

A GET request to localhost:3000/entries/:entryId (example from above: localhost:3000/entries/5e3022ecbf5a6646209325b2) will return just a single record.

A PUT request sent to localhost:3000/entries/:entryId will update the entry with whatever you put in the body.

A DELETE request sent to localhost:3000/entries/:entryId will delete the specified entry.

I think you get the idea. What’s missing from this? Proper error handling. Since we made the player and score fields required, the response will be an error if one of those two fields isn’t entered. We need a way to handle this gracefully.

Error Handling

For error handling with REST API’s, we are going to use try-catch statements. We are going to “try” to make the request and if that fails we will “catch” the error. This is a way to gracefully handle errors. Below are the types of errors you may find when creating an API request:

  • 100 level (informational) — The server acknowledges a request.
  • 200 level (Successful) — The server completed the request.
  • 300 level (Redirect) — The client needs to do more to complete the request.
  • 400 level (Client Error) —The client sent an invalid request.
  • 500 level (Server Error) — The server failed to complete the request due to server error.

Checkpoint: Let’s send in a bad request so we can see if our error handling works. I’ll post before and after error handling so you can see the difference.

In the request, I’m just going to remove the player field. This will trigger an error since it’s a required field:

Image for post
Image for post

Before error handling:

Image for post
Image for post

In Postman, before adding error handling, the server will just keep trying to send the request. It has nothing to catch the error with, so it will eventually time out and you won’t know what’s wrong with your request.

In your console you’ll just see this messy output:

Image for post
Image for post

But when we add error handling we just get this simple response:

Image for post
Image for post

Much better!


As this is a leaderboard, we want to sort in descending order by score. We take the sort parameter out of the URL string, check if it’s true, and then execute a simple sort.

We only have to update our read_entries method:

We take the sort variable out of our URL query string. The way we access this is req.query.sort.

Checkpoint: Before our sort, our output should look something like this when performing a GET request:

Image for post
Image for post

After adding sort=true to our endpoint:

Image for post
Image for post

It should look like this:

Image for post
Image for post

It’s been sorted in descending order!


We now want to display only the registered entries. How do we do that? By adding a filter. Again, for simplicity's sake, we are going to only modify the read_entries method.

We take the registered variable down from the URL and if it’s equal to “yes”, then we filter out all entries that aren’t registered.

Checkpoint: Before adding the filter, the results of the GET request will look like this:

Image for post
Image for post

After adding registered=yes to the endpoint:

Image for post
Image for post

The response should look like this:

Image for post
Image for post

That’s it! You’ve successfully filtered your data from the back end.


In this tutorial, you have learned how to successfully:

  • Create a REST server
  • Perform CRUD operations
  • Gracefully handle errors
  • Sort your data using query parameters
  • Filter your data using query parameters

I hope this was helpful! If you have any questions, comments or concerns please don’t hesitate to reach out.

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store