By Devport Team | Last updated: 2025-07-12 | 21 min read

WooCommerce REST API: Complete Developer Guide

The WooCommerce REST API opens up endless possibilities for integrating your e-commerce store with external applications, building mobile apps, and creating headless commerce experiences. This comprehensive guide covers everything from basic authentication to advanced custom endpoints, helping you leverage the full power of WooCommerce's API ecosystem.

Whether you're building a mobile app, integrating with third-party services, or creating a custom frontend, understanding the WooCommerce REST API is essential. We'll explore practical examples, security best practices, and performance optimization techniques that transform how you interact with WooCommerce data.

Table of Contents

  1. REST API Fundamentals
  2. Authentication and Security
  3. Core API Endpoints
  4. Building Custom Endpoints
  5. Webhooks and Real-time Updates
  6. Performance and Best Practices

REST API Fundamentals

Setting Up REST API Access

// Enable and configure WooCommerce REST API
class WC_REST_API_Manager {

    /**
     * Initialize REST API configuration
     */
    public function __construct() {
        add_action('rest_api_init', [$this, 'register_routes']);
        add_filter('woocommerce_rest_check_permissions', [$this, 'check_permissions'], 10, 4);
        add_filter('woocommerce_rest_api_get_rest_namespaces', [$this, 'add_custom_namespace']);

        // Custom authentication
        add_filter('determine_current_user', [$this, 'authenticate_api_user'], 20);
        add_filter('rest_authentication_errors', [$this, 'check_authentication_error']);

        // Performance optimizations
        add_filter('woocommerce_rest_prepare_product_object', [$this, 'optimize_product_response'], 10, 3);
        add_filter('woocommerce_rest_product_object_query', [$this, 'optimize_product_query'], 10, 2);
    }

    /**
     * Generate API keys programmatically
     */
    public function generate_api_keys($user_id, $description = 'API Key', $permissions = 'read_write') {
        global $wpdb;

        // Generate keys
        $consumer_key = 'ck_' . wc_rand_hash();
        $consumer_secret = 'cs_' . wc_rand_hash();

        // Prepare data
        $data = [
            'user_id' => $user_id,
            'description' => $description,
            'permissions' => $permissions,
            'consumer_key' => wc_api_hash($consumer_key),
            'consumer_secret' => $consumer_secret,
            'truncated_key' => substr($consumer_key, -7),
        ];

        // Insert into database
        $wpdb->insert(
            $wpdb->prefix . 'woocommerce_api_keys',
            $data,
            [
                '%d',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
            ]
        );

        return [
            'consumer_key' => $consumer_key,
            'consumer_secret' => $consumer_secret,
            'key_id' => $wpdb->insert_id,
        ];
    }

    /**
     * Custom authentication handler
     */
    public function authenticate_api_user($user_id) {
        // Skip if already authenticated
        if ($user_id) {
            return $user_id;
        }

        // Check for custom authentication headers
        $auth_header = $this->get_authorization_header();

        if ($auth_header) {
            // Bearer token authentication
            if (preg_match('/Bearer\s+(\S+)/', $auth_header, $matches)) {
                return $this->authenticate_bearer_token($matches[1]);
            }

            // Basic authentication
            if (strpos($auth_header, 'Basic') === 0) {
                return $this->authenticate_basic_auth($auth_header);
            }
        }

        // OAuth 1.0a authentication
        if ($this->is_oauth_request()) {
            return $this->authenticate_oauth();
        }

        return $user_id;
    }

    /**
     * Get authorization header
     */
    private function get_authorization_header() {
        $authorization = '';

        if (function_exists('getallheaders')) {
            $headers = getallheaders();
            if (isset($headers['Authorization'])) {
                $authorization = $headers['Authorization'];
            }
        }

        // Fallback for nginx
        if (empty($authorization) && isset($_SERVER['HTTP_AUTHORIZATION'])) {
            $authorization = $_SERVER['HTTP_AUTHORIZATION'];
        }

        return $authorization;
    }

