Créer une API REST simplement : le guide qui change tout

Pourquoi s'embêter avec une API REST quand un fichier JSON suffit ? Découvrez comment en créer une vraiment fonctionnelle, de zéro, avec les erreurs à éviter et les raccourcis qui coûtent cher.

Créer une API REST simplement : le guide qui change tout

Il y a une question qu'on me pose à chaque fois que je parle d'API REST autour de moi : « mais pourquoi tu t'embêtes avec ça alors qu'un simple fichier JSON suffit ? »

Bonne question. Et honnêtement, dans 80 % des petits projets que je vois passer, un fichier JSON suffit effectivement. Sauf qu'à partir du moment où deux programmes doivent se parler en temps réel, où une appli mobile doit lire les mêmes données qu'un site web, où vous voulez ajouter une fonctionnalité sans tout réécrire… là, le fichier JSON montre ses limites. Et c'est précisément là qu'une API REST entre en jeu.

Je vais vous montrer comment en créer une de zéro à quelque chose qui tourne vraiment, pas juste un « bonjour le monde » qui plante dès la première requête authentifiée. Avec du code, des erreurs que j'ai faites, et les raccourcis qui m'ont coûté cher.

Points clés à retenir

  • Une API REST, c'est une convention d'échange de données basée sur HTTP : des URL qui représentent des ressources, des verbes (GET, POST, PUT, DELETE) qui décrivent l'action.
  • Le choix du langage compte moins que la façon dont vous structurez vos routes et vos réponses.
  • L'authentification et la gestion des erreurs ne sont pas des détails : ce sont les deux choses qui font basculer un prototype en outil utilisable.
  • Un exemple complet et testé vaut mille diagrammes.
  • Documenter son API coûte une heure et vous économise des dizaines d'échanges par mail avec vos collègues.
  • Versionner dès le départ (même grossièrement) évite de casser tous vos clients à la première modification.

API REST, c'est quoi vraiment ?

Une API REST, c'est un contrat. Vous exposez des ressources (un utilisateur, une commande, un article de blog), accessibles via des URL stables, manipulables avec les verbes HTTP standard. Un client envoie une requête, le serveur répond du JSON. Point.

Ce qui rend REST intéressant, ce n'est pas la techno. C'est la contrainte.

Les quatre contraintes qui comptent

Sur le papier, REST en compte davantage. En pratique, quatre seulement ont un impact réel sur votre code :

  • Sans état : chaque requête porte tout ce dont elle a besoin. Le serveur ne se souvient de rien entre deux appels. Vous devez donc transmettre un token à chaque fois.
  • Interface uniforme : toujours les mêmes verbes, toujours les mêmes conventions de nommage. C'est ce qui rend une API prévisible pour celui qui l'utilise.
  • Client-serveur découplés. L'appli mobile peut changer du tout au tout sans que vous touchiez au serveur.
  • Réponses cacheables. Un GET sur une ressource publique peut être mis en cache, ce qui vous évite de recalculer bêtement.

Le piège classique que je vois chez les débutants : vouloir gérer une « session » côté serveur. Mauvaise idée. Vous perdez tout l'intérêt du modèle et vous rendez la mise à l'échelle pénible.

Créer une API REST en Python : un exemple qui marche

Je vais prendre Python parce que c'est ce que j'utilise le plus quand je veux prototyper vite. Le choix du langage importe peu : la logique est identique en Node, en Java ou en Go.

Créer une API REST en Python : un exemple qui marche

Deux options s'offrent à vous. La première : tout écrire à la main avec la bibliothèque standard. La deuxième : utiliser un framework. J'ai fait les deux. La première m'a fait perdre une semaine pour réinventer le routage, la gestion des méthodes HTTP et le parsing du corps de requête. La deuxième me prend dix minutes.

L'option que je recommande

FastAPI, concrètement, vous donne du routage, de la validation de données et une documentation interactive générée automatiquement. Flask fait la même chose en plus minimaliste. Les deux tiennent la charge pour des projets sérieux.

Voici le squelette que j'utilise systématiquement, celui d'une mini-API de gestion de tâches :

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
from uuid import uuid4

app = FastAPI()

taches = {}

class TacheEntree(BaseModel):
    titre: str
    terminee: bool = False

class TacheSortie(TacheEntree):
    id: str

@app.get("/taches")
def lister_taches():
    return list(taches.values())

@app.post("/taches", status_code=201)
def creer_tache(t: TacheEntree):
    identifiant = str(uuid4())
    tache = TacheSortie(id=identifiant, **t.dict())
    taches[identifiant] = tache
    return tache

@app.get("/taches/{tache_id}")
def lire_tache(tache_id: str):
    if tache_id not in taches:
        raise HTTPException(status_code=404, detail="Tâche introuvable")
    return taches[tache_id]

@app.delete("/taches/{tache_id}", status_code=204)
def supprimer_tache(tache_id: str):
    if tache_id not in taches:
        raise HTTPException(status_code=404, detail="Tâche introuvable")
    del taches[tache_id]

Lancez-le avec uvicorn main:app --reload, ouvrez /docs, vous avez une interface pour tester chaque route. C'est gratuit, c'est automatique, et ça vous évite d'écrire un Postman à la main.

Vérifier que ça tourne (sans se mentir)

Le test le plus rapide reste curl :

curl -X POST http://localhost:8000/taches \
  -H "Content-Type: application/json" \
  -d '{"titre": "Écrire cet article"}'

Si la réponse vous renvoie un identifiant et le bon code 201, c'est gagné. Si vous obtenez un 422, c'est que le corps de la requête ne respecte pas le schéma attendu. J'ai passé un après-midi entier sur un 422 qui venait simplement d'une virgule manquante dans mon JSON… avouons-le, ça arrive à tout le monde.

