Skip to content

API Endpoints

The Elasticsearch integration provides structured data access through AJAX endpoints, REST-like interfaces, and direct class methods. While not a traditional REST API, the system offers comprehensive programmatic access to all functionality.

All AJAX operations are handled through WordPress hooks in functions.php:

EndpointFunctionPurposeAccess
get_elasticsearch_statsGet sync statisticsReal-time monitoringAdmin only
get_elasticsearch_logFetch log contentLog viewingAdmin only
test_elasticsearch_connectionTest ES connectionHealth monitoringAdmin only
reset_elasticsearch_syncReset sync processEmergency resetAdmin only
run_manual_elasticsearch_syncTrigger syncManual syncAdmin only
search_productsProduct searchPublic searchPublic
load_category_childrenLoad child categoriesCategory treePublic
search_categoriesSearch categoriesCategory searchPublic
// Admin-only endpoints
add_action('wp_ajax_get_elasticsearch_stats', 'ajax_get_elasticsearch_stats');
add_action('wp_ajax_get_elasticsearch_log', 'ajax_get_elasticsearch_log');
add_action('wp_ajax_test_elasticsearch_connection', 'ajax_test_elasticsearch_connection');
add_action('wp_ajax_reset_elasticsearch_sync', 'ajax_reset_elasticsearch_sync');
add_action('wp_ajax_run_manual_elasticsearch_sync', 'ajax_run_manual_elasticsearch_sync');
// Public endpoints
add_action('wp_ajax_nopriv_search_products', 'ajax_search_products');
add_action('wp_ajax_nopriv_load_category_children', 'ajax_load_category_children');
add_action('wp_ajax_nopriv_search_categories', 'ajax_search_categories');

Endpoint: get_elasticsearch_stats
Access: Admin only
Purpose: Retrieve real-time sync statistics and performance metrics

jQuery.post(ajaxurl, {
action: 'get_elasticsearch_stats',
nonce: ajax_nonce
}, function(response) {
console.log(response);
});
{
"success": true,
"data": {
"stats": {
"phase": "bulk_syncing",
"total_products": 60560,
"indexed_products": 15000,
"elasticsearch_count": 15000,
"progress_percentage": 24.7,
"started_at": "2025-09-28T15:14:03+00:00",
"last_run": "2025-09-28T16:22:53+00:00",
"errors": 2,
"failed_batches": 1,
"consecutive_failures": 0
},
"performance": {
"remaining_products": 45560,
"remaining_batches": 91,
"scheduled_eta_hours": 22.8,
"adaptive_eta_hours": 18.5,
"calculation_method": "adaptive",
"products_per_hour": 2462,
"confidence_level": "high"
},
"alerts": [
{
"type": "warning",
"message": "Sync hasn't run in 2.5 hours",
"timestamp": "2025-09-28T16:25:00+00:00"
}
]
}
}

Endpoint: search_products
Access: Public
Purpose: Perform product search with filters and pagination

jQuery.post(ajaxurl, {
action: 'search_products',
nonce: search_nonce,
query: 'smartphone',
category: '123',
min_price: 100,
max_price: 500,
brand: ['Samsung', 'Apple'],
availability: 'In Stock',
page: 1,
per_page: 20,
sort: 'price_asc'
}, function(response) {
console.log(response);
});
{
"success": true,
"data": {
"hits": [
{
"id": "12345",
"source": {
"id": 12345,
"title": "Samsung Galaxy S21",
"brand": "Samsung",
"price": 299.99,
"list_price": 399.99,
"discount_percentage": 25.0,
"availability": "In Stock",
"category": "Smartphones",
"sku": "SAM-S21-128",
"image_url": "https://example.com/image.jpg",
"product_url": "https://example.com/product/12345"
},
"score": 15.2,
"highlight": {
"title": ["Samsung Galaxy <mark>S21</mark>"],
"description": ["Latest <mark>smartphone</mark> from Samsung"]
}
}
],
"total": 1250,
"page": 1,
"per_page": 20,
"total_pages": 63,
"aggregations": {
"categories": [
{"key": "Smartphones", "doc_count": 450},
{"key": "Accessories", "doc_count": 200}
],
"brands": [
{"key": "Samsung", "doc_count": 300},
{"key": "Apple", "doc_count": 250}
],
"price_ranges": [
{"key": "100-250", "doc_count": 400},
{"key": "250-500", "doc_count": 350}
]
}
}
}

Endpoint: get_elasticsearch_log
Access: Admin only
Purpose: Retrieve log file content for monitoring and debugging

jQuery.post(ajaxurl, {
action: 'get_elasticsearch_log',
nonce: ajax_nonce,
log_type: 'auto_sync',
lines: 100
}, function(response) {
console.log(response);
});
{
"success": true,
"data": {
"content": "[2025-09-28 16:22:53] INFO: Starting bulk sync phase\n[2025-09-28 16:22:54] INFO: Processing batch of 500 products\n[2025-09-28 16:23:15] ERROR: Elasticsearch connection timeout\n[2025-09-28 16:23:16] WARNING: Retrying batch after connection error",
"file": "elasticsearch-auto-sync.log",
"size": 1048576,
"modified": "2025-09-28 16:23:16",
"lines": 100
}
}

Endpoint: test_elasticsearch_connection
Access: Admin only
Purpose: Test Elasticsearch connectivity and health

jQuery.post(ajaxurl, {
action: 'test_elasticsearch_connection',
nonce: ajax_nonce
}, function(response) {
console.log(response);
});
{
"success": true,
"data": {
"status": "success",
"message": "Elasticsearch connection successful",
"document_count": 15000,
"index_size": "2.1GB",
"health": "green"
}
}

Endpoint: reset_elasticsearch_sync
Access: Admin only
Purpose: Emergency reset of sync process

jQuery.post(ajaxurl, {
action: 'reset_elasticsearch_sync',
nonce: ajax_nonce
}, function(response) {
console.log(response);
});
{
"success": true,
"data": {
"status": "success",
"message": "Sync process reset successfully"
}
}
$elasticsearch = new ProductElasticsearch();
// Search products
$results = $elasticsearch->searchProducts($query, $filters, $page, $per_page, $sort);
// Get document count
$count = $elasticsearch->getDocumentCount();
// Test connection
$is_available = $elasticsearch->isAvailable();
// Get index statistics
$stats = $elasticsearch->getIndexStats();
// Bulk index products
$success = $elasticsearch->bulkIndexProducts($products);
$console_manager = new ElasticsearchConsoleManager();
// Get statistics
$stats = $console_manager->getStats();
// Get performance estimates
$performance = $console_manager->getPerformanceEstimates();
// Get log content
$logs = $console_manager->getLogContent('auto_sync', 100);
// Test connection
$connection_test = $console_manager->testConnection();
// Reset sync
$reset_result = $console_manager->resetSync();
$sync_manager = new ElasticsearchAutoSyncManager();
// Run sync
$sync_manager->autoSync();
// Get sync state
$state = $sync_manager->getSyncState();
// Show statistics
$sync_manager->showStats();
// Reset sync
$sync_manager->resetSync();
// Search with complex filters
$filters = [
'category' => '123',
'min_price' => 100,
'max_price' => 500,
'brand' => ['Samsung', 'Apple'],
'availability' => 'In Stock',
'date_range' => [
'from' => '2025-01-01',
'to' => '2025-12-31'
]
];
$results = $elasticsearch->searchProducts(
$query = 'smartphone',
$filters = $filters,
$page = 1,
$per_page = 20,
$sort = ['price' => 'asc', 'title' => 'desc']
);
// Complete search response
$response = [
'hits' => [
[
'id' => '12345',
'source' => [
'id' => 12345,
'title' => 'Product Title',
'brand' => 'Brand Name',
'price' => 299.99,
'category' => 'Category Name',
// ... other fields
],
'score' => 15.2,
'highlight' => [
'title' => ['Highlighted <mark>text</mark>'],
'description' => ['More <mark>highlighted</mark> text']
]
]
],
'total' => 1250,
'page' => 1,
'per_page' => 20,
'total_pages' => 63,
'aggregations' => [
'categories' => [
['key' => 'Category 1', 'doc_count' => 450],
['key' => 'Category 2', 'doc_count' => 200]
],
'brands' => [
['key' => 'Brand 1', 'doc_count' => 300],
['key' => 'Brand 2', 'doc_count' => 250]
],
'price_stats' => [
'min' => 10.0,
'max' => 999.99,
'avg' => 245.50,
'count' => 1250
]
]
];
{
"success": false,
"data": "Error message describing what went wrong"
}
{
"success": false,
"data": "Elasticsearch connection failed: Connection timeout"
}
{
"success": false,
"data": "Insufficient permissions"
}
{
"success": false,
"data": "Invalid search parameters"
}
{
"success": false,
"data": "Search temporarily unavailable"
}

