Your first route
With the server from part one running, it's time to make it actually do something. Every Express route follows the same shape: a method, a path, and a function that receives the request and sends a response.
Adding a health check route
A health check is the smallest useful route you can write — it just confirms the server is alive:
const express = require('express');
const app = express();
app.get('/api/health', (req, res) => {
res.json({ status: 'ok' });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});Restart the server and visit http://localhost:3000/api/health in your browser. You should see {"status":"ok"}.
What just happened
app.get registers a handler for GET requests to a specific path. Express passes your function two objects: req, which describes the incoming request, and res, which you use to send a response. Calling res.json(...) sets the content type automatically and serializes your object to JSON.
Route parameters
Most real routes need to accept an identifier. Express captures that from the URL with a colon prefix:
app.get('/api/users/:id', (req, res) => {
res.json({ id: req.params.id, name: 'Sample User' });
});Visiting /api/users/42 returns {"id":"42","name":"Sample User"} — req.params.id is always a string, even though it looks like a number.
Add a second route, GET /api/status, that returns the server's uptime using Node's built-in process.uptime(). You'll use the same pattern for every route in this series.
FAQ
How do I read data sent in a POST request body?
req.body is undefined by default — Express needs app.use(express.json()) added before your routes to parse a JSON request body into req.body. This series introduces POST routes with that middleware already in place once one is needed.
What's the difference between a route parameter and a query string?
/api/users/:id (this part's route parameter) identifies a specific resource — /api/users/42 means "user 42." A query string (/api/users?role=admin, read via req.query.role) filters or modifies a request instead of identifying one specific thing. Both are strings regardless of what they look like.
Why does req.params.id return a string even for a numeric ID?
URL segments are always text — Express has no way to know 42 should become the number 42 versus staying the string "42" without converting it explicitly. A route that queries a database expecting a number typically calls Number(req.params.id) or lets the database driver handle the conversion.
Next, you'll intentionally break this server to see what happens when something goes wrong — and fix it properly.