Express Yourself with MongoDB: Your First API, No Tears Attached 😭➡️😄

Want to build your own REST API and connect it to MongoDB? You’re in the right place! In this tutorial, we’ll walk through creating a full CRUD API using Node.js, Express, and MongoDB (with Mongoose) — step by step, from scratch. If you are absolutel...

the_OldSchool_coder
Express Yourself with MongoDB: Your First API, No Tears Attached 😭➡️😄

Want to build your own REST API and connect it to MongoDB? You’re in the right place!

In this tutorial, we’ll walk through creating a full CRUD API using Node.js, Express, and MongoDB (with Mongoose) — step by step, from scratch.

If you are absolutely new to Rest API and it’s hand on then you can check out my blog like Rest API basics and Rest API hands on( with no db ) .

This is not a mongo DB crash course but a hands on guide to make REST api with B-son database ie. mongoDB


What We’ll Build

We’ll create a simple Product API where you can:

Create a product
Read all or single products
Update a product
Delete a product


Prerequisites

Make sure you have these installed:

  • Node.js + npm

  • MongoDB (local or MongoDB Atlas)

  • VS Code or any code editor


Project Setup

1. Initialize a Node project

mkdir api-mongodb
cd api-mongodb
npm init -y

2. Install dependencies

npm install express mongoose dotenv
npm install nodemon --save-dev

Update package.json:

"scripts": {
  "dev": "nodemon index.js"
}

or Just Grab my starter kit and start the tutorial

A reusable boilerplate? 👉 api-boilerplates GitHub


Setup the Server

3. Create index.js

import express from "express";
import mongoose from "mongoose";
import dotenv from "dotenv"
import productRouter from "./routes/productRoutes.js";
import catagoryRouter from "./routes/catagoryRoutes.js";

dotenv.config()
const app = express()
app.use(express.json())

const mongoURI = process.env.mongo_string_url

mongoose.connect(mongoURI)

mongoose.connection.on("connected", () => {
  console.log(`Mongo Db is connected`)
  app.listen(5000, () => {
    console.log(`server is running on 5000`)
  })
})


mongoose.connection.on("error", (error) => {
  console.log("error is ", error)
})

app.use("/api/products", productRouter);
app.use("/api/catagories", catagoryRouter)

Add .env

Create a .env file:

MONGO_URI=your-mongodb-connection-uri
PORT=5000

Define the Product Model

4. Create models/Product.js

import mongoose from "mongoose";

const productSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  description: {
    type: String,
  },
  price: {
    type: Number,
    required: true
  },
  quantity: {
    type: Number,
    default: 0
  },
  active: {
    type: Boolean,
    default: true
  },
  catagory: {
    type: String,
    enum: ["food", "electronics", "vegetable"]
  },
}, {
  timestamps: true,
}
)

export default mongoose.model("ProductModel", productSchema);

Build the Routes

5. Create routes/productRoutes.js

import express from "express";
import { createProducts, deleteProduct, getProducts, getProductsById, updateProduct } from "../controllers/productsControler.js";

const router = express.Router()

router.post("/", createProducts)
router.get("/", getProducts)
router.get("/:id", getProductsById)
router.put("/:id", updateProduct)
router.delete("/:id",deleteProduct);

export default router;

Write the Logic

6. Create controllers/productController.js

import mongoose from "mongoose";
import productsModels from "../models/productsModels.js";
export const createProducts = async (req, res) => {
  try {

    if (!req.body.name) {
      return res.status(422).json({
        "error": "name feild is not given"
      })
    }
    if (!req.body.description) {
      return res.status(422).json({
        "error": "description feild is not given"
      })
    }
    if (!req.body.price) {
      return res.status(422).json({
        "error": "price feild is not given"
      })
    }
    if (!req.body.quantity) {
      return res.status(422).json({
        "error": "quantity feild is not given"
      })
    }
    if (!req.body.active) {
      return res.status(422).json({
        "error": "active feild is not given"
      })
    }
    if (!req.body.catagory) {
      return res.status(422).json({
        "error": "catagory feild is not given"
      })
    }

    const product = await productsModels
      .create(req.body)
    res.status(201).json(product)
  }

  catch (error) {
    return res.status(501).json({
      "error": error.message
    })
  }
}

export const getProducts = async (req, res) => {
  try {
    const product = await productsModels.find()
    return res.status(201).json(product)
  } catch (error) {
    return res.status(422).json({
      "error": "Invalid product ID"
    })
  }
}

export const getProductsById = async (req, res) => {
  try {
    const product = await productsModels.findById(req.params.id).select("_id name price")
    return res.status(201).json(product)
  } catch (error) {
    return res.status(422).json({
      "error": "Invalid product ID"
    })
  }
}

export const updateProduct = async (req, res) => {
  if (!mongoose.isValidObjectId(req.params.id)) {
    return res.status(422).json({
      "error": "Invalid Mongo ID"
    })
  }
  if (!await product.exists({ _id: req.params.id })) {
    return res.status(422).json({
      "error": "Invalid product ID"
    })
  }
  try {
    const product = await productsModels.findByIdAndUpdate(req.params.id, req.body, { new: true })
    res.status(201).json({
      product
    })
  } catch (error) {
    return res.status(422).json({
      "error": error.message
    })
  }
}

export const deleteProduct = async (req, res) => {
  if (!mongoose.isValidObjectId(req.params.id)) {
    return res.status(422).json({
      "error": "Invalid Mongo ID"
    })
  }
  if (!await product.exists({ _id: req.params.id })) {
    return res.status(422).json({
      "error": "Invalid product ID"
    })
  }
  try {
    const product = await productsModels.findByIdAndDelete(req.params.id);

    if (!product) {
      return res.status(404).json({ error: "Product not found" });
    }

    return res.status(200).json({
      message: "Product deleted successfully"
    });

  } catch (error) {
    return res.status(500).json({
      error: error.message
    });
  }
}

Test Your API

Use Postman or Thunder Client to test your endpoints:

  • POST /api/products

  • GET /api/products

  • GET /api/products/:id

  • PUT /api/products/:id

  • DELETE /api/products/:id


Done! What’s Next?

Now that you’ve built a working REST API with MongoDB, you can:

  • Add validation with Zod/Joi

  • Add user authentication with JWT

  • Deploy to Render, Vercel, or Railway


Starter Code

Full working code: 👉 api-mongodb GitHub

Need a reusable boilerplate? 👉 api-boilerplates GitHub


Final Words

You just built your first production-ready API! Whether you’re learning or planning to scale, this gives you a solid backend foundation.

If you found this useful, give it a ⭐ on GitHub and follow me for more content!