    /**
     * Rate limiting implementation
     */
    public function check_rate_limits($user_id) {
        $rate_limit_key = 'api_rate_limit_' . $user_id;
        $requests = get_transient($rate_limit_key);

        if (!$requests) {
            $requests = [];
        }

        // Clean old requests (older than 1 hour)
        $current_time = time();
        $requests = array_filter($requests, function($timestamp) use ($current_time) {
            return ($current_time - $timestamp) < HOUR_IN_SECONDS;
        });

        // Check limit (default: 100 requests per hour)
        $limit = apply_filters('woocommerce_api_rate_limit', 100, $user_id);

        if (count($requests) >= $limit) {
            return new WP_Error(
                'rate_limit_exceeded',
                'API rate limit exceeded',
                ['status' => 429]
            );
        }

        // Add current request
        $requests[] = $current_time;
        set_transient($rate_limit_key, $requests, HOUR_IN_SECONDS);

        return true;
    }
}

// Initialize API manager
new WC_REST_API_Manager();

API Client Implementation

// JavaScript API client for WooCommerce
class WooCommerceAPI {
    constructor(config) {
        this.url = config.url;
        this.consumerKey = config.consumerKey;
        this.consumerSecret = config.consumerSecret;
        this.version = config.version || 'wc/v3';
        this.encoding = config.encoding || 'utf8';
        this.queryStringAuth = config.queryStringAuth || false;
        this.port = config.port || '';
        this.timeout = config.timeout || 5000;
    }

    /**
     * Build complete URL
     */
    _getUrl(endpoint, params = {}) {
        const url = new URL(`${this.url}/wp-json/${this.version}/${endpoint}`);

        // Add query parameters
        Object.keys(params).forEach(key => {
            if (params[key] !== undefined) {
                url.searchParams.append(key, params[key]);
            }
        });

        // Add authentication to query string if needed
        if (this.queryStringAuth) {
            url.searchParams.append('consumer_key', this.consumerKey);
            url.searchParams.append('consumer_secret', this.consumerSecret);
        }

        return url.toString();
    }

    /**
     * Get authorization header
     */
    _getAuthHeader() {
        if (this.queryStringAuth) {
            return {};
        }

        const credentials = Buffer.from(`${this.consumerKey}:${this.consumerSecret}`).toString('base64');
        return {
            'Authorization': `Basic ${credentials}`
        };
    }

    /**
     * Make API request
     */
    async _request(method, endpoint, data = null, params = {}) {
        const url = this._getUrl(endpoint, params);
        const headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            ...this._getAuthHeader()
        };

        const options = {
            method,
            headers,
            timeout: this.timeout
        };

        if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
            options.body = JSON.stringify(data);
        }

        try {
            const response = await fetch(url, options);
            const responseData = await response.json();

            if (!response.ok) {
                throw new Error(responseData.message || 'API request failed');
            }

            // Include headers for pagination
            return {
                data: responseData,
                headers: {
                    total: response.headers.get('X-WP-Total'),
                    totalPages: response.headers.get('X-WP-TotalPages'),
                    link: response.headers.get('Link')
                }
            };

        } catch (error) {
            console.error('API Error:', error);
            throw error;
        }
    }

    // HTTP methods
    get(endpoint, params) {
        return this._request('GET', endpoint, null, params);
    }

    post(endpoint, data, params) {
        return this._request('POST', endpoint, data, params);
    }

    put(endpoint, data, params) {
        return this._request('PUT', endpoint, data, params);
    }

    delete(endpoint, params) {
        return this._request('DELETE', endpoint, null, params);
    }

    // Convenience methods
    async getProducts(params = {}) {
        return this.get('products', params);
    }

    async getProduct(id, params = {}) {
        return this.get(`products/${id}`, params);
    }

    async createProduct(data) {
        return this.post('products', data);
    }

    async updateProduct(id, data) {
        return this.put(`products/${id}`, data);
    }

    async deleteProduct(id, force = false) {
        return this.delete(`products/${id}`, { force });
    }

    // Batch operations
    async batch(endpoint, operations) {
        return this.post(`${endpoint}/batch`, operations);
    }
}

// Usage example
const api = new WooCommerceAPI({
    url: 'https://example.com',
    consumerKey: 'ck_xxx',
    consumerSecret: 'cs_xxx',
    version: 'wc/v3'
});

// Get products with pagination
api.getProducts({ per_page: 20, page: 1 })
    .then(response => {
        console.log('Products:', response.data);
        console.log('Total products:', response.headers.total);
    })
    .catch(error => console.error('Error:', error));

Authentication and Security

Advanced Authentication Methods

// JWT authentication for WooCommerce API
class WC_JWT_Authentication {

