Only show guides for your app
Routes, HTTP status codes, and input validation for a clean Express API on Falix — the shape most bot dashboards, mobile backends, and side projects actually need, verified end to end.
Most backends you'll build are a REST API: a set of URLs that return JSON instead of HTML. A Discord bot's dashboard, a mobile app's server, a public data feed — all the same shape. This guide covers the three things that separate a tidy API from a messy one: routes that read well, status codes that tell the truth, and validation that rejects bad input before it reaches your logic. It runs on the Node.js application with Express.
| At a glance | |
|---|---|
| You need | A server running the Node.js application |
| Background | Your first web app (the SERVER_PORT / 0.0.0.0 rule) and Build an Express website + API |
| Plan | Any plan |
| Time | Thirty minutes |
New to Express here? Read Build an Express website + API first — this guide assumes the index.js entry file and automatic npm install it explains.
A REST API maps things (resources) to URLs, and actions to HTTP methods. Pick a plural noun for the resource and let the method carry the verb — never put the verb in the URL.
| Do this | Not this |
|---|---|
GET /api/notes |
GET /api/getAllNotes |
GET /api/notes/42 |
GET /api/note?id=42&action=fetch |
POST /api/notes |
POST /api/createNote |
DELETE /api/notes/42 |
POST /api/deleteNote |
The pattern is always method + collection + optional id. Read it aloud: "GET notes" lists them, "POST notes" adds one, "DELETE notes 42" removes one. Once the shape is consistent, anyone can guess the rest.
The status code is the first thing a client reads. Sending 200 OK on a failure is the single most common API bug — it forces every caller to dig through the body to find out what really happened. Use the small set that covers almost everything:
| Code | Means | Use it when |
|---|---|---|
200 OK |
Success, here's the data | A GET that found something |
201 Created |
Made a new thing | A POST that added a row |
204 No Content |
Success, nothing to return | A DELETE that worked |
400 Bad Request |
Your request was malformed | Missing/garbage input |
401 Unauthorized |
You're not logged in | No/invalid credentials — see Sessions, JWT & passwords |
404 Not Found |
That thing doesn't exist | An id that isn't there |
422 Unprocessable Entity |
Valid shape, invalid values | Validation failed |
429 Too Many Requests |
Slow down | Rate limited — see Rate limiting your API |
500 Internal Server Error |
You broke, not them | An unhandled exception |
Never write a request body straight into your data. Check it first, and reject bad input with a clear message and a 4xx code. The express-validator library does this cleanly, but the principle is the same if you hand-roll the checks: validate, and only then act.
Install express, then express-validator, from the Packages page (search each name, install, then restart). Here's a complete index.js — a notes API with all four routes, honest status codes, and validation on the one route that takes input:
const express = require('express');
const { body, validationResult } = require('express-validator');
const app = express();
app.use(express.json()); // parse JSON request bodies
let notes = [{ id: 1, title: 'First note', body: 'hello' }];
let nextId = 2;
// List all
app.get('/api/notes', (req, res) => {
res.json(notes);
});
// Get one — 404 if it isn't there
app.get('/api/notes/:id', (req, res) => {
const note = notes.find((n) => n.id === Number(req.params.id));
if (!note) return res.status(404).json({ error: 'Note not found' });
res.json(note);
});
// Create one — validate, then 201
app.post('/api/notes',
body('title').isString().trim().notEmpty().withMessage('title is required'),
body('body').isString().trim().notEmpty().withMessage('body is required'),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
const note = { id: nextId++, title: req.body.title, body: req.body.body };
notes.push(note);
res.status(201).json(note);
}
);
// Delete one — 204 on success, 404 if missing
app.delete('/api/notes/:id', (req, res) => {
const idx = notes.findIndex((n) => n.id === Number(req.params.id));
if (idx === -1) return res.status(404).json({ error: 'Note not found' });
notes.splice(idx, 1);
res.status(204).end();
});
const PORT = process.env.SERVER_PORT || 8080;
app.listen(PORT, '0.0.0.0', () => console.log(`Listening on port ${PORT}`));
express.json() turns the incoming JSON body into req.body. Each body('title')... line is a rule; validationResult(req) collects any failures so you can return them all at once with a 422. Every route ends in exactly one response.
Start the server, then hit it from the Console's neighbour — your own machine — using your server's public address (Network page). The shape you should see:
| Request | Response |
|---|---|
GET /api/notes |
200 + the array |
GET /api/notes/999 |
404 + {"error":"Note not found"} |
POST /api/notes with {"title":"Hi","body":"there"} |
201 + the new note |
POST /api/notes with {"title":""} |
422 + the validation errors |
DELETE /api/notes/1 |
204, empty body |
From a terminal, curl proves it in one line each:
curl -i -X POST -H "Content-Type: application/json" \
-d '{"title":"Hi","body":"there"}' http://YOUR_ADDRESS:PORT/api/notes
The -i flag prints the status line, so you can confirm HTTP/1.1 201 Created with your own eyes.
🎯 Good to know: This example keeps notes in a plain array, so they reset on every restart. That's fine for learning the shape — when you want them to persist, move the array to SQLite or a managed database. Add a database is the next step, and The classic todo REST API is this same design wired to real storage.
res.json / res.send / res.status().end(). return the early ones so code doesn't fall through and try to respond twice (ERR_HTTP_HEADERS_SENT).{ error: '...' } with the right code./api/v1/ lets you change things without breaking them.cors middleware — see CORS errors explained.Everything past this point — pagination, filtering, nested resources, OpenAPI docs — is standard Express and standard REST. The official Express guide at expressjs.com covers routing and middleware in depth, and express-validator.github.io documents every validation rule.