API y Endpoints
Esta sección documenta la API de NewBytes, los endpoints REST del plugin y las interfaces de comunicación entre componentes.
🌐 API de NewBytes
URL Base
https://api.nb.com.ar/v1
https://api.nb.com.ar/v1
Autenticación
POST /auth/login
Descripción: Obtiene un token JWT para autenticación en otras operaciones.
Headers:
Content-Type: application/json
Content-Type: application/json
Body:
{
"user": "tu-usuario-newbytes",
"password": "tu-contraseña",
"mode": "wp-extension",
"domain": "https://tu-sitio.com"
}
{
"user": "tu-usuario-newbytes",
"password": "tu-contraseña",
"mode": "wp-extension",
"domain": "https://tu-sitio.com"
}
Respuesta Exitosa (200):
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"expires_in": 3600,
"user_info": {
"id": 12345,
"username": "tu-usuario",
"email": "tu-email@ejemplo.com"
}
}
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"expires_in": 3600,
"user_info": {
"id": 12345,
"username": "tu-usuario",
"email": "tu-email@ejemplo.com"
}
}
Respuesta de Error (401):
{
"error": "invalid_credentials",
"message": "Usuario o contraseña incorrectos"
}
{
"error": "invalid_credentials",
"message": "Usuario o contraseña incorrectos"
}
Implementación en el Plugin:
function nb_get_token()
{
$args = array(
'headers' => array(
'Content-Type' => 'application/json'
),
'body' => json_encode(array(
'user' => get_option('nb_user'),
'password' => get_option('nb_password'),
'mode' => 'wp-extension',
'domain' => home_url()
)),
'timeout' => '5',
'blocking' => true,
);
$response = wp_remote_post(API_URL_NB . '/auth/login', $args);
if (is_wp_error($response)) {
return null;
}
$body = wp_remote_retrieve_body($response);
$json = json_decode($body, true);
return isset($json['token']) ? $json['token'] : null;
}
function nb_get_token()
{
$args = array(
'headers' => array(
'Content-Type' => 'application/json'
),
'body' => json_encode(array(
'user' => get_option('nb_user'),
'password' => get_option('nb_password'),
'mode' => 'wp-extension',
'domain' => home_url()
)),
'timeout' => '5',
'blocking' => true,
);
$response = wp_remote_post(API_URL_NB . '/auth/login', $args);
if (is_wp_error($response)) {
return null;
}
$body = wp_remote_retrieve_body($response);
$json = json_decode($body, true);
return isset($json['token']) ? $json['token'] : null;
}
Catálogo de Productos
GET /products
Descripción: Obtiene el catálogo completo de productos disponibles.
Headers:
Authorization: Bearer {token}
Content-Type: application/json
Authorization: Bearer {token}
Content-Type: application/json
Parámetros de Query (opcionales):
?page=1&limit=100&category=electronics&in_stock=true
?page=1&limit=100&category=electronics&in_stock=true
Respuesta Exitosa (200):
{
"products": [
{
"id": "12345",
"sku": "PROD-001",
"name": "Smartphone Samsung Galaxy A54",
"description": "Smartphone con pantalla de 6.4 pulgadas...",
"price": {
"amount": 299.99,
"currency": "USD",
"with_tax": 362.99,
"without_tax": 299.99
},
"stock": {
"quantity": 15,
"available": true,
"reserved": 2
},
"images": [
{
"url": "https://cdn.nb.com.ar/products/12345/main.jpg",
"alt": "Samsung Galaxy A54 - Vista frontal",
"is_primary": true
}
],
"category": {
"id": "electronics",
"name": "Electrónicos",
"path": "Electrónicos > Smartphones"
},
"attributes": {
"brand": "Samsung",
"model": "Galaxy A54",
"color": "Negro",
"storage": "128GB"
},
"updated_at": "2024-01-15T14:30:25Z"
}
],
"pagination": {
"current_page": 1,
"total_pages": 25,
"total_products": 2500,
"per_page": 100
},
"last_updated": "2024-01-15T14:30:25Z"
}
{
"products": [
{
"id": "12345",
"sku": "PROD-001",
"name": "Smartphone Samsung Galaxy A54",
"description": "Smartphone con pantalla de 6.4 pulgadas...",
"price": {
"amount": 299.99,
"currency": "USD",
"with_tax": 362.99,
"without_tax": 299.99
},
"stock": {
"quantity": 15,
"available": true,
"reserved": 2
},
"images": [
{
"url": "https://cdn.nb.com.ar/products/12345/main.jpg",
"alt": "Samsung Galaxy A54 - Vista frontal",
"is_primary": true
}
],
"category": {
"id": "electronics",
"name": "Electrónicos",
"path": "Electrónicos > Smartphones"
},
"attributes": {
"brand": "Samsung",
"model": "Galaxy A54",
"color": "Negro",
"storage": "128GB"
},
"updated_at": "2024-01-15T14:30:25Z"
}
],
"pagination": {
"current_page": 1,
"total_pages": 25,
"total_products": 2500,
"per_page": 100
},
"last_updated": "2024-01-15T14:30:25Z"
}
Respuesta de Error (401):
{
"error": "unauthorized",
"message": "Token inválido o expirado"
}
{
"error": "unauthorized",
"message": "Token inválido o expirado"
}
Implementación en el Plugin:
function nb_get_products($token)
{
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
),
'timeout' => 30,
'blocking' => true,
);
$response = wp_remote_get(API_URL_NB . '/products', $args);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
function nb_get_products($token)
{
$args = array(
'headers' => array(
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
),
'timeout' => 30,
'blocking' => true,
);
$response = wp_remote_get(API_URL_NB . '/products', $args);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
Producto Individual
GET /products/
Descripción: Obtiene información detallada de un producto específico.
Headers:
Authorization: Bearer {token}
Authorization: Bearer {token}
Respuesta: Mismo formato que el objeto producto en /products
pero con información más detallada.
Verificación de Stock
POST /products/check-stock
Descripción: Verifica el stock actual de múltiples productos.
Body:
{
"product_ids": ["12345", "12346", "12347"]
}
{
"product_ids": ["12345", "12346", "12347"]
}
Respuesta:
{
"stock_info": [
{
"id": "12345",
"stock": 15,
"available": true,
"last_updated": "2024-01-15T14:30:25Z"
}
]
}
{
"stock_info": [
{
"id": "12345",
"stock": 15,
"available": true,
"last_updated": "2024-01-15T14:30:25Z"
}
]
}
🔌 Endpoints REST del Plugin
El plugin expone varios endpoints REST para operaciones remotas y AJAX.
Configuración Base
Namespace: newbytes/v1
URL Base: https://tu-sitio.com/wp-json/newbytes/v1/
Endpoints Disponibles
POST /sync
Descripción: Ejecuta una sincronización manual remota.
Autenticación: WordPress REST API Authentication
Body:
{
"sync_type": "manual",
"force_update": false,
"categories": ["electronics", "clothing"]
}
{
"sync_type": "manual",
"force_update": false,
"categories": ["electronics", "clothing"]
}
Respuesta:
{
"success": true,
"sync_id": "sync_20240115_143025",
"stats": {
"products_processed": 150,
"products_created": 12,
"products_updated": 138,
"products_deleted": 3,
"duration": "2m 34s"
},
"errors": []
}
{
"success": true,
"sync_id": "sync_20240115_143025",
"stats": {
"products_processed": 150,
"products_created": 12,
"products_updated": 138,
"products_deleted": 3,
"duration": "2m 34s"
},
"errors": []
}
Implementación:
// En includes/rest-api.php
add_action('rest_api_init', function () {
register_rest_route('newbytes/v1', '/sync', array(
'methods' => 'POST',
'callback' => 'nb_rest_sync_products',
'permission_callback' => function () {
return current_user_can('manage_options');
}
));
});
function nb_rest_sync_products($request) {
$params = $request->get_json_params();
$sync_type = $params['sync_type'] ?? 'manual';
$result = nb_callback(false, $sync_type);
return new WP_REST_Response($result, 200);
}
// En includes/rest-api.php
add_action('rest_api_init', function () {
register_rest_route('newbytes/v1', '/sync', array(
'methods' => 'POST',
'callback' => 'nb_rest_sync_products',
'permission_callback' => function () {
return current_user_can('manage_options');
}
));
});
function nb_rest_sync_products($request) {
$params = $request->get_json_params();
$sync_type = $params['sync_type'] ?? 'manual';
$result = nb_callback(false, $sync_type);
return new WP_REST_Response($result, 200);
}
GET /status
Descripción: Obtiene el estado actual del plugin y última sincronización.
Respuesta:
{
"plugin_version": "0.1.8",
"is_configured": true,
"is_connected": true,
"last_sync": {
"timestamp": "2024-01-15T14:30:25Z",
"type": "automatic",
"status": "success",
"products_count": 150
},
"next_sync": "2024-01-15T15:00:25Z",
"configuration": {
"sync_interval": 1800,
"prefix_sku": "NB-",
"sync_no_iva": true,
"sync_usd": false
}
}
{
"plugin_version": "0.1.8",
"is_configured": true,
"is_connected": true,
"last_sync": {
"timestamp": "2024-01-15T14:30:25Z",
"type": "automatic",
"status": "success",
"products_count": 150
},
"next_sync": "2024-01-15T15:00:25Z",
"configuration": {
"sync_interval": 1800,
"prefix_sku": "NB-",
"sync_no_iva": true,
"sync_usd": false
}
}
GET /logs
Descripción: Obtiene logs de sincronización con filtros.
Parámetros:
?limit=50&offset=0&type=automatic&status=success&date_from=2024-01-01&date_to=2024-01-31
?limit=50&offset=0&type=automatic&status=success&date_from=2024-01-01&date_to=2024-01-31
Respuesta:
{
"logs": [
{
"id": "log_20240115_143025",
"timestamp": "2024-01-15T14:30:25Z",
"type": "automatic",
"status": "success",
"duration": "2m 34s",
"stats": {
"products_processed": 150,
"products_created": 12,
"products_updated": 138
}
}
],
"pagination": {
"total": 245,
"limit": 50,
"offset": 0
}
}
{
"logs": [
{
"id": "log_20240115_143025",
"timestamp": "2024-01-15T14:30:25Z",
"type": "automatic",
"status": "success",
"duration": "2m 34s",
"stats": {
"products_processed": 150,
"products_created": 12,
"products_updated": 138
}
}
],
"pagination": {
"total": 245,
"limit": 50,
"offset": 0
}
}
🔄 Endpoints AJAX
Sincronización Manual
Action: nb_manual_sync
Method: POST URL: /wp-admin/admin-ajax.php
Data:
{
action: 'nb_manual_sync',
nonce: nb_ajax_object.nonce,
sync_type: 'manual'
}
{
action: 'nb_manual_sync',
nonce: nb_ajax_object.nonce,
sync_type: 'manual'
}
Respuesta:
{
"success": true,
"data": {
"message": "Sincronización completada exitosamente",
"stats": {
"products_processed": 150,
"duration": "2m 34s"
}
}
}
{
"success": true,
"data": {
"message": "Sincronización completada exitosamente",
"stats": {
"products_processed": 150,
"duration": "2m 34s"
}
}
}
Implementación JavaScript:
jQuery(document).ready(function($) {
$('#manual-sync-btn').click(function() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'nb_manual_sync',
nonce: nb_ajax_object.nonce
},
beforeSend: function() {
$('#sync-status').html('Sincronizando...');
},
success: function(response) {
if (response.success) {
$('#sync-status').html('✅ ' + response.data.message);
} else {
$('#sync-status').html('❌ Error: ' + response.data);
}
},
error: function() {
$('#sync-status').html('❌ Error de conexión');
}
});
});
});
jQuery(document).ready(function($) {
$('#manual-sync-btn').click(function() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'nb_manual_sync',
nonce: nb_ajax_object.nonce
},
beforeSend: function() {
$('#sync-status').html('Sincronizando...');
},
success: function(response) {
if (response.success) {
$('#sync-status').html('✅ ' + response.data.message);
} else {
$('#sync-status').html('❌ Error: ' + response.data);
}
},
error: function() {
$('#sync-status').html('❌ Error de conexión');
}
});
});
});
Actualización de Descripciones
Action: nb_update_description_products
Data:
{
action: 'nb_update_description_products',
nb_update_description_all_nonce: nonce_value
}
{
action: 'nb_update_description_products',
nb_update_description_all_nonce: nonce_value
}
Eliminación de Productos
Action: nb_delete_products
Data:
{
action: 'nb_delete_products',
nb_delete_products_nonce: nonce_value,
confirm: true
}
{
action: 'nb_delete_products',
nb_delete_products_nonce: nonce_value,
confirm: true
}
Gestión de Logs
Obtener Datos de Log
Action: nb_get_log_data
Data:
{
action: 'nb_get_log_data',
log_file: 'sync_20240115_143025.json'
}
{
action: 'nb_get_log_data',
log_file: 'sync_20240115_143025.json'
}
Descargar Log
Action: nb_download_log
Limpiar Logs
Action: nb_cleanup_logs
Data:
{
action: 'nb_cleanup_logs',
days: 30,
type: 'all'
}
{
action: 'nb_cleanup_logs',
days: 30,
type: 'all'
}
🛡️ Seguridad en APIs
Autenticación y Autorización
// Verificación de permisos
function nb_check_permissions() {
if (!current_user_can('manage_options')) {
wp_die(__('No tienes permisos suficientes.'));
}
}
// Verificación de nonce
function nb_verify_nonce($action, $nonce_field) {
if (!wp_verify_nonce($_POST[$nonce_field], $action)) {
wp_die(__('Verificación de seguridad fallida.'));
}
}
// Sanitización de datos
function nb_sanitize_input($data) {
if (is_array($data)) {
return array_map('nb_sanitize_input', $data);
}
return sanitize_text_field($data);
}
// Verificación de permisos
function nb_check_permissions() {
if (!current_user_can('manage_options')) {
wp_die(__('No tienes permisos suficientes.'));
}
}
// Verificación de nonce
function nb_verify_nonce($action, $nonce_field) {
if (!wp_verify_nonce($_POST[$nonce_field], $action)) {
wp_die(__('Verificación de seguridad fallida.'));
}
}
// Sanitización de datos
function nb_sanitize_input($data) {
if (is_array($data)) {
return array_map('nb_sanitize_input', $data);
}
return sanitize_text_field($data);
}
Rate Limiting
// Implementación básica de rate limiting
function nb_check_rate_limit($user_id, $action) {
$transient_key = "nb_rate_limit_{$user_id}_{$action}";
$attempts = get_transient($transient_key);
if ($attempts >= 10) {
wp_die(__('Demasiados intentos. Intenta nuevamente en 1 hora.'));
}
set_transient($transient_key, $attempts + 1, HOUR_IN_SECONDS);
}
// Implementación básica de rate limiting
function nb_check_rate_limit($user_id, $action) {
$transient_key = "nb_rate_limit_{$user_id}_{$action}";
$attempts = get_transient($transient_key);
if ($attempts >= 10) {
wp_die(__('Demasiados intentos. Intenta nuevamente en 1 hora.'));
}
set_transient($transient_key, $attempts + 1, HOUR_IN_SECONDS);
}
Validación de Datos
// Validación de entrada para sincronización
function nb_validate_sync_params($params) {
$valid_types = ['manual', 'automatic', 'description'];
if (isset($params['sync_type']) && !in_array($params['sync_type'], $valid_types)) {
return new WP_Error('invalid_sync_type', 'Tipo de sincronización inválido');
}
if (isset($params['categories']) && !is_array($params['categories'])) {
return new WP_Error('invalid_categories', 'Categorías debe ser un array');
}
return true;
}
// Validación de entrada para sincronización
function nb_validate_sync_params($params) {
$valid_types = ['manual', 'automatic', 'description'];
if (isset($params['sync_type']) && !in_array($params['sync_type'], $valid_types)) {
return new WP_Error('invalid_sync_type', 'Tipo de sincronización inválido');
}
if (isset($params['categories']) && !is_array($params['categories'])) {
return new WP_Error('invalid_categories', 'Categorías debe ser un array');
}
return true;
}
📊 Monitoreo y Logging de API
Logging de Requests
function nb_log_api_request($endpoint, $method, $data, $response) {
$log_entry = array(
'timestamp' => current_time('mysql'),
'endpoint' => $endpoint,
'method' => $method,
'request_data' => $data,
'response_code' => wp_remote_retrieve_response_code($response),
'response_body' => wp_remote_retrieve_body($response),
'user_id' => get_current_user_id(),
'ip_address' => $_SERVER['REMOTE_ADDR']
);
// Guardar en log específico de API
error_log(json_encode($log_entry), 3, plugin_dir_path(__FILE__) . '../logs-sync-nb/api-requests.log');
}
function nb_log_api_request($endpoint, $method, $data, $response) {
$log_entry = array(
'timestamp' => current_time('mysql'),
'endpoint' => $endpoint,
'method' => $method,
'request_data' => $data,
'response_code' => wp_remote_retrieve_response_code($response),
'response_body' => wp_remote_retrieve_body($response),
'user_id' => get_current_user_id(),
'ip_address' => $_SERVER['REMOTE_ADDR']
);
// Guardar en log específico de API
error_log(json_encode($log_entry), 3, plugin_dir_path(__FILE__) . '../logs-sync-nb/api-requests.log');
}
Métricas de Rendimiento
function nb_track_api_performance($start_time, $endpoint) {
$duration = microtime(true) - $start_time;
// Guardar métricas
$metrics = get_option('nb_api_metrics', array());
$metrics[$endpoint][] = array(
'duration' => $duration,
'timestamp' => time()
);
// Mantener solo últimas 100 métricas por endpoint
if (count($metrics[$endpoint]) > 100) {
$metrics[$endpoint] = array_slice($metrics[$endpoint], -100);
}
update_option('nb_api_metrics', $metrics);
}
function nb_track_api_performance($start_time, $endpoint) {
$duration = microtime(true) - $start_time;
// Guardar métricas
$metrics = get_option('nb_api_metrics', array());
$metrics[$endpoint][] = array(
'duration' => $duration,
'timestamp' => time()
);
// Mantener solo últimas 100 métricas por endpoint
if (count($metrics[$endpoint]) > 100) {
$metrics[$endpoint] = array_slice($metrics[$endpoint], -100);
}
update_option('nb_api_metrics', $metrics);
}
🔧 Configuración Avanzada de API
Timeouts Personalizados
// Configuración de timeouts por endpoint
function nb_get_api_timeout($endpoint) {
$timeouts = array(
'/auth/login' => 5,
'/products' => 30,
'/products/check-stock' => 10
);
return $timeouts[$endpoint] ?? 15;
}
// Configuración de timeouts por endpoint
function nb_get_api_timeout($endpoint) {
$timeouts = array(
'/auth/login' => 5,
'/products' => 30,
'/products/check-stock' => 10
);
return $timeouts[$endpoint] ?? 15;
}
Retry Logic
function nb_api_request_with_retry($url, $args, $max_retries = 3) {
$retry_count = 0;
while ($retry_count < $max_retries) {
$response = wp_remote_request($url, $args);
if (!is_wp_error($response)) {
$response_code = wp_remote_retrieve_response_code($response);
if ($response_code < 500) {
return $response;
}
}
$retry_count++;
sleep(pow(2, $retry_count)); // Exponential backoff
}
return new WP_Error('max_retries_exceeded', 'Máximo número de reintentos excedido');
}
function nb_api_request_with_retry($url, $args, $max_retries = 3) {
$retry_count = 0;
while ($retry_count < $max_retries) {
$response = wp_remote_request($url, $args);
if (!is_wp_error($response)) {
$response_code = wp_remote_retrieve_response_code($response);
if ($response_code < 500) {
return $response;
}
}
$retry_count++;
sleep(pow(2, $retry_count)); // Exponential backoff
}
return new WP_Error('max_retries_exceeded', 'Máximo número de reintentos excedido');
}
Esta documentación de API proporciona una base sólida para desarrolladores que necesiten integrar, extender o depurar el Conector NewBytes.
💡 Para Desarrolladores
Usa los endpoints REST para crear integraciones personalizadas o dashboards externos que monitoreen el estado de sincronización.
⚠️ Límites de Rate
La API de NewBytes tiene límites de rate. Implementa lógica de retry y respeta los headers de rate limiting para evitar bloqueos temporales.