    private $secret_key;
    private $algorithm = 'HS256';
    private $token_expiry = 3600; // 1 hour

    public function __construct() {
        $this->secret_key = defined('JWT_AUTH_SECRET_KEY') 
            ? JWT_AUTH_SECRET_KEY 
            : wp_generate_password(64, true, true);

        // Authentication endpoints
        add_action('rest_api_init', [$this, 'register_auth_routes']);

        // Token validation
        add_filter('determine_current_user', [$this, 'validate_token'], 10);
        add_filter('rest_pre_dispatch', [$this, 'rest_pre_dispatch'], 10, 3);
    }

    /**
     * Register authentication routes
     */
    public function register_auth_routes() {
        register_rest_route('wc-auth/v1', '/token', [
            'methods' => 'POST',
            'callback' => [$this, 'generate_token'],
            'permission_callback' => '__return_true',
            'args' => [
                'username' => [
                    'required' => true,
                    'type' => 'string',
                ],
                'password' => [
                    'required' => true,
                    'type' => 'string',
                ],
            ],
        ]);

        register_rest_route('wc-auth/v1', '/token/validate', [
            'methods' => 'POST',
            'callback' => [$this, 'validate_token_endpoint'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route('wc-auth/v1', '/token/refresh', [
            'methods' => 'POST',
            'callback' => [$this, 'refresh_token'],
            'permission_callback' => [$this, 'require_valid_token'],
        ]);
    }

    /**
     * Generate JWT token
     */
    public function generate_token($request) {
        $username = $request->get_param('username');
        $password = $request->get_param('password');

        // Authenticate user
        $user = wp_authenticate($username, $password);

        if (is_wp_error($user)) {
            return new WP_Error(
                'invalid_credentials',
                'Invalid username or password',
                ['status' => 401]
            );
        }

        // Generate token payload
        $payload = [
            'iss' => get_bloginfo('url'),
            'iat' => time(),
            'exp' => time() + $this->token_expiry,
            'data' => [
                'user' => [
                    'id' => $user->ID,
                    'email' => $user->user_email,
                    'nicename' => $user->user_nicename,
                    'display_name' => $user->display_name,
                ],
            ],
        ];

        // Generate token
        $token = $this->encode_token($payload);

        // Generate refresh token
        $refresh_token = $this->generate_refresh_token($user->ID);

        return [
            'token' => $token,
            'refresh_token' => $refresh_token,
            'expires_in' => $this->token_expiry,
            'user' => [
                'id' => $user->ID,
                'email' => $user->user_email,
                'name' => $user->display_name,
            ],
        ];
    }

    /**
     * Validate JWT token
     */
    public function validate_token($user_id) {
        $token = $this->get_bearer_token();

        if (!$token) {
            return $user_id;
        }

        try {
            $payload = $this->decode_token($token);

            if ($payload && isset($payload->data->user->id)) {
                return $payload->data->user->id;
            }

        } catch (Exception $e) {
            return new WP_Error(
                'invalid_token',
                $e->getMessage(),
                ['status' => 401]
            );
        }

        return $user_id;
    }

    /**
     * Get bearer token from headers
     */
    private function get_bearer_token() {
        $auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

        if (preg_match('/Bearer\s+(\S+)/', $auth_header, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * Encode JWT token
     */
    private function encode_token($payload) {
        return JWT::encode($payload, $this->secret_key, $this->algorithm);
    }

    /**
     * Decode JWT token
     */
    private function decode_token($token) {
        return JWT::decode($token, $this->secret_key, [$this->algorithm]);
    }
}

// Initialize JWT authentication
new WC_JWT_Authentication();

API Security Best Practices

// API security implementation
class WC_API_Security {

    /**
     * Initialize security measures
     */
    public function __construct() {
        // Request validation
        add_filter('rest_pre_dispatch', [$this, 'validate_request'], 10, 3);

        // Response filtering
        add_filter('rest_pre_echo_response', [$this, 'filter_response'], 10, 3);

        // CORS handling
        add_action('rest_api_init', [$this, 'handle_cors'], 15);

        // IP whitelisting
        add_filter('rest_authentication_errors', [$this, 'check_ip_whitelist']);

        // Request logging
        add_action('rest_api_init', [$this, 'log_api_requests']);
    }

    /**
     * Validate incoming requests
     */
    public function validate_request($result, $server, $request) {
        // Check request method
        if (!$this->is_allowed_method($request->get_method())) {
            return new WP_Error(
                'method_not_allowed',
                'This method is not allowed',
                ['status' => 405]
            );
        }

        // Validate content type
        $content_type = $request->get_header('content-type');
        if ($content_type && !$this->is_valid_content_type($content_type)) {
            return new WP_Error(
                'invalid_content_type',
                'Invalid content type',
                ['status' => 415]
            );
        }

        // Check request size
        if ($this->is_request_too_large($request)) {
            return new WP_Error(
                'request_too_large',
                'Request entity too large',
                ['status' => 413]
            );
        }

        // Validate API version
        if (!$this->is_valid_api_version($request->get_route())) {
            return new WP_Error(
                'invalid_api_version',
                'This API version is not supported',
                ['status' => 400]
            );
        }

        return $result;
    }

    /**
     * Filter API responses
     */
    public function filter_response($response, $server, $request) {
        // Remove sensitive data
        if (is_array($response)) {
            $response = $this->remove_sensitive_data($response);
        }

        // Add security headers
        $server->send_header('X-Content-Type-Options', 'nosniff');
        $server->send_header('X-Frame-Options', 'DENY');
        $server->send_header('X-XSS-Protection', '1; mode=block');
        $server->send_header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');

        return $response;
    }

    /**
     * Handle CORS
     */
    public function handle_cors() {
        $origin = get_http_origin();
        $allowed_origins = $this->get_allowed_origins();

        if ($origin && in_array($origin, $allowed_origins, true)) {
            header('Access-Control-Allow-Origin: ' . esc_url_raw($origin));
            header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
            header('Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With');
            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Max-Age: 86400');
        }

        // Handle preflight requests
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            status_header(200);
            exit();
        }
    }

    /**
     * IP whitelisting
     */
    public function check_ip_whitelist($error) {
        // Skip if already has error
        if (is_wp_error($error)) {
            return $error;
        }

        // Get whitelisted IPs
        $whitelist = get_option('woocommerce_api_ip_whitelist', []);

        if (empty($whitelist)) {
            return $error;
        }

        $client_ip = $this->get_client_ip();

        if (!in_array($client_ip, $whitelist, true)) {
            return new WP_Error(
                'forbidden',
                'Your IP address is not whitelisted',
                ['status' => 403]
            );
        }

        return $error;
    }

    /**
     * Get client IP address
     */
    private function get_client_ip() {
        $ip_keys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];

        foreach ($ip_keys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    $ip = trim($ip);

                    if (filter_var(
                        $ip,
                        FILTER_VALIDATE_IP,
                        FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
                    ) !== false) {
                        return $ip;
                    }
                }
            }
        }

        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }
}

// Initialize security
new WC_API_Security();

Core API Endpoints

Product Management Endpoints

// Enhanced product endpoints
class WC_Product_API_Extensions {

    public function __construct() {
        add_action('rest_api_init', [$this, 'register_routes']);
        add_filter('woocommerce_rest_prepare_product_object', [$this, 'add_custom_fields'], 10, 3);
        add_filter('woocommerce_rest_product_object_query', [$this, 'add_custom_query_params'], 10, 2);
    }

    /**
     * Register custom product routes
     */
    public function register_routes() {
        // Bulk operations
        register_rest_route('wc/v3', '/products/bulk', [
            'methods' => 'POST',
            'callback' => [$this, 'bulk_update_products'],
            'permission_callback' => [$this, 'check_permissions'],
            'args' => [
                'create' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                    ],
                ],
                'update' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                    ],
                ],
                'delete' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'integer',
                    ],
                ],
            ],
        ]);

        // Advanced search
        register_rest_route('wc/v3', '/products/search', [
            'methods' => 'GET',
            'callback' => [$this, 'advanced_product_search'],
            'permission_callback' => [$this, 'check_permissions'],
            'args' => [
                'query' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                ],
                'type' => [
                    'type' => 'string',
                    'enum' => ['simple', 'variable', 'grouped', 'external'],
                ],
                'price_range' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'number',
                    ],
                ],
                'in_stock' => [
                    'type' => 'boolean',
                ],
            ],
        ]);

        // Product analytics
        register_rest_route('wc/v3', '/products/(?P<id>[\d]+)/analytics', [
            'methods' => 'GET',
            'callback' => [$this, 'get_product_analytics'],
            'permission_callback' => [$this, 'check_permissions'],
            'args' => [
                'id' => [
                    'validate_callback' => function($param) {
                        return is_numeric($param);
                    },
                ],
                'period' => [
                    'type' => 'string',
                    'default' => 'last_30_days',
                    'enum' => ['last_7_days', 'last_30_days', 'last_90_days', 'last_year'],
                ],
            ],
        ]);
    }

    /**
     * Bulk update products
     */
    public function bulk_update_products($request) {
        $results = [
            'created' => [],
            'updated' => [],
            'deleted' => [],
            'errors' => [],
        ];

        // Handle creates
        if (!empty($request['create'])) {
            foreach ($request['create'] as $product_data) {
                try {
                    $product = $this->create_product($product_data);
                    $results['created'][] = $product->get_id();
                } catch (Exception $e) {
                    $results['errors'][] = [
                        'operation' => 'create',
                        'data' => $product_data,
                        'error' => $e->getMessage(),
                    ];
                }
            }
        }

        // Handle updates
        if (!empty($request['update'])) {
            foreach ($request['update'] as $product_data) {
                try {
                    if (empty($product_data['id'])) {
                        throw new Exception('Product ID is required for update');
                    }

                    $product = $this->update_product($product_data['id'], $product_data);
                    $results['updated'][] = $product->get_id();
                } catch (Exception $e) {
                    $results['errors'][] = [
                        'operation' => 'update',
                        'data' => $product_data,
                        'error' => $e->getMessage(),
                    ];
                }
            }
        }

        // Handle deletes
        if (!empty($request['delete'])) {
            foreach ($request['delete'] as $product_id) {
                try {
                    $product = wc_get_product($product_id);
                    if (!$product) {
                        throw new Exception('Product not found');
                    }

                    $product->delete(true);
                    $results['deleted'][] = $product_id;
                } catch (Exception $e) {
                    $results['errors'][] = [
                        'operation' => 'delete',
                        'id' => $product_id,
                        'error' => $e->getMessage(),
                    ];
                }
            }
        }

        return rest_ensure_response($results);
    }

    /**
     * Advanced product search
     */
    public function advanced_product_search($request) {
        $args = [
            'post_type' => 'product',
            'post_status' => 'publish',
            's' => $request['query'],
            'posts_per_page' => 20,
        ];

        // Filter by product type
        if (!empty($request['type'])) {
            $args['tax_query'][] = [
                'taxonomy' => 'product_type',
                'field' => 'slug',
                'terms' => $request['type'],
            ];
        }

        // Filter by price range
        if (!empty($request['price_range']) && count($request['price_range']) === 2) {
            $args['meta_query'][] = [
                'key' => '_price',
                'value' => $request['price_range'],
                'compare' => 'BETWEEN',
                'type' => 'NUMERIC',
            ];
        }

        // Filter by stock status
        if (isset($request['in_stock'])) {
            $args['meta_query'][] = [
                'key' => '_stock_status',
                'value' => $request['in_stock'] ? 'instock' : 'outofstock',
            ];
        }

        // Execute search
        $query = new WP_Query($args);
        $products = [];

        foreach ($query->posts as $post) {
            $product = wc_get_product($post->ID);
            $products[] = $this->prepare_product_response($product);
        }

        return rest_ensure_response([
            'products' => $products,
            'total' => $query->found_posts,
            'pages' => $query->max_num_pages,
        ]);
    }
}

