vendredi 25 septembre 2026

À propos

Contact

Headless & API

Exposer un CPT en lecture seule via l’API REST sans installer d’extension

Pas besoin d'un plugin supplémentaire pour rendre un type de contenu personnalisé accessible en lecture depuis un front headless. Trois arguments suffisent, correctement réglés.

Par Clément Hadrot • 9 avril 2020 • 4 min de lecture • Aucun commentaire
Exposer un CPT en lecture seule via l'API REST sans installer d'extension

Un client nous a récemment demandé d’ajouter un type de contenu « Témoignages » à son site headless, sans rien écrire côté React. Sa première réaction a été de chercher un plugin pour « exposer ça en API ». Il n’y en avait pas besoin. WordPress sait exposer un type de contenu personnalisé via l’API REST nativement depuis longtemps, à condition de déclarer le bon type avec les bons arguments.

Cette recette couvre le cas le plus fréquent d’un front headless simple : un CPT lu uniquement en front public, jamais modifié depuis le site, sans champ personnalisé complexe à gérer pour l’instant. Les champs ACF et les mutations en écriture sont volontairement laissés de côté, ils méritent un traitement à part.

Le problème : un CPT invisible pour l’API REST par défaut

Par défaut, register_post_type() ne rend pas un type de contenu accessible à l’API REST, même s’il apparaît normalement dans l’administration. C’est un choix délibéré de WordPress : rien n’est exposé publiquement sans déclaration explicite. Un développeur pressé ajoute parfois une extension entière juste pour ce comportement, alors que trois arguments du même register_post_type() suffisent.

Le snippet commenté

add_action( 'init', function () {
    register_post_type( 'temoignage', array(
        'labels'       => array(
            'name'          => 'Témoignages',
            'singular_name' => 'Témoignage',
        ),
        'public'       => true,
        'has_archive'  => false,
        'supports'     => array( 'title', 'editor', 'thumbnail' ),

        // Les trois réglages qui comptent pour l'API REST :
        'show_in_rest'  => true,               // active l'exposition REST
        'rest_base'     => 'temoignages',       // URL: /wp-json/wp/v2/temoignages
        'rest_controller_class' => 'WP_REST_Posts_Controller', // valeur par défaut, explicite ici
    ) );
} );
L'essentiel à retenir : show_in_rest suffit pour l'essentiel ; rest_base évite les collisions d'URL ; Un contexte de lecture seule se garde sans permission_callback complexe

Avec ces réglages, le point de terminaison GET /wp-json/wp/v2/temoignages devient immédiatement disponible, avec pagination, filtres et champ context hérités du contrôleur natif, sans une ligne de code supplémentaire côté API.

Verrouiller l’accès en lecture seule

Le contrôleur par défaut de WordPress gère déjà les méthodes d’écriture (POST, PUT, DELETE) en vérifiant les permissions de l’utilisateur connecté. Sans compte authentifié, ces méthodes échouent naturellement avec une erreur 401. Pour un front headless anonyme, ce comportement par défaut correspond exactement au besoin : lecture publique, écriture réservée aux comptes autorisés dans l’administration. Aucun permission_callback personnalisé n’est nécessaire dans ce cas précis.

Si l’on veut être plus strict encore et empêcher toute tentative d’écriture même par un compte mal configuré, on peut désactiver l’édition côté REST sans toucher à l’administration :

add_filter( 'rest_prepare_temoignage', function ( $response ) {
    // Purement défensif : on ne modifie rien ici,
    // le filtre sert de point d'ancrage pour un futur contrôle.
    return $response;
} );

Vérifier ce qui est réellement exposé

Une erreur fréquente consiste à supposer que show_in_rest suffit sans vérifier le résultat concret. La commande WP-CLI suivante liste tous les types de contenu et indique lesquels sont exposés :

wp post-type list --fields=name,show_in_rest,rest_base

Elle permet de repérer en une ligne un CPT oublié, ou un rest_base qui entre en collision avec un autre point de terminaison déjà utilisé par un plugin tiers.

Les pièges à éviter

  • Oublier rest_base : WordPress utilisera par défaut le nom du type de contenu, parfois moins lisible côté front (temoignage au singulier plutôt que temoignages).
  • Déclarer le CPT après le hook rest_api_init : le crochet init reste le bon choix, il s’exécute avant l’initialisation de l’API REST.
  • Confondre public et show_in_rest : un CPT public dans l’administration n’est pas automatiquement exposé côté API, ce sont deux réglages indépendants.

Variantes utiles

Pour restreindre les champs renvoyés sans installer de plugin, il est possible de filtrer directement la réponse avec rest_prepare_{post_type}, en retirant du tableau $response->data les clés non désirées avant de le retourner. C’est une alternative légère à register_rest_field quand il s’agit seulement de masquer des champs natifs plutôt que d’en ajouter de nouveaux.

Autre variante fréquente : limiter le nombre de résultats par défaut avec l’argument rest_default_per_page disponible depuis les versions récentes de l’API, pour éviter qu’un front mal codé ne récupère l’intégralité des témoignages en un seul appel.

En résumé

Trois arguments de register_post_type(), un hook init, et un point de terminaison REST en lecture seule est prêt, sans dépendance externe. Cette approche minimale convient parfaitement à un front headless qui se contente de lire du contenu : elle évite d’ajouter une extension de plus à maintenir, pour un besoin que le cœur de WordPress couvre déjà très bien.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi