« Cette API a l’air pratique, on va juste requêter /wp-json/wp/v2/ directement depuis le front. » Cette phrase, prononcée en début de projet, mérite qu’on s’y arrête un instant, car elle sous-entend souvent une méconnaissance de ce que WordPress expose réellement sans le moindre réglage préalable. La documentation officielle sur developer.wordpress.org le précise clairement : la plupart des routes de l’API REST sont accessibles publiquement dès l’activation du cœur, sans qu’aucune authentification ne soit requise pour la lecture.
Pour un développeur qui découvre le développement headless, cette accessibilité par défaut peut sembler être un simple confort. Elle mérite pourtant d’être inventoriée précisément avant toute mise en production, tant certaines routes révèlent des informations que l’équipe éditoriale ne pensait pas rendre publiques.
Un inventaire simple avec WP-CLI
La commande suivante liste l’ensemble des routes enregistrées sur une installation donnée, avec leurs méthodes disponibles :
wp rest-api list 2>/dev/null || curl -s https://exemple.test/wp-json/ | php -r \
"echo implode(PHP_EOL, array_keys(json_decode(file_get_contents('php://stdin'), true)['routes']));"
Sur une installation fraîche, sans extension particulière, cette liste couvre déjà les contenus (/wp/v2/posts, /wp/v2/pages), les médias, les catégories et étiquettes, les commentaires, et surtout les utilisateurs via /wp/v2/users.
Ce que révèle la route des utilisateurs
C’est souvent la découverte la plus surprenante pour une équipe qui migre vers un usage headless : la route /wp/v2/users retourne, sans authentification, la liste des comptes disposant d’au moins un contenu publié, avec leur identifiant numérique, leur pseudonyme public (slug) et leur nom affiché. Sur un site où le pseudonyme correspond, par négligence, à l’identifiant de connexion, cette route offre gratuitement la moitié du travail à quiconque cherche à deviner des identifiants valides.

Le cas des contenus non destinés au public
Les types de contenus personnalisés déclarés avec show_in_rest => true héritent, sauf réglage contraire, du même comportement public que les articles standards. Un type de contenu interne, pensé pour un usage strictement administratif, mais exposé par erreur dans l’API, se retrouve accessible à quiconque connaît ou devine son chemin de route.
Ce qui reste protégé sans intervention
Toutes les routes ne sont pas ouvertes de la même façon. Les opérations d’écriture — création, modification, suppression — restent, elles, correctement protégées par défaut grâce au mécanisme de permission_callback, qui vérifie les capacités de l’utilisateur authentifié avant d’autoriser l’action. C’est spécifiquement la lecture qui est permissive par conception, dans une logique historique de compatibilité avec l’affichage public d’un site classique.
| Route | Accès sans authentification | Donnée exposée |
|---|---|---|
/wp/v2/posts | Lecture seule | Contenus publiés |
/wp/v2/users | Lecture seule | Identifiants et pseudonymes publics |
/wp/v2/posts (écriture) | Refusée | Aucune sans jeton valide |
| Types personnalisés | Selon show_in_rest | Variable selon déclaration |
Réduire l’exposition sans tout bloquer
La réponse ne consiste pas à désactiver l’API REST dans son ensemble, ce qui casserait l’éditeur de blocs lui-même, mais à filtrer précisément ce qui doit rester accessible. Le filtre rest_endpoints permet de retirer des méthodes sur des routes spécifiques :
add_filter( 'rest_endpoints', function ( $endpoints ) {
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'][0] );
}
return $endpoints;
} );
Pour un type de contenu personnalisé qui ne doit jamais transiter par l’API publique, il suffit de ne pas déclarer show_in_rest, ou de retirer sélectivement la visibilité tout en gardant un accès authentifié via un permission_callback personnalisé.
Les bons réflexes avant mise en production
- Lister systématiquement les routes exposées avant chaque mise en ligne, pas seulement lors de l’audit initial du projet.
- Vérifier le contenu exact retourné par
/wp/v2/userset masquer les champs superflus viaregister_rest_field()si nécessaire. - Documenter, pour chaque type personnalisé, la décision explicite d’exposition ou non dans l’API REST.
Une route publique par défaut n’est pas une faille en soi : c’est un choix de conception hérité de l’histoire de WordPress. Le problème apparaît quand personne dans l’équipe n’a vérifié ce que ce choix implique concrètement pour le projet en cours.
En résumé
Avant d’écrire la moindre ligne de code côté front, un inventaire des routes exposées par défaut évite bien des mauvaises surprises. Ce réflexe, simple à mettre en place avec WP-CLI ou un appel direct à /wp-json/, mérite de figurer systématiquement dans la checklist de démarrage de tout projet headless.