All AJAX requests require nonce verification:

// Verify nonce
check_ajax_referer('elasticsearch_nonce', 'nonce');
// Admin-only endpoints
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
}
// Public endpoints (no additional checks needed)
// Search is public, no login required
// Sanitize all inputs
$query = sanitize_text_field($_POST['query']);
$category = sanitize_text_field($_POST['category']);
$min_price = floatval($_POST['min_price']);
$max_price = floatval($_POST['max_price']);
$page = intval($_POST['page']);
$per_page = intval($_POST['per_page']);
// Cache search results
$cache_key = 'search_' . md5(serialize([$query, $filters, $page, $per_page]));
$cached = wp_cache_get($cache_key, 'elasticsearch');
if ($cached === false) {
$cached = $elasticsearch->searchProducts($query, $filters, $page, $per_page);
wp_cache_set($cache_key, $cached, 'elasticsearch', 300); // 5 min cache
}
// Implement rate limiting for public endpoints
$rate_limit_key = 'rate_limit_' . $_SERVER['REMOTE_ADDR'];
$requests = wp_cache_get($rate_limit_key, 'elasticsearch_rate_limit');
if ($requests && $requests > 100) { // 100 requests per hour
wp_send_json_error('Rate limit exceeded');
}
wp_cache_set($rate_limit_key, ($requests ?? 0) + 1, 'elasticsearch_rate_limit', 3600);
class ElasticsearchAPI {
constructor() {
this.ajaxUrl = ajaxurl;
this.nonce = ajax_nonce;
}
async searchProducts(params) {
const response = await fetch(this.ajaxUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'search_products',
nonce: this.nonce,
...params
})
});
return response.json();
}
async getStats() {
const response = await fetch(this.ajaxUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'get_elasticsearch_stats',
nonce: this.nonce
})
});
return response.json();
}
}
// Usage
const api = new ElasticsearchAPI();
// Search products
api.searchProducts({
query: 'smartphone',
category: '123',
page: 1
}).then(response => {
if (response.success) {
console.log('Search results:', response.data);
} else {
console.error('Search failed:', response.data);
}
});
// Get statistics
api.getStats().then(response => {
if (response.success) {
console.log('Stats:', response.data);
}
});
// Direct class usage
$elasticsearch = new ProductElasticsearch();
// Search products
$results = $elasticsearch->searchProducts('smartphone', [
'category' => '123',
'min_price' => 100,
'max_price' => 500
], 1, 20);
// Process results
foreach ($results['hits'] as $hit) {
$product = $hit['source'];
$score = $hit['score'];
$highlight = $hit['highlight'];
echo "Product: {$product['title']} (Score: {$score})\n";
if (isset($highlight['title'])) {
echo "Highlighted: {$highlight['title'][0]}\n";
}
}