En este artículo veremos cómo crear endpoints personalizados, cómo incorporarlos en la API REST de WordPress y cómo utilizarlos en desarrollos desacoplados (headless).
Pero, ¿qué es esto de los endpoints?. Los endpoints o puntos finales, nos proporcionan un acceso a una API (en nuestro caso de WordPress) a través de rutas HTTP únicas, con ellas recibimos los datos del sitio a través de objetos de JavaScript mediante el formato JSON (JavaScript Object Notation).
La REST API de WordPress viene activada por defecto y nos proporciona una serie de puntos finales listos para utilizar sin tener que crearlos. Comprueba que la API de tu sitio esta activa introduciendo la siguiente url:
https://misitio.com/wp-json
En ocasiones. tendrás información que no se muestre por defecto en esta API REST de WordPress o simplemente necesitarás que cierta información se pueda consultar de forma pública o privada (con autenticación).
Como desarrollador tu serás el encargado de registrar este contenido para que aparezca en la misma API de WordPress.
Lo necesitarás…
Cuando estés desarrollando una aplicación (móvil o web) y necesitas extraer de forma dinámica información de la base de datos de WordPress.
Si quieras que tu aplicación externa acceda a datos específicos de tu sitio de WordPress que no están disponibles en los endpoints estándar de la API REST.
Si Necesitamos desarrollar una aplicación que nos permite crear, leer, actualizar, eliminar… contenido de WordPress desde Javascript del lado del cliente.
Al crear campos personalizados, taxonomías personalizadas o datos de entidades (custom post types).
Para acceder a información o datos de la base de datos de otros plugins de terceros así como extender su funcionalidad.
En Aplicaciones Desacopladas: Al desarrollar aplicaciones con frameworks como React, Vue.js, Astro o Angular, y necesitas que el frontend obtenga datos del backend de WordPress.
Cuando tu sitio de WordPress necesita comunicarse con APIs de terceros y quieres hacer la intermediación mediante un endpoint personalizado.
Si deseas optimizar la cantidad de datos enviados a través de la API o añadir seguridad adicional.
¿Cómo y con qué funciones de WordPress creamos estos endpoints?
Para crear endpoints personalizados en la API REST de WordPress, utilizamos principalmente el hook rest_api_init
y la función register_rest_route
rest_api_init
: Este hook es crucial ya que se ejecuta cada vez que la API REST de WordPress se inicializa. Dentro de este hook, puedes registrar rutas personalizadas para tu API.
add_action('rest_api_init', function () {
register_rest_route('tu-namespace/v1', '/tu-endpoint/', array(
'methods' => 'GET',
'callback' => 'tu_funcion_callback',
));
});
La función register_rest_route
se utiliza para definir las rutas de los endpoints personalizados. Acepta los siguientes parámetros:
- Namespace: Una cadena que agrupa tus endpoints bajo un espacio de nombres común (ej.,
tu-namespace/v1
). - Ruta: La ruta específica del endpoint (ej.,
/tu-endpoint/
). - Array de Opciones:
- methods: Especifica los métodos HTTP permitidos (
GET
,POST
,PUT
,DELETE
, etc.). - callback: La función de callback que maneja la solicitud.
- args: Parámetros opcionales para validación y sanitización.
- permission_callback: Una función de callback para verificar permisos de acceso.
- methods: Especifica los métodos HTTP permitidos (
Esta función la puedes poner en el archivo functions.php
de tu tema en funcionamiento o en un plugin personalizaciones.
add_action('rest_api_init', function () {
register_rest_route('mi-namespace/v1', '/recursos/', array(
'methods' => 'GET',
'callback' => 'obtener_recursos',
'permission_callback' => 'verificar_permisos_recurso',
));
});
Puedes agregar parámetros y funciones de validación/sanitización. Aquí puedes realizar todas las validación necesarías.
add_action('rest_api_init', function () {
register_rest_route('mi-namespace/v1', '/saludo/(?P<nombre>[a-zA-Z]+)', array(
'methods' => 'GET',
'callback' => 'mi_funcion_saludo',
'args' => array(
'nombre' => array(
'required' => true,
'validate_callback' => function ($param, $request, $key) {
return preg_match('/^[a-zA-Z]+$/', $param);
}
),
),
));
});
function mi_funcion_saludo(WP_REST_Request $request) {
$nombre = $request->get_param('nombre');
return new WP_REST_Response("¡Hola, $nombre!", 200);
}
Puedes especificar diferentes métodos HTTP (GET, POST, PUT, DELETE).
//Endpoint POST con Manejo de Datos
add_action('rest_api_init', function () {
register_rest_route('mi-namespace/v1', '/guardar-datos/', array(
'methods' => 'POST',
'callback' => 'mi_funcion_guardar_datos',
));
});
function mi_funcion_guardar_datos(WP_REST_Request $request) {
$datos = $request->get_json_params();
if (!isset($datos['mensaje'])) {
return new WP_Error('sin_mensaje', 'No se proporcionó un mensaje.', array('status' => 400));
}
$mensaje = sanitize_text_field($datos['mensaje']);
// Aquí se podrían guardar los datos en la base de datos o realizar otra acción.
return new WP_REST_Response("Mensaje guardado: $mensaje", 200);
}
¿Tienes una agencia de desarrollo web?
Te puedo ayudar a realizar desarrollos a medida de WordPress y WooCommerce, programando todo tipo de soluciones a medida si es necesario.
Receta:
En el siguiente turorial crearemos una API básica de recursos, gestionados a través de WordPress con CPT y campos personalizados.
Primero, necesitamos definir el Custom Post Type »Recursos». Este tipo de contenido será privado y solo accesible mediante nuestro endpoint personalizado.
function crear_cpt_recursos() {
$labels = array(
'name' => __('Recursos', 'textdomain'),
'singular_name' => __('Recurso', 'textdomain'),
'menu_name' => __('Recursos', 'textdomain'),
'name_admin_bar' => __('Recurso', 'textdomain'),
'add_new' => __('Añadir Nuevo', 'textdomain'),
'add_new_item' => __('Añadir Nuevo Recurso', 'textdomain'),
'new_item' => __('Nuevo Recurso', 'textdomain'),
'edit_item' => __('Editar Recurso', 'textdomain'),
'view_item' => __('Ver Recurso', 'textdomain'),
'all_items' => __('Todos los Recursos', 'textdomain'),
'search_items' => __('Buscar Recursos', 'textdomain'),
'not_found' => __('No se encontraron recursos.', 'textdomain'),
'not_found_in_trash' => __('No se encontraron recursos en la papelera.', 'textdomain')
);
$args = array(
'labels' => $labels,
'public' => false, // Hace el CPT privado
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'recursos'),
'capability_type' => 'post',
'has_archive' => false,
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
'show_in_rest' => true, // Habilita la API REST para el CPT
);
register_post_type('recursos', $args);
}
add_action('init', 'crear_cpt_recursos');
Ahora crearemos un endpoint que devolverá una lista de recursos, pero solo si se proporciona una clave API válida o si el usuario tiene los permisos adecuados.
add_action('rest_api_init', function () {
register_rest_route('mi-namespace/v1', '/recursos/', array(
'methods' => 'GET',
'callback' => 'obtener_recursos',
'permission_callback' => 'verificar_permisos_recurso',
));
});
Implementaremos una función para verificar si el usuario tiene permisos o si la clave API proporcionada es válida.
function verificar_permisos_recurso(WP_REST_Request $request) {
// Obtener la clave API de la solicitud (puede estar en el header o en los parámetros)
$api_key = $request->get_param('api_key');
// Clave API secreta que solo conocen los usuarios autorizados
$clave_api_secreta = 'mi_clave_api_secreta';
// Verifica si el usuario está logueado y tiene los permisos adecuados
if (current_user_can('edit_posts')) {
return true;
}
// Verifica si la clave API proporcionada es válida
if ($api_key && $api_key === $clave_api_secreta) {
return true;
}
// Si ninguna de las condiciones anteriores se cumple, deniega el acceso
return new WP_Error('sin_permisos', 'No tienes permisos para acceder a estos recursos.', array('status' => 403));
}
La función de callback es donde obtendremos los recursos del CPT y los devolveremos en la respuesta.
WP_REST_Response
es una clase de WordPress diseñada para crear y manejar las respuestas que se devuelven desde un endpoint de la API REST. Proporciona una forma más controlada de manipular las respuestas HTTP, permitiéndote establecer los datos, los códigos de estado HTTP y los encabezados de respuesta de manera más granular.
function obtener_recursos(WP_REST_Request $request) {
// Argumentos para la consulta WP_Query
$args = array(
'post_type' => 'recursos',
'post_status' => 'private',
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => -1, // Obtiene todos los recursos
);
$query = new WP_Query($args);
// Si no hay recursos, devuelve un error
if (!$query->have_posts()) {
return new WP_REST_Response(array('message' => 'No se encontraron recursos.'), 404);
}
$recursos = array();
// Itera sobre los posts y extrae los datos
while ($query->have_posts()) {
$query->the_post();
$recursos[] = array(
'id' => get_the_ID(),
'title' => get_the_title(),
'date' => get_the_date(),
// Puedes añadir más campos si es necesario
);
}
// Restablecer el post global después de la consulta
wp_reset_postdata();
return new WP_REST_Response($recursos, 200);
}
¡Perfecto! Si has introducido estos snippets te animo a probar la siguiente petición HTTP. Puedes tener una API con cientos de URLs, con la que cubrir cualquier necesidad de tus clientes.
https://tusitio.com/wp-json/mi-namespace/v1/recursos/?api_key=mi_clave_api_secreta
Puedes utilizar un programa para hacer peticiones HTTP como puede ser «Postman».
Si necesitas crear claves API privadas, en el perfíl de cada usuario la puedes generar.
¿Qué más se pude hacer?
- Añade campos personalizados en el CPT Recursos y permite que sean visibles en la API REST.
- Si utilizas ACF u otro sistema de campos personalizados, asegúrate de incluirlos en la respuesta del endpoint.
- Asegúrate de que los datos sensibles no se exponen y que las verificaciones de permisos son robustas.
- Filtra el contenido desde la petición con
wp_query
- Considera la paginación si el número de resultados es grande para mejorar el rendimiento.
- Utiliza un mecanismo de caché para mejorar el rendimiento, especialmente si la lista de recursos es grande.
- Crea una documentación de tu API. Hazla todo lo grande que quieras. No hay limitaciones. Explica los endpoints, incluyendo los métodos, rutas, parámetros esperados y ejemplos de respuesta.
- Implementa mecanismos de autenticación si los endpoints requieren acceso protegido (ej., tokens JWT, OAuth).
- Utiliza
fetch
o librerías de AJAX para enviar solicitudes y procesar las respuestas en tu frontend. - Actualiza la interfaz de usuario en función de los datos recibidos y maneja interacciones del usuario en los sitios de forma remota enviando y recibiendo objetos JSON.