Own API with NodeJS and Express
Tags: webdev, javascript, programming, beginners
Published: 2023-12-13 19:02:38

![](https://blog.disane.dev/content/images/2023/12/own_api-with-nodejs-and-express_banner.jpeg)

In this day and age, APIs are the new "gold". They can be used to automate, retrieve or change many things. Many services offer APIs here. Some hide their APIs behind verifications (Meta I look at you 🥴) or are directly available for free. If you want to create your own API for your services, you quickly face the question of how to do it. In this article, I would like to build a small and simple API with you.

---

If you don't yet know what an API is, you should definitely take a look at my article and APIs as a whole 👇

[Understanding and using REST APIsAPIs: Ubiquitous and everyone uses them , albeit directly. But what are they for and how do they work? We explain 💡![](https://blog.disane.dev/content/images/size/w256h256/2023/11/--D---Logo-Black.png)Disane.dev - Personal tech blogMarco Franke![](https://blog.disane.dev/content/images/2023/11/rest_api-standard-erklart_banner-1.jpeg)](https://blog.disane.dev/rest-api-standard-erklart/)

---

## What is NodeJS?

In simple terms, NodeJS is JavaScript that runs as an application and is not just limited to websites. This makes it possible to build applications or entire server systems based on JavaScript. This is of course a blessing for experienced web developers and makes them feel much more comfortable in server environments than if they had to write C# or PHP. NodeJS is also platform-independent.

NodeJS is also suitable for small scripts that were "previously" written in Powershell, Bash/Batch or Python.

For my part, I love NodeJS and am very happy that JavaScript has now managed to establish itself as an application and server language. If you want to learn more about NodeJS, I recommend the documentation for [NodeJS](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs).

## Fundamental considerations 🤔

First of all, you need to think about what exactly you want to do. In this guide, we will only cover a small use case. In this case, Express provides our web server.

First, let's assume we just want to return a random name from a fixed list. To achieve this, we first set up a new NodeJS project.

## Our NodeJS project

In order to create NodeJS projects, you will of course need NodeJS. This should be installed in advance (I recommend the latest version, alternatively the latest LTS \[long term service\]).

Once everything is installed, we can create a new folder somewhere and execute the following command:

```bash
npm init
```

### NPM

NPM in this case is nothing other than the [Node Package Manager](https://www.npmjs.com/), with which you can create and provide your own packages, as well as install and use other libraries. In this case, we create a new package. The command then guides you through the setup:

![](https://blog.disane.dev/content/images/2023/12/image-8.png)

If you look at the project now, you will see that only one `package.json` file was created. It is the linchpin for your NodeJS project:  

![](https://blog.disane.dev/content/images/2023/12/image-9.png)

## Install and use Express 🚂

Since Express is a third-party web server library, we now need to install it. NPM also offers a command for this:

```bash
npm install express
```

```json
{
  "name": "nodejs-express-simple-api",
  "version": "0.0.1",
  "description": "Simple NodeJS and Express REST-API",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Marco Franke",
  "license": "MIT",
  "dependencies": {
    "express": "^4.18.2"
  }
}
```

These are your project dependencies. If you also want to publish your project on NPM, these will also be installed when the user installs your project (with `npm install`). There are also `devDependencies`. These are packages that are only needed at development time, e.g. Linter or other tools. You can also see that there is now a folder `node_modules`. This is where all your installed NPM packages are stored. This folder can tend to be large and is not shared with all other projects!

What we are still missing is a file that is to be executed. In the setup of `npm init`, a file was also suggested that should serve as the entry point. In the standard case, this is `index.js`. We now create this file and open the project with [Visual Studio Code](https://code.visualstudio.com/) (not necessary, but I love VS Code ❤️).

## We write your first web server

When the project is now open, you grab the `index.js`and first import the `express` package:

```js
const express = require('express');
```

This allows us to access and use everything from Express. Now we instantiate a new instance of Express and assign a port to the web server (3000 is the standard NodeJS port, by convention, but can be changed as required):

```js
const app = express();
const port = 3000;
```

All we need to do now is start the server and specify a route on which the server "listens" and provides content. We can do this quite easily with:

```js
app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})
```

Now we have a web server that listens to port `3000` and returns the content `Hello World!` on the root route `/`.

You can then simply start the web server with the command:

```bash
node index.js
```

💡

In Visual Studio Code, you can simply press F5 and select NodeJS as the project. The project will then start automatically and you can even debug it with breakpoints.

![](https://blog.disane.dev/content/images/2023/12/image-10.png)

If you now surf to your page with `http://localhost:3000/`, you should see "Hello World".

![](https://blog.disane.dev/content/images/2023/12/image-11.png)

With this you have now written your first web server 🎉

![](https://blog.disane.dev/content/images/2023/12/HappyDanceGIF.gif)

## The path to our own API 🛣️

But now we want to provide a REST API that randomly returns us any names.

```js
app.get('/generate/names', (req, res) => {
    res.send('Hello Names!');
});

```

We want to use JSON as the return and not provide any data directly to the browser (as a website). To do this, we now have to tell Express that it should please give us the return as `application/json`. Express also offers a function for this purpose `res.json()`. `Res` is the response that is sent to the browser. We can simply pass the object to it and it is sent to the browser as JSON.

```js
app.get('/generate/names', (req, res) => {

    // list of random names
    names = ["John", "Paul", "George", "Ringo"];
    
    // get random index
    let randomIndex = Math.floor(Math.random() * names.length);

    // return random name
    res.json({ randomName: names[randomIndex]});
});
```

If we now open `http://localhost:3000/generate/names`, we get our random name as JSON from our API:

![](https://blog.disane.dev/content/images/2023/12/image-12.png)

### Passing parameters to the API

Currently, we open the API via browser, i.e. the HTTP method `GET`.

---

I have already mentioned these HTTP methods in my article about REST APIs. If you haven't read the article yet, take a look 👇

[Understanding and using REST APIsAPIs: Ubiquitous and everyone uses them , albeit directly. But what are they for and how do they work? We explain 💡![](https://blog.disane.dev/content/images/size/w256h256/2023/11/--D---Logo-Black.png)Disane.dev - Personal tech blogMarco Franke![](https://blog.disane.dev/content/images/2023/11/rest_api-standard-erklart_banner-1.jpeg)](https://blog.disane.dev/rest-api-standard-erklart/)

---

If we now want to give the API parameters, we only have two options:

* Route parameters
* Query string parameters

Both types are specified via the address, but are anchored differently.

### Route parameters

`Route parameters` are also passed via the address line, but are not added to the end of the address, but are an integral part of the address itself:

```http
GET http://test.xyz/[parameter]/
```

If we now change our code so that we want to differentiate between male and female names, we could do this via this. Express also offers a solution for this, as we can read the `request` to the API. Route parameters are specified in `app.get()`in the first parameter with  
`:[parameter name]`:

```js
app.get('/generate/names/:gender', (req, res) => {
    const gender = req.params.gender;

    // list of random names with gender
    const names = [
        { name: 'John', gender: 'male' },
        { name: 'Emma', gender: 'female' },
        { name: 'Michael', gender: 'male' },
        { name: 'Sophia', gender: 'female' },
        // Add more names with their genders here
    ];

    // get all names for a specific gender
    const genderNames = names.filter(name => name.gender == gender)
  
     // get random index of named for specific gender
    let randomIndex = Math.floor(Math.random() * genderNames.length);

    // return random name object
    res.json({ randomName: genderNames[randomIndex]});
});
```

We can access the parameters with `req.params` and then extract the named parameter. Consequently, we would still have to check whether the transfer is `male` or `female` and, if not, exit with an error:

```js
if(!gender.includes('male', 'female')){
    res.status(500).send("Gender must be `male` or `female`")
}
```

So if we now surf to `http://localhost:3000/generate/names/male`, we get this return:

![](https://blog.disane.dev/content/images/2023/12/image-13.png)

### Query string parameters

`Query string parameters` are added to the address at the end. You have probably seen an address like this before:

```http
GET http://google.com/?q=searchTerm
```

Everything after the `?` signals to the browser/server that parameters are now coming from here. These parameters consist of keys/values that are specified with `=`. Several parameters themselves are separated with `&`.

If we now want to include a search that only returns male or female names that contain a certain character, we can do this using these query string parameters. The parameter name `q` has become the standard for searches. We change the code as follows:

```js
app.get('/generate/names/:gender', (req, res) => {
    // get the gender param from the url
    const gender = req.params.gender;

    // get the search term from the query string
    const searchTerm = req.query.q;

    // check if gender is male or female, if not exit with 500 error
    if(!gender.includes('male', 'female')){
        res.status(500).send("Gender must be `male` or `female`")
    }

    // list of random names with gender
    const names = [
        { name: 'John', gender: 'male' },
        { name: 'Emma', gender: 'female' },
        { name: 'Michael', gender: 'male' },
        { name: 'Sophia', gender: 'female' },
        // Add more names with their genders here
    ];
    
    const genderNames = names.filter(name => name.gender == gender);
    const searchTermNames = genderNames.filter(name => name.name.includes(searchTerm));
     // get random index
    let randomIndex = Math.floor(Math.random() * searchTermNames.length);

    // return random name
    res.json({ randomName: searchTermNames[randomIndex]});
});
```

As you can see, we can retrieve the query string parameters with `req.params.q`. Let's try it out by calling the following URL: `http://localhost:3000/generate/names/male?q=Mi`

And indeed, we now get all male names that contain "Mi":

![](https://blog.disane.dev/content/images/2023/12/image-14.png)

## Passing complete data to the API 💾

Up to now, we have only passed data to the API via `GET`. However, if we now want to generate data (e.g. a blog article in a system), we have to pass entire data that would be too large for the address line. To do this, we use `POST` to transfer data to the API as `JSON`. This is no longer possible with the browser, so we have to use [cURL](https://curl.se/), [Postman ](https://www.postman.com/)or other API tools.

### Prepare endpoint

In order to receive data in our API, we have to prepare it accordingly. For example, let's assume we want to pass the list of names and gender to the API and it should simply return a random name for a gender.

To do this, we need to change our route from `app.get()`to `app.post()` (this is exactly how it would behave with `PUT`, `PATCH`, `DELETE`etc.):

```js
app.post('/generate/names/:gender', (req, res) => {
    // get the gender param from the url
    const gender = req.params.gender;

    // get the search term from the query string
    const searchTerm = req.query.q;
    

    // check if gender is male or female, if not exit with 500 error
    if(!gender.includes('male', 'female')){
        res.status(500).send("Gender must be `male` or `female`")
    }

    // list of random names with gender
    const names = [
        { name: 'John', gender: 'male' },
        { name: 'Emma', gender: 'female' },
        { name: 'Michael', gender: 'male' },
        { name: 'Sophia', gender: 'female' },
        // Add more names with their genders here
    ];
    
    const genderNames = names.filter(name => name.gender == gender);
    const searchTermNames = genderNames.filter(name => name.name.includes(searchTerm));
     // get random index
    let randomIndex = Math.floor(Math.random() * searchTermNames.length);

    // return random name
    res.json({ randomName: searchTermNames[randomIndex]});
});
```

And import, use and configure the `bodyParser` from Express:

```js
// put this underneath "const express = require('express');"
const bodyParser = require('body-parser')

// this should be right under declaring express and the port
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
```

We can then query the `body` of the request with `req.body`. The modified code would look like this:

```js
app.post('/generate/names/:gender', (req, res) => {
    // get the gender param from the url
    const gender = req.params.gender;

    // get the search term from the query string
    const searchTerm = req.query.q;


    // check if gender is male or female, if not exit with 500 error
    if(!gender.includes('male', 'female')){
        res.status(500).send("Gender must be `male` or `female`")
    }

    // get the body of the request with all names and genders
    const names = req.body;
    
    const genderNames = names.filter(name => name.gender == gender);
    const searchTermNames = genderNames.filter(name => name.name.includes(searchTerm));
     // get random index
    let randomIndex = Math.floor(Math.random() * searchTermNames.length);

    // return random name
    res.json({ randomName: searchTermNames[randomIndex]});
});
```

With `const names = req.body;` we now assign the body of our request to our variable `name`. However, this also means that we have to pass this and, above all, check that the body corresponds to our structure, otherwise the code would pop with error messages. But I'll leave that part to you 😉

If we now call our API like this and send it the expected body, we should also get our result, namely a name for a defined gender with "Mi" in the name:

![](https://blog.disane.dev/content/images/2023/12/image-15.png)

And lo and behold, it works 🎉

With the basics in place, you can now write your own APIs and make services available to the world. Welcome to the world of APIs 👨‍🚀

![](https://blog.disane.dev/content/images/2023/12/WelcomeMichaelScottGIF.gif)

---

If you like my posts, it would be nice if you follow my [Blog](https://blog.disane.dev) for more tech stuff.