// Initialize extensions
new WC_Product_API_Extensions();

Building Custom Endpoints

Creating Custom REST Controllers

// Custom REST controller for advanced features
class WC_REST_Custom_Controller extends WC_REST_Controller {

    protected $namespace = 'wc/v3';
    protected $rest_base = 'custom';

    /**
     * Register routes
     */
    public function register_routes() {
        // Collection endpoints
        register_rest_route($this->namespace, '/' . $this->rest_base, [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => [$this, 'get_items'],
                'permission_callback' => [$this, 'get_items_permissions_check'],
                'args' => $this->get_collection_params(),
            ],
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'create_item'],
                'permission_callback' => [$this, 'create_item_permissions_check'],
                'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
            ],
        ]);

        // Single item endpoints
        register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => [$this, 'get_item'],
                'permission_callback' => [$this, 'get_item_permissions_check'],
                'args' => [
                    'context' => $this->get_context_param(['default' => 'view']),
                ],
            ],
            [
                'methods' => WP_REST_Server::EDITABLE,
                'callback' => [$this, 'update_item'],
                'permission_callback' => [$this, 'update_item_permissions_check'],
                'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE),
            ],
            [
                'methods' => WP_REST_Server::DELETABLE,
                'callback' => [$this, 'delete_item'],
                'permission_callback' => [$this, 'delete_item_permissions_check'],
                'args' => [
                    'force' => [
                        'default' => false,
                        'type' => 'boolean',
                        'description' => 'Whether to bypass trash and force deletion.',
                    ],
                ],
            ],
        ]);

        // Custom action endpoints
        register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)/action', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'perform_action'],
            'permission_callback' => [$this, 'perform_action_permissions_check'],
            'args' => [
                'action' => [
                    'required' => true,
                    'type' => 'string',
                    'enum' => ['process', 'cancel', 'refund'],
                ],
                'reason' => [
                    'type' => 'string',
                    'description' => 'Reason for the action',
                ],
            ],
        ]);
    }

    /**
     * Get collection of items
     */
    public function get_items($request) {
        $query_args = $this->prepare_items_query($request);
        $query = new WP_Query($query_args);

        $items = [];
        foreach ($query->posts as $post) {
            $data = $this->prepare_item_for_response($post, $request);
            $items[] = $this->prepare_response_for_collection($data);
        }

        $response = rest_ensure_response($items);

        // Add pagination headers
        $total_items = $query->found_posts;
        $max_pages = $query->max_num_pages;

        $response->header('X-WP-Total', $total_items);
        $response->header('X-WP-TotalPages', $max_pages);

        return $response;
    }

    /**
     * Prepare query arguments
     */
    protected function prepare_items_query($request) {
        $args = [
            'post_type' => 'custom_post_type',
            'posts_per_page' => $request['per_page'],
            'paged' => $request['page'],
            'orderby' => $request['orderby'],
            'order' => $request['order'],
        ];

        // Search
        if (!empty($request['search'])) {
            $args['s'] = $request['search'];
        }

        // Status filter
        if (!empty($request['status'])) {
            $args['post_status'] = $request['status'];
        }

        // Date filters
        if (!empty($request['after'])) {
            $args['date_query'][] = [
                'after' => $request['after'],
                'inclusive' => true,
            ];
        }

        if (!empty($request['before'])) {
            $args['date_query'][] = [
                'before' => $request['before'],
                'inclusive' => true,
            ];
        }

        // Custom filters
        return apply_filters('woocommerce_rest_custom_query', $args, $request);
    }

    /**
     * Get schema
     */
    public function get_item_schema() {
        $schema = [
            '$schema' => 'http://json-schema.org/draft-04/schema#',
            'title' => 'custom',
            'type' => 'object',
            'properties' => [
                'id' => [
                    'description' => 'Unique identifier for the object.',
                    'type' => 'integer',
                    'context' => ['view', 'edit'],
                    'readonly' => true,
                ],
                'name' => [
                    'description' => 'Name of the object.',
                    'type' => 'string',
                    'context' => ['view', 'edit'],
                    'required' => true,
                ],
                'status' => [
                    'description' => 'Status of the object.',
                    'type' => 'string',
                    'enum' => ['active', 'inactive', 'pending'],
                    'context' => ['view', 'edit'],
                ],
                'meta_data' => [
                    'description' => 'Meta data.',
                    'type' => 'array',
                    'context' => ['view', 'edit'],
                    'items' => [
                        'type' => 'object',
                        'properties' => [
                            'key' => [
                                'type' => 'string',
                            ],
                            'value' => [
                                'type' => ['string', 'number', 'boolean', 'array', 'object'],
                            ],
                        ],
                    ],
                ],
            ],
        ];

        return $this->add_additional_fields_schema($schema);
    }
}

