Python Fundamentals + Building APIs with Node.js
BUILDSPHERE SHORT COURSE
Python Fundamentals + Building APIs with Node.js
For Beginners & Junior Developers
INTRODUCTION
You don't need a computer science degree to become a developer. You need two things: the right knowledge and the discipline to show up every day.
This short course covers two of the most in-demand skills in software right now — Python and building APIs with Node.js. By the end, you'll have written real, working code and built two mini projects you can show people.
Let's get into it.
MODULE 1: PYTHON FUNDAMENTALS
1.1 — Why Python?

Python is the world's most popular programming language. It reads almost like plain English, which means you spend less time fighting the language and more time actually solving problems.
Here's what Python is used for in the real world:
- Web development (Django, Flask, FastAPI)
- Data science and machine learning
- Automation and scripting
- Artificial intelligence
- APIs and backend development
It's also the best first language. Once you understand Python, picking up any other language becomes much easier because the core concepts — variables, loops, functions, data structures — transfer directly.
1.2 — Setting Up Your Environment
Before you write any code, you need two things installed: Python and a code editor.
STEP 1 — Install Python
Go to python.org/downloads and grab the latest version (3.11 or higher). On Windows, tick the box that says "Add Python to PATH" during installation. On Mac, open your terminal and type python3 --version to see if it's already there.
STEP 2 — Install VS Code
Download Visual Studio Code from code.visualstudio.com. It's free and the most widely used editor in the industry.
STEP 3 — Install the Python Extension
Inside VS Code, press Ctrl+Shift+X (or Cmd+Shift+X on Mac), search for "Python", and install the Microsoft extension. This gives you syntax highlighting, autocomplete, and the ability to run code directly inside the editor.
Inside VS Code, press Ctrl+Shift+X (or Cmd+Shift+X on Mac), search for "Python", and install the Microsoft extension. This gives you syntax highlighting, autocomplete, and the ability to run code directly inside the editor.
Now test your setup. Open the VS Code terminal and type:
----
python3 --version
----
You should see something like: Python 3.11.5
If you do — you're ready.
1.3 — Variables, Data Types & Your First Program

