« Une route REST, c’est plus léger qu’une page complète, non ? » Cette hypothèse, répandue chez les développeurs qui découvrent le développement headless, mérite d’être corrigée : une requête vers /wp-json/ déclenche le chargement complet du cœur de WordPress, exactement comme le ferait l’affichage d’une page classique. Ce que la route REST évite, c’est uniquement le rendu du gabarit de thème, pas l’initialisation du logiciel dans son ensemble.
Comprendre précisément quels hooks s’exécutent, et dans quel ordre, avant qu’une réponse REST ne soit renvoyée permet de déboguer efficacement un comportement inattendu : un champ manquant, une donnée non filtrée comme prévu, ou une extension qui semble interférer sans lien apparent avec la route concernée.
L’ordre réel d’exécution
Une requête HTTP vers une route de l’API REST traverse la même séquence d’amorçage que n’importe quelle autre requête WordPress, avec quelques hooks spécifiques qui s’ajoutent en cours de route :
plugins_loaded: toutes les extensions actives sont chargées, y compris celles sans lien apparent avec l’API REST.init: les types de contenus personnalisés, les taxonomies et les routes REST elles-mêmes sont enregistrés viaregister_post_type()et consorts.rest_api_init: ce hook spécifique se déclenche uniquement lorsque la requête entrante cible effectivement l’API REST, et sert de point d’ancrage privilégié pourregister_rest_route().- Résolution de la route, exécution du
permission_callback, puis du callback principal.

Ce que cet ordre explique concrètement
Un filtre appliqué deux fois sans raison apparente
Un développeur qui accroche un filtre the_content à la fois dans le rendu classique et dans le traitement d’une route REST personnalisée peut observer une transformation appliquée deux fois si le callback de la route appelle indirectement une fonction qui exécute déjà ce filtre, comme get_the_content() suivi d’un traitement manuel équivalent. Comprendre que init précède l’exécution du callback de route aide à localiser où ce filtre a réellement été accroché et pourquoi il s’applique dans ce contexte précis.
Une extension qui modifie une réponse REST sans y toucher directement
Une extension de sécurité activée sur le site, qui bloque certaines requêtes selon leur en-tête User-Agent dès le hook init, peut empêcher une route REST légitime de répondre correctement, alors que rien dans le code de cette route ne semble concerné. Le fait que plugins_loaded et init s’exécutent avant même que la route ne soit identifiée explique pourquoi ce type d’interférence, en apparence sans rapport, doit systématiquement figurer dans la liste des causes à vérifier.
Utiliser cet ordre pour déboguer efficacement
Ajouter des points de trace à chaque étape clé du cycle permet de confirmer précisément où un comportement diverge de l’attendu :
add_action( 'plugins_loaded', function () {
error_log( 'plugins_loaded : ' . $_SERVER['REQUEST_URI'] );
} );
add_action( 'rest_api_init', function () {
error_log( 'rest_api_init declenche' );
} );
add_filter( 'rest_pre_dispatch', function ( $result, $server, $request ) {
error_log( 'route resolue : ' . $request->get_route() );
return $result;
}, 10, 3 );
Cette instrumentation temporaire, à retirer une fois le diagnostic posé, révèle rapidement si un plugin tiers interfère avant même que la route personnalisée n’entre en jeu, un cas fréquent quand plusieurs extensions de sécurité ou de cache coexistent sur la même installation.
Ce que cela signifie pour la conception
- Une route REST ne dispense jamais d’auditer l’ensemble des extensions actives sur l’installation, même sans lien apparent avec l’API.
- Le hook
rest_api_initreste le point d’ancrage le plus fiable pour enregistrer des routes personnalisées, plutôt queinitseul. - Un comportement inattendu sur une route REST mérite d’être vérifié en remontant tout le cycle, pas seulement le code du callback lui-même.
Une route REST qui répond en apparence de façon isolée reste, sous le capot, un point d’arrivée d’un cycle de chargement complet. Ignorer ce cycle en cas de comportement anormal revient à chercher une clé perdue uniquement sous le lampadaire, là où la lumière est la plus commode.
En résumé
La légèreté apparente d’une réponse REST ne doit pas masquer la réalité de son exécution : le cœur de WordPress tourne intégralement derrière chaque requête, avec ses hooks, ses extensions actives et ses filtres. Garder cet ordre précis en tête simplifie considérablement le débogage d’un comportement qui semble, à première vue, n’avoir aucun lien avec la route concernée.