Webhooks and Real-time Updates

Webhook Management System

// Advanced webhook implementation
class WC_Webhook_Manager {

    private $webhook_events = [
        'product.created',
        'product.updated',
        'product.deleted',
        'order.created',
        'order.updated',
        'order.status_changed',
        'customer.created',
        'customer.updated',
        'inventory.updated',
    ];

    public function __construct() {
        // Register webhook handlers
        foreach ($this->webhook_events as $event) {
            $hook = str_replace('.', '_', $event);
            add_action('woocommerce_' . $hook, [$this, 'trigger_webhook'], 10, 2);
        }

        // Custom webhook endpoints
        add_action('rest_api_init', [$this, 'register_webhook_endpoints']);

        // Webhook delivery system
        add_action('woocommerce_deliver_webhook_async', [$this, 'deliver_webhook_async'], 10, 2);
    }

    /**
     * Register webhook management endpoints
     */
    public function register_webhook_endpoints() {
        // Create webhook
        register_rest_route('wc/v3', '/webhooks/subscribe', [
            'methods' => 'POST',
            'callback' => [$this, 'create_webhook_subscription'],
            'permission_callback' => [$this, 'check_admin_permissions'],
            'args' => [
                'url' => [
                    'required' => true,
                    'type' => 'string',
                    'format' => 'uri',
                ],
                'events' => [
                    'required' => true,
                    'type' => 'array',
                    'items' => [
                        'type' => 'string',
                        'enum' => $this->webhook_events,
                    ],
                ],
                'secret' => [
                    'type' => 'string',
                    'description' => 'Secret key for webhook signature',
                ],
            ],
        ]);

        // List webhooks
        register_rest_route('wc/v3', '/webhooks/subscriptions', [
            'methods' => 'GET',
            'callback' => [$this, 'list_webhook_subscriptions'],
            'permission_callback' => [$this, 'check_admin_permissions'],
        ]);

        // Test webhook
        register_rest_route('wc/v3', '/webhooks/test', [
            'methods' => 'POST',
            'callback' => [$this, 'test_webhook'],
            'permission_callback' => [$this, 'check_admin_permissions'],
            'args' => [
                'webhook_id' => [
                    'required' => true,
                    'type' => 'integer',
                ],
            ],
        ]);
    }