A variable is a container. You give it a name, store something inside it, and use it whenever you need it. Python figures out what type of data you're storing automatically — you don't have to tell it.
The four main data types to know:
----
# String — text, always wrapped in quotes
name = "Alex"
# Integer — whole numbers
age = 24
# Float — numbers with decimals
height = 5.9
# Boolean — only two possible values: True or False
is_developer = True
----
Now use them together:
----
name = "Alex"
age = 24
print(f"Hi, I'm {name} and I'm {age} years old.")
# Output: Hi, I'm Alex and I'm 24 years old.
----
NOTE: The "f" before the quote makes it an f-string. Put any variable inside curly braces { } and Python drops it right into the text. This is the cleanest way to work with text and variables together.
1.4 — Control Flow: Making Decisions in Code
Programs need to make decisions. If this is true, do this. Otherwise, do that. That's control flow — and it's the foundation of every program ever written.
THE IF STATEMENT:
----
score = 78
if score >= 90:
print("Grade: A — Excellent!")
elif score >= 70:
print("Grade: B — Good work.")
elif score >= 50:
print("Grade: C — Keep going.")
else:
print("Grade: F — Let's try again.")
# Output: Grade: B — Good work.
----
Notice the indentation. Python uses spaces to define what belongs inside each block. This is not optional — it's how the language works.
THE FOR LOOP — repeating something a set number of times:
----
for i in range(5):
print(f"Round {i + 1}")
# Output:
# Round 1
# Round 2
# Round 3
# Round 4
# Round 5
----
THE WHILE LOOP — keep going until a condition becomes false:
----
count = 0
while count < 3:
print(f"Count is {count}")
count += 1
# Output:
# Count is 0
# Count is 1
# Count is 2
----
1.5 — Functions: Write Once, Use Everywhere
A function is a named block of code you define once and call whenever you need it. Functions keep your code organized, clean, and reusable. If you find yourself writing the same logic twice — make it a function.
----
# Define the function
def greet_user(name, language="English"):
if language == "Spanish":
return f"Hola, {name}!"
elif language == "French":
return f"Bonjour, {name}!"
return f"Hello, {name}!"
# Call the function
print(greet_user("Maria"))
print(greet_user("Carlos", "Spanish"))
print(greet_user("Sophie", "French"))
# Output:
# Hello, Maria!
# Hola, Carlos!
# Bonjour, Sophie!
----
KEY RULE: A function should do one thing and do it well. If your function is doing five different things, split it into five functions. This is called the Single Responsibility Principle and it's the first habit that separates beginner code from professional code.
1.6 — Lists, Dicts & Working with Real Data
Real programs don't work with single values — they work with collections of data. Python gives you two essential tools for this.
LISTS — ordered, indexed collections:
----
fruits = ["apple", "banana", "mango", "grape"]
print(fruits[0]) # apple (index starts at 0)
print(fruits[-1]) # grape (last item)
print(len(fruits)) # 4
fruits.append("kiwi") # add to end
print(len(fruits)) # 5
# Loop through a list
for fruit in fruits:
print(fruit)
----
DICTIONARIES — key-value pairs, like a real dictionary:
----
user = {
"name": "Jordan",
"age": 27,
"role": "developer",
"active": True
}
print(user["name"]) # Jordan
print(user["age"]) # 27
user["level"] = "mid" # add a new key
# Loop through all key-value pairs
for key, value in user.items():
print(f"{key}: {value}")
----
1.7 — MINI PROJECT: Build a CLI To-Do App
Here's your first complete Python program. It runs in the terminal and lets you add tasks, view them, and mark them done. Type this out yourself — don't copy and paste. Typing builds muscle memory.
----
# todo_app.py
tasks = []
def add_task(title):
tasks.append({"title": title, "done": False})
print(f"Added: '{title}'")
def view_tasks():
if not tasks:
print("No tasks yet.")
return
for i, task in enumerate(tasks):
status = "Done" if task["done"] else "Pending"
print(f"{i + 1}. [{status}] {task['title']}")
def complete_task(index):
tasks[index]["done"] = True
print(f"Marked as done: {tasks[index]['title']}")
# --- Run the app ---
add_task("Learn Python variables")
add_task("Build a function")
add_task("Understand loops")
complete_task(0)
view_tasks()
# Output:
# Added: 'Learn Python variables'
# Added: 'Build a function'
# Added: 'Understand loops'
# Marked as done: Learn Python variables
# 1. [Done] Learn Python variables
# 2. [Pending] Build a function
# 3. [Pending] Understand loops
----
CHALLENGE: Add a delete_task() function that removes a task by its index number. Then add input() calls so the user can type their own tasks at the terminal instead of having them hardcoded. You know everything you need to do this right now.
MODULE 2: BUILDING APIs WITH NODE.JS

