> Guide pratique pour construire une API REST avec Express.js : installation, routes, middlewares, objets req et res, méthodes HTTP, JSON, gestion des erreurs, structure de projet et connexion à une base.

*Source : https://coder-studio.com/tutoriels/express-js-api/*

---

[// Backend](https://coder-studio.com/tutoriels/)

# Créer une API REST avec Express.js

Par **Kévin Papot** · publié le 2 décembre 2025

**Express.js** est le framework web le plus utilisé de l’écosystème Node.js. Framework minimaliste, il ne vous impose presque aucune structure : il se contente de simplifier radicalement la gestion des routes, des requêtes et des réponses, là où le module natif `http` de Node.js devient vite verbeux. Si vous savez déjà lancer un serveur Node, Express est la brique qui vous fera passer à une véritable API. Ce guide construit une API REST fonctionnelle, pas à pas.

## Installer et démarrer Express

Express s’installe comme n’importe quel paquet npm, dans un projet déjà initialisé avec `npm init` :

```
npm install express
```

Le serveur minimal tient en quelques lignes. Dans un fichier `server.js` :

```
import express from "express";

const app = express();
app.use(express.json()); // permet de lire les corps JSON

app.get("/", (requete, reponse) => {
  reponse.send("API en ligne");
});

app.listen(3000, () => {
  console.log("Serveur sur http://localhost:3000");
});
```

Comparé à un serveur écrit avec le module `http` brut, la différence saute aux yeux : plus besoin de vérifier manuellement l’URL et la méthode, Express s’en charge. La ligne `app.use(express.json())` est un **middleware** intégré qui analyse automatiquement le corps JSON des requêtes entrantes — nous y reviendrons.

## Les routes et les méthodes HTTP

Une **route** associe une URL et une méthode HTTP à une fonction de traitement. Express expose une méthode par verbe : `app.get`, `app.post`, `app.put`, `app.patch`, `app.delete`. Construisons une API pour gérer une collection d’articles :

```
// données en mémoire, pour l'exemple
let articles = [
  { id: 1, titre: "Débuter avec Node.js" },
  { id: 2, titre: "Comprendre REST" }
];

// Lire la collection
app.get("/articles", (req, res) => {
  res.json(articles);
});

// Lire un article précis
app.get("/articles/:id", (req, res) => {
  const article = articles.find(a => a.id === Number(req.params.id));
  if (!article) {
    return res.status(404).json({ erreur: "Article introuvable" });
  }
  res.json(article);
});
```

La partie `:id` dans l’URL est un **paramètre de route** : Express la rend accessible via `req.params.id`. On récupère ici l’identifiant, on cherche l’article correspondant, et on renvoie une erreur `404` s’il n’existe pas. Cette correspondance entre verbes HTTP et opérations forme le cœur d’une API REST, un sujet que détaille notre [guide sur les principes d’une API REST](https://coder-studio.com/tutoriels/api-rest-guide/).

## Les objets req et res

Chaque fonction de route reçoit deux objets essentiels. La **requête** (`req`) décrit ce que le client envoie, la **réponse** (`res`) est ce que vous renvoyez.

Du côté de `req`, les propriétés les plus utiles sont :

-   `req.params` — les paramètres d’URL (`/articles/:id`).
-   `req.query` — la _query string_ (`/articles?tri=date&page=2`).
-   `req.body` — le corps de la requête, disponible grâce au middleware `express.json()`.
-   `req.headers` — les en-têtes HTTP.

Du côté de `res`, on enchaîne généralement un code de statut et un contenu :

```
res.status(201).json({ id: 3, titre: "Nouvel article" });
```

-   `res.json(...)` envoie une réponse JSON avec le bon en-tête `Content-Type`.
-   `res.status(code)` fixe le code de statut HTTP.
-   `res.send(...)` envoie du texte ou du HTML.

## Créer et modifier des ressources

Voyons maintenant la création et la mise à jour, qui exploitent `req.body` :

```
// Créer un article
app.post("/articles", (req, res) => {
  const { titre } = req.body;
  if (!titre) {
    return res.status(400).json({ erreur: "Le titre est obligatoire" });
  }
  const nouvel = { id: Date.now(), titre };
  articles.push(nouvel);
  res.status(201).json(nouvel);
});

// Modifier un article
app.patch("/articles/:id", (req, res) => {
  const article = articles.find(a => a.id === Number(req.params.id));
  if (!article) {
    return res.status(404).json({ erreur: "Article introuvable" });
  }
  if (req.body.titre) article.titre = req.body.titre;
  res.json(article);
});

// Supprimer un article
app.delete("/articles/:id", (req, res) => {
  articles = articles.filter(a => a.id !== Number(req.params.id));
  res.status(204).end();
});
```

Remarquez les codes de statut choisis avec soin : `201 Created` après une création, `400 Bad Request` en cas de données invalides, `404 Not Found` quand la ressource n’existe pas, `204 No Content` après une suppression réussie. Une API honnête reflète toujours le résultat dans son code de statut.

## Les middlewares, cœur d’Express

Un **middleware** est une fonction qui s’exécute entre la réception d’une requête et l’envoi de la réponse. Elle reçoit trois arguments : `req`, `res` et `next`, cette dernière permettant de passer au middleware suivant. C’est le mécanisme central d’Express : l’authentification, la journalisation, la validation ou la gestion CORS sont tous des middlewares.

Un exemple simple qui journalise chaque requête :

```
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next(); // sans cet appel, la requête reste bloquée
});
```

Placé avant les routes, ce middleware s’exécute pour chaque requête. L’oubli de `next()` est une erreur classique : sans lui, la requête n’atteint jamais la route et le client attend indéfiniment.

## Gérer les erreurs proprement

Express dispose d’un type particulier de middleware pour les erreurs, reconnaissable à ses **quatre arguments**. Placé en dernier, il capture toutes les erreurs survenues dans les routes :

```
app.use((erreur, req, res, next) => {
  console.error(erreur.stack);
  res.status(erreur.status || 500).json({
    erreur: erreur.message || "Erreur interne du serveur"
  });
});
```

Pour l’utiliser, il suffit de passer une erreur à `next()` dans une route, ou de lever une exception dans une fonction asynchrone correctement encadrée. Centraliser la gestion des erreurs évite de répéter la même logique dans chaque route.

## Structurer son projet

Tout mettre dans un seul `server.js` fonctionne pour apprendre, mais devient vite ingérable. Une structure éprouvée sépare les responsabilités :

```
mon-api/
├── server.js          # point d'entrée, configuration Express
├── routes/
│   └── articles.js    # les routes liées aux articles
├── controllers/
│   └── articles.js    # la logique métier
└── package.json
```

Express propose l’objet `Router` pour découper les routes par domaine :

```
// routes/articles.js
import { Router } from "express";
const router = Router();

router.get("/", listerArticles);
router.post("/", creerArticle);

export default router;

// server.js
import articlesRouter from "./routes/articles.js";
app.use("/articles", articlesRouter);
```

Toutes les routes du fichier `articles.js` sont ainsi préfixées par `/articles`, ce qui garde le point d’entrée lisible même quand l’API grandit.

## Connecter une base de données

Nos exemples stockaient les données dans un tableau en mémoire — elles disparaissent au redémarrage. En production, on connecte une vraie base. La logique reste identique : on remplace les opérations sur le tableau par des appels à la base, généralement asynchrones :

```
app.get("/articles", async (req, res, next) => {
  try {
    const articles = await db.query("SELECT * FROM articles");
    res.json(articles);
  } catch (erreur) {
    next(erreur); // délègue au middleware d'erreur
  }
});
```

Le bloc `try/catch` combiné à `next(erreur)` est le motif standard pour gérer les erreurs asynchrones. En pratique, on passe souvent par un ORM comme Prisma ou Sequelize, qui traduit ces requêtes en appels JavaScript plus lisibles. Le point clé : Express ne se soucie pas de la base utilisée, il orchestre simplement requêtes et réponses.

## En résumé

Express transforme Node.js en une plateforme d’API productive avec très peu de cérémonie : des routes claires par verbe HTTP, des middlewares composables, des objets `req` et `res` expressifs, et une gestion des erreurs centralisée. Commencez petit avec un seul fichier, puis découpez en routes et contrôleurs à mesure que le projet grossit. C’est cette simplicité assumée qui explique la longévité d’Express dans l’écosystème JavaScript.

## À lire ensuite

-   [API REST : principes et bonnes pratiques](https://coder-studio.com/tutoriels/api-rest-guide/) — les conventions à respecter pour concevoir de bonnes API.
-   [Le CRUD expliqué : Create, Read, Update, Delete](https://coder-studio.com/tutoriels/crud-guide/) — les quatre opérations que votre API implémente.
-   [Node.js : débuter le développement côté serveur](https://coder-studio.com/tutoriels/nodejs-debutant/) — revenir aux fondations si besoin.