    /**
     * Create webhook subscription
     */
    public function create_webhook_subscription($request) {
        $url = $request['url'];
        $events = $request['events'];
        $secret = $request['secret'] ?? wp_generate_password(32, true, true);

        // Validate URL
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            return new WP_Error('invalid_url', 'Invalid webhook URL');
        }

        // Create webhook
        $webhook = new WC_Webhook();
        $webhook->set_name('Custom Webhook - ' . parse_url($url, PHP_URL_HOST));
        $webhook->set_status('active');
        $webhook->set_delivery_url($url);
        $webhook->set_secret($secret);
        $webhook->set_topic('action.woocommerce_webhook_custom');
        $webhook->set_api_version('wp_api_v3');

        // Store events in meta
        $webhook->add_meta_data('subscribed_events', $events);
        $webhook->save();

        return [
            'id' => $webhook->get_id(),
            'url' => $url,
            'events' => $events,
            'secret' => $secret,
            'status' => 'active',
        ];
    }

    /**
     * Deliver webhook with retry logic
     */
    public function deliver_webhook_async($webhook_id, $arg) {
        $webhook = new WC_Webhook($webhook_id);

        if (!$webhook->get_id()) {
            return;
        }

        $payload = $this->build_payload($webhook, $arg);
        $response = $this->send_webhook_request($webhook, $payload);

        // Log delivery
        $this->log_webhook_delivery($webhook, $payload, $response);

        // Handle failed delivery
        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) >= 400) {
            $this->handle_failed_delivery($webhook, $response);
        }
    }

    /**
     * Build webhook payload
     */
    private function build_payload($webhook, $arg) {
        $payload = [
            'id' => uniqid('evt_'),
            'created' => time(),
            'type' => $arg['event'],
            'api_version' => 'wc/v3',
            'data' => $arg['data'],
        ];

        // Add signature
        $signature = $this->generate_signature($webhook->get_secret(), $payload);

        return [
            'body' => json_encode($payload),
            'headers' => [
                'Content-Type' => 'application/json',
                'X-WC-Webhook-Signature' => $signature,
                'X-WC-Webhook-ID' => $webhook->get_id(),
                'X-WC-Webhook-Event' => $arg['event'],
            ],
        ];
    }

    /**
     * Generate webhook signature
     */
    private function generate_signature($secret, $payload) {
        return base64_encode(hash_hmac('sha256', json_encode($payload), $secret, true));
    }
}

