Il problema: l'API di WordPress non fa quello che ti serve
Hai un'app React, un'app mobile, o un sistema esterno che deve parlare con il tuo WordPress. Le route standard di WP — post, pagine, utenti — ci sono, ma le tue esigenze sono diverse: vuoi esporre metadati personalizzati, lanciare una logica di business, integrare un plugin fatto su misura. Oppure vuoi che solo utenti autenticati possano scrivere o leggere certi dati. La WordPress REST API ti dà tutto questo, ma devi sapere come usarla bene. Noi, di Meteora Web, lo facciamo ogni giorno: dai siti WooCommerce con calcoli di spedizione custom a portali B2B con ruoli personalizzati. Ecco come fare.
Le basi: registrare una route custom
Per creare un endpoint personalizzato devi usare la funzione register_rest_route. Va chiamata all'interno di un hook sull'inizializzazione dell'API, di solito rest_api_init. Mettiamo il codice in un plugin o nel file functions.php del tema (anche se meglio un plugin per modularità). Ecco un esempio concreto: un endpoint che restituisce i prodotti più venduti (se sei su WooCommerce).
add_action( 'rest_api_init', function () {
register_rest_route( 'mio-plugin/v1', '/prodotti-top/', array(
'methods' => 'GET',
'callback' => 'mia_funzione_get_top_products',
'permission_callback' => '__return_true',
) );
} );
function mia_funzione_get_top_products( $data ) {
// Logica per ottenere i prodotti più venduti
$prodotti = wc_get_products( array( 'orderby' => 'total_sales', 'order' => 'DESC', 'limit' => 5 ) );
$response = array();
foreach ( $prodotti as $prodotto ) {
$response[] = array(
'id' => $prodotto->get_id(),
'nome' => $prodotto->get_name(),
'prezzo'=> $prodotto->get_price(),
'url' => get_permalink( $prodotto->get_id() ),
);
}
return new WP_REST_Response( $response, 200 );
}Spiegazione veloce: il namespace mio-plugin/v1 evita conflitti con altri plugin. Il metodo GET, il callback è la funzione che esegue la logica. permission_callback qui è pubblico, ma nella realtà vorrai proteggerlo. L'oggetto $data contiene parametri della richiesta (query params, body, etc.).
Cosa fare subito
Prova a creare un endpoint che restituisca l'elenco dei tag di un post. Usa register_rest_route con un parametro {id} — ad esempio /mio-plugin/v1/post/(?P. Poi chiamalo dal browser con /wp-json/mio-plugin/v1/post/42/tags.
Autenticazione: perché non basta mettere __return_true
Se il tuo endpoint modifica dati (POST, PUT, DELETE) o espone dati sensibili, devi autenticare la richiesta. WordPress ha tre metodi principali: Cookie authentication (di default per utenti loggati), Nonce (per applicazioni JavaScript nello stesso dominio), OAuth 1.0a o JWT (per app esterne). Noi usiamo spesso i nonce per plugin WordPress + frontend React mounted sullo stesso dominio, e JWT per app mobile o multi-dominio.
Nonce: il metodo più semplice (e sottovalutato)
I nonce sono token temporanei che verificano la provenienza della richiesta. Funzionano solo per utenti loggati. Ecco come integrarli:
// Nel tuo plugin, registra la route
register_rest_route( 'mio-plugin/v1', '/aggiorna-prezzo/(?P\d+)', array(
'methods' => 'POST',
'callback' => 'aggiorna_prezzo_callback',
'permission_callback' => function () {
// Simile a check_admin_referer ma per REST
return current_user_can( 'edit_posts' ) && wp_verify_nonce( $_SERVER['HTTP_X_WP_NONCE'] ?? '', 'wp_rest' );
},
) );
function aggiorna_prezzo_callback( $request ) {
$id = $request['id'];
$nuovo_prezzo = $request->get_param( 'prezzo' );
// ... logica di aggiornamento
return new WP_REST_Response( [ 'success' => true ], 200 );
} Nel frontend JavaScript (con React o vanilla), devi passare l'header X-WP-Nonce usando il nonce generato da wp_localize_script:
// In functions.php
wp_localize_script( 'mio-script', 'wpApiSettings', array(
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' ),
) );Poi nella tua fetch:
fetch( wpApiSettings.root + 'mio-plugin/v1/aggiorna-prezzo/123', {
method: 'POST',
headers: {
'X-WP-Nonce': wpApiSettings.nonce,
'Content-Type': 'application/json',
},
body: JSON.stringify( { prezzo: 29.99 } ),
} );JWT per app mobile e client esterni
Quando l'app non è nello stesso dominio (es. app React Native, Flutter, o un servizio Node.js), i nonce non funzionano perché basati sui cookie di sessione. Serve un token JWT. Installi il plugin JWT Authentication for WP REST API (o un equivalente) e configuri l'autenticazione. Attenzione: richiede di modificare le regole di rewrite e impostare una secret key nel wp-config.php. Il flusso è semplice: l'utente fa login a /wp-json/jwt-auth/v1/token con username e password, riceve un token, e lo passa in ogni richiesta come header Authorization: Bearer <token>. Ecco un esempio di permission_callback per route JWT protette:
// Assumendo che il plugin JWT sia attivo
add_action( 'rest_api_init', function () {
register_rest_route( 'mio-plugin/v1', '/dati-riservati', array(
'methods' => 'GET',
'callback' => 'dati_riservati_callback',
'permission_callback' => function () {
// Il plugin JWT gestisce già l'autenticazione e setta $current_user
// Basta controllare che l'utente sia loggato
return is_user_logged_in();
},
) );
} );Attenzione: il plugin JWT per WP richiede alcune accortezze — abilita i permalink, setta JWT_AUTH_SECRET_KEY in wp-config, e gestisci il refresh del token (il token scade). Se vuoi una soluzione più controllata, puoi costruire tu stesso un middleware che verifica il token, ma noi consigliamo di partire da plugin collaudati.
Errori comuni e come evitarli
Non restituire mai WP_Error direttamente
Se usi return new WP_Error( 'codice', 'Messaggio' );, WordPress lo trasformerà automaticamente in una risposta JSON con status 500. Meglio usare WP_REST_Response con status appropriato.
Namespace e permission_callback
Non dimenticare di dichiarare permission_callback. Se non lo fai, WordPress restituisce errore 403 per default. Per endpoint pubblici usa 'permission_callback' => '__return_true'.
Cache delle route
WordPress cache le route registrate. Se modifichi il codice, disattiva e riattiva il plugin o vai in Impostazioni -> Permalink e salva di nuovo.
Quando conviene un endpoint custom? Un caso reale
Un nostro cliente, un negozio di abbigliamento (sì, abbiamo gestito il loro ERP), voleva un'app mobile per lo staff che leggesse giacenze e prezzi in tempo reale. L'API default di WooCommerce andava bene per la lettura, ma le modifiche rapide (sconti last minute) richiedevano un endpoint custom con logica di business (es. applica sconto solo se il prodotto è in saldo). Abbiamo creato route protette con JWT, utilizzabili dall'app senza esporre le credenziali dell'amministratore. Un altro caso: una piattaforma di prenotazioni con Vue.js che parlava a WordPress headless — l'autenticazione con nonce era perfetta perché tutto girava sullo stesso dominio.
In sintesi — cosa fare adesso
- Scegli il tipo di autenticazione: nonce per frontend integrato, JWT per client esterni, cookie per amministrazione.
- Registra la prima route protetta: parti da un esempio semplice (es. GET che restituisce dati di un utente loggato).
- Testa con Postman o cURL: verifica che l'autenticazione funzioni e che i permessi siano corretti.
- Metti in sicurezza: non dimenticare di validare e sanificare i parametri in input (
sanitize_text_field,absint). - Documenta il tuo endpoint: aggiungi un paragrafo nel README del plugin per i futuri sviluppatori (o per te tra sei mesi).
Se hai bisogno di un'architettura headless complessa o di integrare WordPress con servizi esterni, contattaci. Noi lavoriamo su questi temi tutti i giorni.
Sponsored Protocol