Skip to content

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:

http
Content-Type: application/json
Content-Type: application/json

Body:

json
{
  "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):

json
{
  "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):

json
{
  "error": "invalid_credentials",
  "message": "Usuario o contraseña incorrectos"
}
{
  "error": "invalid_credentials",
  "message": "Usuario o contraseña incorrectos"
}

Implementación en el Plugin:

php
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:

http
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):

json
{
  "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):

json
{
  "error": "unauthorized",
  "message": "Token inválido o expirado"
}
{
  "error": "unauthorized",
  "message": "Token inválido o expirado"
}

Implementación en el Plugin:

php
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:

http
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:

json
{
  "product_ids": ["12345", "12346", "12347"]
}
{
  "product_ids": ["12345", "12346", "12347"]
}

Respuesta:

json
{
  "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/v1URL 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:

json
{
  "sync_type": "manual",
  "force_update": false,
  "categories": ["electronics", "clothing"]
}
{
  "sync_type": "manual",
  "force_update": false,
  "categories": ["electronics", "clothing"]
}

Respuesta:

json
{
  "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:

php
// 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:

json
{
  "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:

json
{
  "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_syncMethod: POST URL: /wp-admin/admin-ajax.php

Data:

javascript
{
    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:

json
{
    "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:

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:

javascript
{
    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:

javascript
{
    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:

javascript
{
    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:

javascript
{
    action: 'nb_cleanup_logs',
    days: 30,
    type: 'all'
}
{
    action: 'nb_cleanup_logs',
    days: 30,
    type: 'all'
}

🛡️ Seguridad en APIs

Autenticación y Autorización

php
// 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

php
// 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

php
// 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

php
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

php
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

php
// 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

php
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.