// Initialize webhook manager
new WC_Webhook_Manager();

Performance and Best Practices

API Performance Optimization

// Performance optimization for REST API
class WC_REST_Performance_Optimizer {

    public function __construct() {
        // Response caching
        add_filter('rest_pre_echo_response', [$this, 'maybe_serve_from_cache'], 10, 3);
        add_filter('rest_post_dispatch', [$this, 'maybe_cache_response'], 10, 3);

        // Query optimization
        add_filter('woocommerce_rest_product_object_query', [$this, 'optimize_queries'], 10, 2);

        // Field filtering
        add_filter('rest_pre_echo_response', [$this, 'filter_response_fields'], 15, 3);

        // Batch processing
        add_action('rest_api_init', [$this, 'register_batch_endpoint']);
    }

    /**
     * Cache API responses
     */
    public function maybe_cache_response($response, $server, $request) {
        // Only cache GET requests
        if ($request->get_method() !== 'GET') {
            return $response;
        }

        // Check if cacheable
        if (!$this->is_cacheable_request($request)) {
            return $response;
        }

        $cache_key = $this->get_cache_key($request);
        $cache_time = $this->get_cache_time($request->get_route());

        if ($cache_time > 0) {
            set_transient($cache_key, [
                'response' => $response->get_data(),
                'headers' => $response->get_headers(),
            ], $cache_time);
        }

        return $response;
    }