2.1 — What Is an API and Why Should You Care?
API stands for Application Programming Interface. In plain terms: it's how two pieces of software talk to each other over the internet.
When your weather app shows today's forecast — it's calling an API. When you log in with Google — that's an API. When Instagram loads your feed — API. When a payment goes through on an online store — API.
You are going to build one.
The most common type is a REST API. It uses HTTP — the same protocol websites use. It has endpoints (specific URLs), and each one does something specific:
GET — Read data (e.g., load a user's profile)
POST — Create new data (e.g., submit a new blog post)
PUT — Update data (e.g., edit your username)
DELETE — Remove data (e.g., delete a comment)
These four methods, combined with a server that handles them, is what almost every app on the internet is built on.
2.2 — Node.js + Express: Your First Server
Node.js lets you run JavaScript outside the browser — on a server. This was a big deal when it launched because it meant developers could use one language (JavaScript) for both the frontend and the backend.
Express is a lightweight framework built on top of Node that makes building APIs fast and clean. Together they're used by Netflix, LinkedIn, Uber, PayPal, and thousands of other companies.
STEP 1 — Install Node.js
Go to nodejs.org and download the LTS version. This installs both Node and npm (Node Package Manager), which you'll use to install libraries.
STEP 2 — Create your project folder
Open your terminal and run these commands one at a time:
----
mkdir my-first-api
cd my-first-api
npm init -y
npm install express
----
This creates a new project and installs Express. You'll see a node_modules folder appear — that's normal and expected.
STEP 3 — Create your server file
Create a new file called server.js and type this:
----
// server.js
const express = require('express');
const app = express();
const PORT = 3000;
// This line lets your server read JSON from incoming requests
app.use(express.json());
// Your first route
app.get('/', (req, res) => {
res.json({ message: 'Hello from your first API!', status: 'running' });
});
// Start the server
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
----
STEP 4 — Run it
In your terminal, type:
----
node server.js
----
Now open your browser and go to: http://localhost:3000
You should see this:
----
{ "message": "Hello from your first API!", "status": "running" }
---- u
2.3 — Routes, Methods & Handling Requests
A route is a combination of a URL path and an HTTP method. Each route does one specific thing.
Let's build a complete set of routes for a tasks resource. Add these to your server.js file, above the app.listen() line:
----
// In-memory tasks store
// (data resets when you restart the server — we'll fix that in section 2.5)
let tasks = [
{ id: 1, title: 'Learn Node.js', done: false },
{ id: 2, title: 'Build an API', done: false },
];
// GET — fetch all tasks
app.get('/tasks', (req, res) => {
res.json(tasks);
});
// GET — fetch a single task by ID
app.get('/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// POST — create a new task
app.post('/tasks', (req, res) => {
const newTask = {
id: tasks.length + 1,
title: req.body.title,
done: false
};
tasks.push(newTask);
res.status(201).json(newTask);
});
// PUT — update an existing task
app.put('/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) return res.status(404).json({ error: 'Task not found' });
task.title = req.body.title ?? task.title;
task.done = req.body.done ?? task.done;
res.json(task);
});
// DELETE — remove a task
app.delete('/tasks/:id', (req, res) => {
tasks = tasks.filter(t => t.id !== parseInt(req.params.id));
res.json({ message: 'Task deleted successfully' });
});
----
TOOL TIP: Install the VS Code extension called "Thunder Client" or download the free app "Postman" to test your API routes. Just pick the method (GET, POST, etc.), type in the URL, and hit Send. You don't need a frontend to test an API.
2.4 — Working with JSON Data
JSON (JavaScript Object Notation) is the language APIs speak. It's how data travels between your server and anyone calling it — a mobile app, a browser, or another server.
It looks like a JavaScript object:
----
{
"id": 42,
"title": "Learn APIs",
"done": false,
"tags": ["node", "backend", "javascript"],
"author": {
"name": "Jordan",
"email": "jordan@dev.io"
}
}
----
Express automatically parses incoming JSON bodies because of the app.use(express.json()) line you added earlier. Here's how you access that data in a route:
----
app.post('/example', (req, res) => {
// Pull specific fields out of the request body
const { title, tags } = req.body;
console.log(title); // whatever the caller sent
console.log(tags); // array from the JSON body
res.json({ received: true, yourTitle: title });
});
----
The { title, tags } = req.body syntax is called destructuring. Instead of writing req.body.title and req.body.tags separately, you pull both out at once. You'll see this pattern constantly in Node.js code.
2.5 — Connecting to a Database (MongoDB Intro)
Right now your tasks live in memory. Every time you restart the server, they're gone. A database stores them permanently.
MongoDB is a popular choice for Node.js because it stores data in JSON-like documents — there are no complex tables or schemas to design upfront. Mongoose is the library that connects Node.js to MongoDB cleanly.
Install it:
----
npm install mongoose
----
Create a new file called db.js:
----
// db.js
const mongoose = require('mongoose');
// Connect to your local MongoDB database
mongoose.connect('mongodb://localhost:27017/tasksdb')
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Connection error:', err));
// Define the shape of a task document
const taskSchema = new mongoose.Schema({
title: { type: String, required: true },
done: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now }
});
// Export the model so other files can use it
module.exports = mongoose.model('Task', taskSchema);
----
Now update your server.js routes to use the database instead of the in-memory array:
----
// At the top of server.js, replace the tasks array with this:
const Task = require('./db');
// GET all tasks from the database
app.get('/tasks', async (req, res) => {
const tasks = await Task.find();
res.json(tasks);
});
// POST — save a new task to the database
app.post('/tasks', async (req, res) => {
const task = new Task({ title: req.body.title });
await task.save();
res.status(201).json(task);
});
----
NOTE: Don't have MongoDB installed locally? Use MongoDB Atlas at atlas.mongodb.com — it's free, cloud-hosted, and ready in about five minutes. Just replace the connection string with the one Atlas gives you.
2.6 — MINI PROJECT: Build a Full REST API
You have everything you need. Here is the complete, final server.js file — a working REST API with all five routes, connected to MongoDB, with proper error handling.
----
// server.js — Complete Task API
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
// Database connection
mongoose.connect('mongodb://localhost:27017/tasksdb')
.then(() => console.log('Database connected'))
.catch(err => console.error('DB Error:', err));
// Task model
const taskSchema = new mongoose.Schema({
title: { type: String, required: true },
done: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now }
});
const Task = mongoose.model('Task', taskSchema);
// GET all tasks
app.get('/tasks', async (req, res) => {
const tasks = await Task.find();
res.json(tasks);
});
// GET one task by ID
app.get('/tasks/:id', async (req, res) => {
const task = await Task.findById(req.params.id);
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// POST — create a task
app.post('/tasks', async (req, res) => {
const task = new Task({ title: req.body.title });
await task.save();
res.status(201).json(task);
});
// PUT — update a task
app.put('/tasks/:id', async (req, res) => {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// DELETE — remove a task
app.delete('/tasks/:id', async (req, res) => {
await Task.findByIdAndDelete(req.params.id);
res.json({ message: 'Task deleted' });
});
// Start server
app.listen(3000, () => {
console.log('API running at http://localhost:3000');
});
----
CHALLENGE: Add a route that filters tasks by status. Something like GET /tasks?done=true should return only completed tasks. Hint: use Task.find({ done: true }). This is how real-world query filtering works and it appears in almost every API ever built.
BONUS: WHAT TO LEARN NEXT
You've built real things. The question now is which direction to take it.
IF YOU WANT TO BUILD WEB APPS WITH PYTHON:
Learn Django (full-featured framework) or FastAPI (lightweight, great for APIs). Start at fastapi.tiangolo.com — the documentation is excellent.
IF YOU WANT TO GO DEEPER ON NODE.JS:
Learn JWT authentication (how login systems work), middleware (how requests are processed), and rate limiting (how APIs protect themselves). The official Node.js docs at nodejs.org are your friend.
IF YOU WANT TO WORK WITH DATA AND AI:
Learn Pandas and NumPy for data manipulation, then move into machine learning with scikit-learn or PyTorch. Start at kaggle.com/learn — it's free and hands-on.
IF YOU WANT TO BUILD MOBILE APPS:
React Native uses JavaScript, so your Node.js knowledge transfers directly. Start at reactnative.dev.
IF YOU WANT TO AUTOMATE THINGS:
Python is king here. Learn how to schedule scripts with cron jobs, scrape websites with BeautifulSoup, and automate files and folders. realpython.com is one of the best resources out there.
IF YOU WANT TO GET A DEVELOPER JOB:
Learn data structures and algorithms. It sounds boring but almost every technical interview tests this. Go to neetcode.io and work through problems systematically. Combine that with building real projects you can show people.
FINAL WORD
The only thing that separates you from a working developer is showing up and writing code every single day.
30 minutes a day. 7 days a week. 90 days. That's a developer.
Keep this guide. Come back to it. Run the code examples, break them, then fix them. That's how programmers are made.
— The BuildSphere Team
END OF COURSE
----
python3 --version
----
You should see something like: Python 3.11.5
If you do — you're ready.
1.3 — Variables, Data Types & Your First Program

A variable is a container. You give it a name, store something inside it, and use it whenever you need it. Python figures out what type of data you're storing automatically — you don't have to tell it.
The four main data types to know:
----
# String — text, always wrapped in quotes
name = "Alex"
# Integer — whole numbers
age = 24
# Float — numbers with decimals
height = 5.9
# Boolean — only two possible values: True or False
is_developer = True
----
Now use them together:
----
name = "Alex"
age = 24
print(f"Hi, I'm {name} and I'm {age} years old.")
# Output: Hi, I'm Alex and I'm 24 years old.
----
NOTE: The "f" before the quote makes it an f-string. Put any variable inside curly braces { } and Python drops it right into the text. This is the cleanest way to work with text and variables together.
1.4 — Control Flow: Making Decisions in Code
Programs need to make decisions. If this is true, do this. Otherwise, do that. That's control flow — and it's the foundation of every program ever written.
THE IF STATEMENT:
----
score = 78
if score >= 90:
print("Grade: A — Excellent!")
elif score >= 70:
print("Grade: B — Good work.")
elif score >= 50:
print("Grade: C — Keep going.")
else:
print("Grade: F — Let's try again.")
# Output: Grade: B — Good work.
----
Notice the indentation. Python uses spaces to define what belongs inside each block. This is not optional — it's how the language works.
THE FOR LOOP — repeating something a set number of times:
----
for i in range(5):
print(f"Round {i + 1}")
# Output:
# Round 1
# Round 2
# Round 3
# Round 4
# Round 5
----
THE WHILE LOOP — keep going until a condition becomes false:
----
count = 0
while count < 3:
print(f"Count is {count}")
count += 1
# Output:
# Count is 0
# Count is 1
# Count is 2
----
1.5 — Functions: Write Once, Use Everywhere
A function is a named block of code you define once and call whenever you need it. Functions keep your code organized, clean, and reusable. If you find yourself writing the same logic twice — make it a function.
----
# Define the function
def greet_user(name, language="English"):
if language == "Spanish":
return f"Hola, {name}!"
elif language == "French":
return f"Bonjour, {name}!"
return f"Hello, {name}!"
# Call the function
print(greet_user("Maria"))
print(greet_user("Carlos", "Spanish"))
print(greet_user("Sophie", "French"))
# Output:
# Hello, Maria!
# Hola, Carlos!
# Bonjour, Sophie!
----
KEY RULE: A function should do one thing and do it well. If your function is doing five different things, split it into five functions. This is called the Single Responsibility Principle and it's the first habit that separates beginner code from professional code.
1.6 — Lists, Dicts & Working with Real Data
Real programs don't work with single values — they work with collections of data. Python gives you two essential tools for this.
LISTS — ordered, indexed collections:
----
fruits = ["apple", "banana", "mango", "grape"]
print(fruits[0]) # apple (index starts at 0)
print(fruits[-1]) # grape (last item)
print(len(fruits)) # 4
fruits.append("kiwi") # add to end
print(len(fruits)) # 5
# Loop through a list
for fruit in fruits:
print(fruit)
----
DICTIONARIES — key-value pairs, like a real dictionary:
----
user = {
"name": "Jordan",
"age": 27,
"role": "developer",
"active": True
}
print(user["name"]) # Jordan
print(user["age"]) # 27
user["level"] = "mid" # add a new key
# Loop through all key-value pairs
for key, value in user.items():
print(f"{key}: {value}")
----
1.7 — MINI PROJECT: Build a CLI To-Do App
Here's your first complete Python program. It runs in the terminal and lets you add tasks, view them, and mark them done. Type this out yourself — don't copy and paste. Typing builds muscle memory.
----
# todo_app.py
tasks = []
def add_task(title):
tasks.append({"title": title, "done": False})
print(f"Added: '{title}'")
def view_tasks():
if not tasks:
print("No tasks yet.")
return
for i, task in enumerate(tasks):
status = "Done" if task["done"] else "Pending"
print(f"{i + 1}. [{status}] {task['title']}")
def complete_task(index):
tasks[index]["done"] = True
print(f"Marked as done: {tasks[index]['title']}")
# --- Run the app ---
add_task("Learn Python variables")
add_task("Build a function")
add_task("Understand loops")
complete_task(0)
view_tasks()
# Output:
# Added: 'Learn Python variables'
# Added: 'Build a function'
# Added: 'Understand loops'
# Marked as done: Learn Python variables
# 1. [Done] Learn Python variables
# 2. [Pending] Build a function
# 3. [Pending] Understand loops
----
CHALLENGE: Add a delete_task() function that removes a task by its index number. Then add input() calls so the user can type their own tasks at the terminal instead of having them hardcoded. You know everything you need to do this right now.
MODULE 2: BUILDING APIs WITH NODE.JS

2.1 — What Is an API and Why Should You Care?
API stands for Application Programming Interface. In plain terms: it's how two pieces of software talk to each other over the internet.
When your weather app shows today's forecast — it's calling an API. When you log in with Google — that's an API. When Instagram loads your feed — API. When a payment goes through on an online store — API.
You are going to build one.
The most common type is a REST API. It uses HTTP — the same protocol websites use. It has endpoints (specific URLs), and each one does something specific:
GET — Read data (e.g., load a user's profile)
POST — Create new data (e.g., submit a new blog post)
PUT — Update data (e.g., edit your username)
DELETE — Remove data (e.g., delete a comment)
These four methods, combined with a server that handles them, is what almost every app on the internet is built on.
2.2 — Node.js + Express: Your First Server
Node.js lets you run JavaScript outside the browser — on a server. This was a big deal when it launched because it meant developers could use one language (JavaScript) for both the frontend and the backend.
Express is a lightweight framework built on top of Node that makes building APIs fast and clean. Together they're used by Netflix, LinkedIn, Uber, PayPal, and thousands of other companies.
STEP 1 — Install Node.js
Go to nodejs.org and download the LTS version. This installs both Node and npm (Node Package Manager), which you'll use to install libraries.
STEP 2 — Create your project folder
Open your terminal and run these commands one at a time:
----
mkdir my-first-api
cd my-first-api
npm init -y
npm install express
----
This creates a new project and installs Express. You'll see a node_modules folder appear — that's normal and expected.
STEP 3 — Create your server file
Create a new file called server.js and type this:
----
// server.js
const express = require('express');
const app = express();
const PORT = 3000;
// This line lets your server read JSON from incoming requests
app.use(express.json());
// Your first route
app.get('/', (req, res) => {
res.json({ message: 'Hello from your first API!', status: 'running' });
});
// Start the server
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
----
STEP 4 — Run it
In your terminal, type:
----
node server.js
----
Now open your browser and go to: http://localhost:3000
You should see this:
----
{ "message": "Hello from your first API!", "status": "running" }
---- u
2.3 — Routes, Methods & Handling Requests
A route is a combination of a URL path and an HTTP method. Each route does one specific thing.
Let's build a complete set of routes for a tasks resource. Add these to your server.js file, above the app.listen() line:
----
// In-memory tasks store
// (data resets when you restart the server — we'll fix that in section 2.5)
let tasks = [
{ id: 1, title: 'Learn Node.js', done: false },
{ id: 2, title: 'Build an API', done: false },
];
// GET — fetch all tasks
app.get('/tasks', (req, res) => {
res.json(tasks);
});
// GET — fetch a single task by ID
app.get('/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// POST — create a new task
app.post('/tasks', (req, res) => {
const newTask = {
id: tasks.length + 1,
title: req.body.title,
done: false
};
tasks.push(newTask);
res.status(201).json(newTask);
});
// PUT — update an existing task
app.put('/tasks/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) return res.status(404).json({ error: 'Task not found' });
task.title = req.body.title ?? task.title;
task.done = req.body.done ?? task.done;
res.json(task);
});
// DELETE — remove a task
app.delete('/tasks/:id', (req, res) => {
tasks = tasks.filter(t => t.id !== parseInt(req.params.id));
res.json({ message: 'Task deleted successfully' });
});
----
TOOL TIP: Install the VS Code extension called "Thunder Client" or download the free app "Postman" to test your API routes. Just pick the method (GET, POST, etc.), type in the URL, and hit Send. You don't need a frontend to test an API.
2.4 — Working with JSON Data
JSON (JavaScript Object Notation) is the language APIs speak. It's how data travels between your server and anyone calling it — a mobile app, a browser, or another server.
It looks like a JavaScript object:
----
{
"id": 42,
"title": "Learn APIs",
"done": false,
"tags": ["node", "backend", "javascript"],
"author": {
"name": "Jordan",
"email": "jordan@dev.io"
}
}
----
Express automatically parses incoming JSON bodies because of the app.use(express.json()) line you added earlier. Here's how you access that data in a route:
----
app.post('/example', (req, res) => {
// Pull specific fields out of the request body
const { title, tags } = req.body;
console.log(title); // whatever the caller sent
console.log(tags); // array from the JSON body
res.json({ received: true, yourTitle: title });
});
----
The { title, tags } = req.body syntax is called destructuring. Instead of writing req.body.title and req.body.tags separately, you pull both out at once. You'll see this pattern constantly in Node.js code.
2.5 — Connecting to a Database (MongoDB Intro)
Right now your tasks live in memory. Every time you restart the server, they're gone. A database stores them permanently.
MongoDB is a popular choice for Node.js because it stores data in JSON-like documents — there are no complex tables or schemas to design upfront. Mongoose is the library that connects Node.js to MongoDB cleanly.
Install it:
----
npm install mongoose
----
Create a new file called db.js:
----
// db.js
const mongoose = require('mongoose');
// Connect to your local MongoDB database
mongoose.connect('mongodb://localhost:27017/tasksdb')
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Connection error:', err));
// Define the shape of a task document
const taskSchema = new mongoose.Schema({
title: { type: String, required: true },
done: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now }
});
// Export the model so other files can use it
module.exports = mongoose.model('Task', taskSchema);
----
Now update your server.js routes to use the database instead of the in-memory array:
----
// At the top of server.js, replace the tasks array with this:
const Task = require('./db');
// GET all tasks from the database
app.get('/tasks', async (req, res) => {
const tasks = await Task.find();
res.json(tasks);
});
// POST — save a new task to the database
app.post('/tasks', async (req, res) => {
const task = new Task({ title: req.body.title });
await task.save();
res.status(201).json(task);
});
----
NOTE: Don't have MongoDB installed locally? Use MongoDB Atlas at atlas.mongodb.com — it's free, cloud-hosted, and ready in about five minutes. Just replace the connection string with the one Atlas gives you.
2.6 — MINI PROJECT: Build a Full REST API
You have everything you need. Here is the complete, final server.js file — a working REST API with all five routes, connected to MongoDB, with proper error handling.
----
// server.js — Complete Task API
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
// Database connection
mongoose.connect('mongodb://localhost:27017/tasksdb')
.then(() => console.log('Database connected'))
.catch(err => console.error('DB Error:', err));
// Task model
const taskSchema = new mongoose.Schema({
title: { type: String, required: true },
done: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now }
});
const Task = mongoose.model('Task', taskSchema);
// GET all tasks
app.get('/tasks', async (req, res) => {
const tasks = await Task.find();
res.json(tasks);
});
// GET one task by ID
app.get('/tasks/:id', async (req, res) => {
const task = await Task.findById(req.params.id);
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// POST — create a task
app.post('/tasks', async (req, res) => {
const task = new Task({ title: req.body.title });
await task.save();
res.status(201).json(task);
});
// PUT — update a task
app.put('/tasks/:id', async (req, res) => {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!task) return res.status(404).json({ error: 'Task not found' });
res.json(task);
});
// DELETE — remove a task
app.delete('/tasks/:id', async (req, res) => {
await Task.findByIdAndDelete(req.params.id);
res.json({ message: 'Task deleted' });
});
// Start server
app.listen(3000, () => {
console.log('API running at http://localhost:3000');
});
----
CHALLENGE: Add a route that filters tasks by status. Something like GET /tasks?done=true should return only completed tasks. Hint: use Task.find({ done: true }). This is how real-world query filtering works and it appears in almost every API ever built.
BONUS: WHAT TO LEARN NEXT
You've built real things. The question now is which direction to take it.
IF YOU WANT TO BUILD WEB APPS WITH PYTHON:
Learn Django (full-featured framework) or FastAPI (lightweight, great for APIs). Start at fastapi.tiangolo.com — the documentation is excellent.
IF YOU WANT TO GO DEEPER ON NODE.JS:
Learn JWT authentication (how login systems work), middleware (how requests are processed), and rate limiting (how APIs protect themselves). The official Node.js docs at nodejs.org are your friend.
IF YOU WANT TO WORK WITH DATA AND AI:
Learn Pandas and NumPy for data manipulation, then move into machine learning with scikit-learn or PyTorch. Start at kaggle.com/learn — it's free and hands-on.
IF YOU WANT TO BUILD MOBILE APPS:
React Native uses JavaScript, so your Node.js knowledge transfers directly. Start at reactnative.dev.
IF YOU WANT TO AUTOMATE THINGS:
Python is king here. Learn how to schedule scripts with cron jobs, scrape websites with BeautifulSoup, and automate files and folders. realpython.com is one of the best resources out there.
IF YOU WANT TO GET A DEVELOPER JOB:
Learn data structures and algorithms. It sounds boring but almost every technical interview tests this. Go to neetcode.io and work through problems systematically. Combine that with building real projects you can show people.
FINAL WORD
The only thing that separates you from a working developer is showing up and writing code every single day.
30 minutes a day. 7 days a week. 90 days. That's a developer.
Keep this guide. Come back to it. Run the code examples, break them, then fix them. That's how programmers are made.
— The BuildSphere Team
END OF COURSE



Comments