Back to Insights
Backend 2 August 2026 9 min read

Node.js & Express: Build Your First API

M
Mwero Abdalla
Founder & Lead Architect

The Fastest Way to Become a "Backend Developer"

Every job posting for a full stack or backend role assumes you can build an API. An API (Application Programming Interface) is just a server that answers requests with data — usually JSON — over HTTP. The good news: with Node.js and Express, the shortest useful API is about fifteen lines of code.

This guide builds a real one end to end. You should finish with a deployed, working API connected to a database — the exact skillset our Backend API Development course takes deeper over a full term.

What Is a REST API, Really?

REST is a convention for structuring URLs and HTTP verbs around resources:

  • GET /tasks — list tasks
  • POST /tasks — create a task
  • GET /tasks/:id — read one task
  • PATCH /tasks/:id — update a task
  • DELETE /tasks/:id — delete a task
  • The verb says what to do; the URL says what to do it to. Every framework you meet later — Django, Laravel, Spring — works on the same mental model, so the skill transfers.

    Project Setup

    Create a folder, initialize it, and install Express:

    mkdir tasks-api && cd tasks-api
    npm init -y
    npm install express

    A minimal server:

    const express = require("express");
    const app = express();
    const PORT = process.env.PORT || 3000;
    
    app.use(express.json());
    
    app.get("/", (req, res) => {
      res.json({ ok: true });
    });
    
    app.listen(PORT, () => console.log(`Listening on ${PORT}`));

    Run node server.js and open http://localhost:3000. That express.json() line is middleware — it parses incoming JSON bodies before your handlers run. Middleware is how Express stays small: you add exactly what you need.

    Your First Resource

    Let's manage tasks in memory first, so the routing is clear before a database enters the picture:

    let tasks = [];
    
    app.get("/tasks", (req, res) => {
      res.json(tasks);
    });
    
    app.post("/tasks", (req, res) => {
      const task = { id: String(Date.now()), title: req.body.title, done: false };
      tasks.push(task);
      res.status(201).json(task);
    });

    Notice the pattern: read requests return 200, a create returns 201, and the response body is JSON. Consistency like this is what makes an API pleasant to consume.

    Add a Real Database with MongoDB

    In-memory arrays disappear on restart. Switch to MongoDB so the data survives — and because it is the storage layer of the MERN stack. Install the official driver:

    npm install mongodb

    Connect once at startup:

    const { MongoClient } = require("mongodb");
    const client = new MongoClient(process.env.MONGO_URI);
    client.connect().then(() => console.log("db connected"));

    Then your routes query the collection instead of the array. Use environment variables for the connection string — never hard-code credentials. This habit alone separates professionals from hobbyists.

    Error Handling That Doesn't Crash the Server

    The classic beginner failure: an async route throws, and the whole process dies. Wrap async handlers and funnel errors to a single handler:

    const wrap = (fn) => (req, res, next) =>
      fn(req, res, next).catch(next);
    
    app.use((err, req, res, next) => {
      console.error(err);
      res.status(500).json({ error: "Something went wrong" });
    });

    Now unexpected failures return a clean 500 instead of crashing. Return 404 for missing resources and 422 for invalid input — clients depend on those codes.

    Validating Input

    Never trust the client. Before saving a task, check that title exists and is a string:

    if (!req.body.title || typeof req.body.title !== "string") {
      return res.status(422).json({ error: "title is required" });
    }

    This is where a library like zod pays off at scale, but the principle matters more than the library: fail early, with a clear message, at the boundary.

    Authentication: The Step Everyone Delays

    Protecting write routes is not optional once an API is public. Start with an Authorization: Bearer check as middleware:

    app.use("/tasks", requireAuth);

    For a production API, use a battle-tested approach (session cookies or JWT with proper signing and expiry) rather than rolling your own crypto. The moment you ship real user data, this line becomes your most important security boundary.

    Deploy It

    Deploy the API to a platform that understands Node (Render, Railway, or a VPS). You will need three things:

  • The code pushed to a repository
  • The MONGO_URI set as an environment variable on the platform
  • A production database (MongoDB Atlas free tier is fine to start)
  • The moment the deployed URL answers GET /tasks, you have shipped a real backend. That is a portfolio-grade artifact, not a tutorial exercise.

    Practice the Pattern

    APIs only get comfortable with reps. Work the fundamentals on Mwenaro Arena — the algorithm patterns you drill there (arrays, hashmaps, recursion) are exactly what surfaces in API design questions. Then extend this guide: add pagination, then authentication, then rate limiting.

    For the full sequence that turns this walkthrough into a production skill, follow the Full Stack cluster and consider the structured backend path at Mwenaro — where you build and deploy this exact project under mentor review.

    #Node.js#Express#REST API#Backend Development#JavaScript

    Start building today

    Turn this roadmap into real skills with a structured, project-based course — live instruction and mentorship from day one.

    Keep exploring