    /**
     * Serve cached responses
     */
    public function maybe_serve_from_cache($result, $server, $request) {
        if ($request->get_method() !== 'GET') {
            return $result;
        }

        $cache_key = $this->get_cache_key($request);
        $cached = get_transient($cache_key);

        if ($cached !== false) {
            $response = rest_ensure_response($cached['response']);

            // Add cache headers
            $response->header('X-WP-Cached', 'true');
            $response->header('X-WP-Cache-Key', $cache_key);

            // Restore original headers
            foreach ($cached['headers'] as $key => $value) {
                $response->header($key, $value);
            }

            return $response;
        }

        return $result;
    }

    /**
     * Optimize database queries
     */
    public function optimize_queries($args, $request) {
        // Only select needed fields
        if (isset($request['_fields'])) {
            $fields = explode(',', $request['_fields']);
            $args['fields'] = $this->map_fields_to_query($fields);
        }

        // Optimize meta queries
        if (!empty($args['meta_query'])) {
            $args['meta_query'] = $this->optimize_meta_queries($args['meta_query']);
        }

        // Add query hints
        $args['no_found_rows'] = true;
        $args['update_post_meta_cache'] = false;
        $args['update_post_term_cache'] = false;

        return $args;
    }

    /**
     * Register batch processing endpoint
     */
    public function register_batch_endpoint() {
        register_rest_route('wc/v3', '/batch', [
            'methods' => 'POST',
            'callback' => [$this, 'process_batch_request'],
            'permission_callback' => [$this, 'check_batch_permissions'],
            'args' => [
                'requests' => [
                    'required' => true,
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                        'properties' => [
                            'method' => [
                                'type' => 'string',
                                'enum' => ['GET', 'POST', 'PUT', 'DELETE'],
                            ],
                            'path' => [
                                'type' => 'string',
                            ],
                            'body' => [
                                'type' => ['object', 'array'],
                            ],
                        ],
                    ],
                ],
            ],
        ]);
    }

    /**
     * Process batch requests
     */
    public function process_batch_request($request) {
        $requests = $request['requests'];
        $responses = [];

        foreach ($requests as $index => $subrequest) {
            $method = $subrequest['method'] ?? 'GET';
            $path = $subrequest['path'] ?? '';
            $body = $subrequest['body'] ?? null;

            // Create sub-request
            $sub = new WP_REST_Request($method, $path);

            if ($body) {
                $sub->set_body_params($body);
            }

            // Process sub-request
            $response = rest_do_request($sub);

            $responses[] = [
                'status' => $response->get_status(),
                'headers' => $response->get_headers(),
                'body' => $response->get_data(),
            ];
        }

        return [
            'responses' => $responses,
        ];
    }
}

// Initialize optimizer
new WC_REST_Performance_Optimizer();

The WooCommerce REST API provides a powerful foundation for extending your e-commerce capabilities. By mastering authentication, custom endpoints, and performance optimization, you can build robust integrations that scale with your business needs.