Convention de nommage : la partie où tout le monde se dispute

Deux camps s'opposent. Ceux qui écrivent /getTaches et ceux qui écrivent /taches. Je suis dans le second, et je vais être franc : le premier camp a tort.

Convention de nommage : la partie où tout le monde se dispute

Les règles que j'applique

  • Des noms au pluriel pour les collections : /utilisateurs, /commandes.
  • Jamais de verbe dans l'URL. L'action est déjà dans la méthode HTTP.
  • Des tirets pour séparer les mots : /lignes-commande, pas /lignesCommande ni /lignes_commande.
  • Minuscules partout. Les URL sont sensibles à la casse, et vous vous remercierez plus tard.
  • Les identifiants directement dans le chemin : /utilisateurs/42/commandes pour les commandes d'un utilisateur précis.

Une exception que j'accepte volontiers : les actions qui ne correspondent à aucune des quatre opérations de base. Par exemple /utilisateurs/42/reinitialiser-mot-de-passe. C'est un verbe, ça casse la convention, mais c'est lisible. Je préfère ça à un POST sur /utilisateurs/42 qui ferait secrètement quelque chose de non documenté.

Ce que personne ne vous montre jamais

Tous les tutoriels s'arrêtent au CRUD. Ils taisent les trois sujets qui déterminent si votre API est utilisable ou pas.

Ce que personne ne vous montre jamais

Authentification : le minimum vital

Sans auth, votre API est un guichet ouvert. La solution la plus simple et la plus répandue aujourd'hui reste le JWT (jeton signé). Le client s'authentifie une fois, récupère un jeton, l'envoie dans l'en-tête Authorization: Bearer xxx à chaque requête. OAuth 2 sert quand vous devez déléguer l'authentification à un tiers (Google, GitHub).

Erreur de débutant que j'ai commise : stocker le mot de passe en clair dans la base. Une fois. Je ne le referai pas. Utilisez bcrypt ou l'équivalent, jamais de hash maison.

Les codes de statut, sans en faire des tonnes

Vous n'avez pas besoin de connaître les 60 codes HTTP. Six suffisent à couvrir 95 % des cas :

CodeSignificationQuand l'utiliser
200OKRequête réussie qui renvoie des données
201CreatedCréation réussie
204No ContentSuppression réussie, sans corps
400Bad RequestRequête mal formée
404Not FoundRessource inexistante
500Server ErrorBug de votre côté

Un 200 renvoyé pour une erreur, c'est la plaie. J'ai passé une journée à debugger une intégration parce que l'API d'en face renvoyait systématiquement 200 avec un champ error: true dans le corps. Ne faites pas ça.

Pagination : indispensable dès 100 lignes

Une collection qui peut grossir, ça se pagine. Le standard de fait : ?limit=20&offset=40 pour les listes simples, ou un curseur (?cursor=abc123) quand les données changent en permanence. Sans pagination, votre API tiendra jusqu'à son premier client qui a beaucoup de données, et là elle tombera.

API REST en Java ou en Python : comment choisir ?

Franchement, la question du langage arrive loin derrière celle du contexte. Si vous êtes dans un environnement d'entreprise avec Spring Boot déjà installé, partez sur Java. Si vous êtes une équipe de deux qui doit livrer vite, Python ou Node.

Voici le tableau que j'aurais aimé trouver quand j'ai débuté :

ContexteLangage conseilléPourquoi
Prototype rapide, équipe réduitePython (FastAPI) ou NodePeu de code pour beaucoup de fonctionnalités
Grande entreprise, forte contrainte de typageJava (Spring Boot)Écosystème mature, outils de suivi éprouvés
Besoin de performance bruteGoConcurrence native, binaire léger
Vous connaissez déjà un langageCelui-làRien ne remplace la familiarité

Le « cours API REST PDF » que vous cherchez peut-être n'existe pas en version parfaite. La vraie doc, c'est celle que vous générez vous-même en écrivant vos premiers endpoints. Je le pense sincèrement.

Passer en production : les trois choses qui changent tout

Trois ajouts font la différence entre un projet de week-end et une API qui vit plusieurs années.

D'abord la documentation. FastAPI la génère via OpenAPI, vous n'avez rien à faire au-delà des docstrings. Pour les autres frameworks, écrivez un fichier OpenAPI à la main, ça vous prend une heure et ça sauve des dizaines d'échanges avec vos collègues.

Ensuite, la version. Mettez /v1/ devant toutes vos routes dès le premier jour. Vous vous direz que c'est prématuré. Ce ne l'est jamais. Le jour où vous devrez modifier un champ sans casser les clients en production, vous me remercierez.

Enfin, les tests. Pas besoin d'une usine. Un fichier qui pytest vos routes principales, avec une base de test séparée, couvre 90 % des régressions. J'ai longtemps considéré les tests comme une perte de temps. Je me suis trompé. Ce qui m'a convaincu, c'est un bug en production un vendredi soir qui aurait été détecté par un test de cinq lignes.

Voilà. Une API REST, vous en avez maintenant une qui tient debout. La prochaine étape, celle que je repousse moi-même depuis des mois, c'est d'y brancher un vrai monitoring. Un jour.

Olivier Turpin

Olivier Turpin est un expert reconnu en sécurité des réseaux, en tests d'intrusion et en cryptographie appliquée. Il accompagne les organisations dans l'évaluation de leurs vulnérabilités et le renforcement de leurs défenses face aux menaces numériques. Passionné par la transmission, il partage volontiers son savoir-faire avec les équipes techniques et les décideurs.

Voir tous les articles →

Articles similaires