Data API Documentation
Connect your website's product catalog, services, orders, and customer accounts to the Vexar.Chat AI chatbot.
Contents
1. Overview
Data API allows the Vexar.Chat AI chatbot to query your website's data in real time. When a visitor asks about products, services, stock availability, order status, or account information, the chatbot calls your API endpoint and uses the response to provide accurate, up-to-date answers.
- Visitor asks: "Do you have red sneakers under $50?"
- AI decides to call
search_productswith{"query": "red sneakers", "max_price": 50} - Your API endpoint receives the request and returns matching products from your database
- AI formats the results into a natural language response for the visitor
2. Quick Start
- Create a single API endpoint on your website (e.g.,
https://your-site.com/vexar-api/) - The endpoint should accept POST requests with JSON body
- Implement handlers for the actions your chatbot needs (at minimum:
ping) - In Vexar.Chat dashboard → Chatbot Settings → Data API: enable, enter your URL and API key
- Click "Test connection" to verify everything works
3. Request Format
The chatbot sends a POST request to your URL with the following JSON body:
{
"action": "search_products",
"params": {
"query": "red sneakers",
"max_price": 50,
"in_stock": true
}
}
Headers:
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer YOUR_API_KEY |
User-Agent | VexarChat-DataAPI/1.0 |
4. Response Format
Successful response:
{
"success": true,
"data": [
{
"id": 123,
"name": "Nike Air Max Red",
"price": 45.99,
"currency": "USD",
"url": "https://your-site.com/product/nike-air-max-red",
"in_stock": true,
"image": "https://your-site.com/images/nike-air-max-red.jpg"
}
]
}
Error response:
{
"success": false,
"error": "Product not found"
}
5. Actions Reference
ping
Health check. Used by "Test connection" button in dashboard.
| Params | Response |
|---|---|
| None | {"success": true, "data": {"status": "ok"}} |
search_products
Search for products or services by keyword, category, price range, and availability.
| Param | Type | Required | Description |
|---|---|---|---|
query | string | No | Search keywords |
category | string | No | Category name or ID |
min_price | number | No | Minimum price |
max_price | number | No | Maximum price |
in_stock | boolean | No | Only in-stock items |
limit | integer | No | Max results (default 5, max 10) |
Expected response data: array of products, each with: id, name, price, currency, url, in_stock, image (optional), description (optional)
get_product
Get detailed information about a specific product or service by its ID.
| Param | Type | Required | Description |
|---|---|---|---|
product_id | string | Yes | Product or service ID |
Expected response data: single product object with all details: id, name, price, currency, url, in_stock, description, specifications, images
get_categories
Get the list of available categories.
| Params | Response |
|---|---|
| None | Array of {"id", "name", "count"} |
check_availability
Check stock availability or service booking slots.
| Param | Type | Required | Description |
|---|---|---|---|
product_id | string | Yes | Product or service ID |
Expected response: {"in_stock": true, "quantity": 15} or for services: {"available": true, "next_slot": "2026-03-15 10:00"}
check_order_status
Check order status by order ID or customer email.
| Param | Type | Required | Description |
|---|---|---|---|
order_id | string | No* | Order number |
email | string | No* | Customer email |
* At least one of order_id or email is required.
Expected response data: {"order_id", "status", "created_at", "total", "items": [...]}
lookup_account
Look up customer account or subscription information by account ID, phone, email, or contract number. Ideal for ISPs, telecom, utilities, SaaS, and any service with subscriber accounts.
| Param | Type | Required | Description |
|---|---|---|---|
account_id | string | No* | Account / subscriber ID |
phone | string | No* | Customer phone number |
email | string | No* | Customer email |
contract_number | string | No* | Contract / agreement number |
* At least one identifier should be provided. The response data structure is flexible — return any fields relevant to your business.
The AI will interpret any fields you return (balance, plan name, expiration date, usage stats, etc.) and present them naturally to the visitor.
Example response:
{
"success": true,
"data": {
"account_id": "ACC-1001",
"name": "John Smith",
"tariff": "Pro 100 Mbps",
"status": "active",
"balance": 15.50,
"currency": "USD",
"next_billing": "2026-04-01",
"expires_at": "2027-03-15"
}
}
6. Code Examples
PHP (Universal)
<?php // File: vexar-api/index.php // This is a minimal example. Adapt the database queries to your CMS. header('Content-Type: application/json'); // Verify API key $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; $apiKey = str_replace('Bearer ', '', $authHeader); if ($apiKey !== 'YOUR_SECRET_KEY') { http_response_code(401); echo json_encode(['success' => false, 'error' => 'Unauthorized']); exit; } // Parse request $input = json_decode(file_get_contents('php://input'), true); $action = $input['action'] ?? ''; $params = $input['params'] ?? []; // Connect to your database $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); switch ($action) { case 'ping': echo json_encode(['success' => true, 'data' => ['status' => 'ok']]); break; case 'search_products': $query = $params['query'] ?? ''; $maxPrice = $params['max_price'] ?? 999999; $limit = min(10, $params['limit'] ?? 5); $stmt = $pdo->prepare( "SELECT id, name, price, 'USD' as currency, url, (stock > 0) as in_stock FROM products WHERE name LIKE :q AND price <= :mp ORDER BY name LIMIT :lim" ); $stmt->execute([':q' => "%{$query}%", ':mp' => $maxPrice, ':lim' => $limit]); echo json_encode(['success' => true, 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)]); break; case 'get_product': $id = $params['product_id'] ?? 0; $stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?"); $stmt->execute([$id]); $product = $stmt->fetch(PDO::FETCH_ASSOC); echo json_encode($product ? ['success' => true, 'data' => $product] : ['success' => false, 'error' => 'Product not found'] ); break; case 'get_categories': $stmt = $pdo->query("SELECT id, name, (SELECT COUNT(*) FROM products WHERE category_id = c.id) as count FROM categories c ORDER BY name"); echo json_encode(['success' => true, 'data' => $stmt->fetchAll(PDO::FETCH_ASSOC)]); break; case 'check_availability': $id = $params['product_id'] ?? 0; $stmt = $pdo->prepare("SELECT stock FROM products WHERE id = ?"); $stmt->execute([$id]); $row = $stmt->fetch(PDO::FETCH_ASSOC); echo json_encode($row ? ['success' => true, 'data' => ['in_stock' => $row['stock'] > 0, 'quantity' => (int)$row['stock']]] : ['success' => false, 'error' => 'Product not found'] ); break; case 'check_order_status': $orderId = $params['order_id'] ?? ''; $email = $params['email'] ?? ''; if ($orderId) { $stmt = $pdo->prepare("SELECT * FROM orders WHERE id = ?"); $stmt->execute([$orderId]); } elseif ($email) { $stmt = $pdo->prepare("SELECT * FROM orders WHERE email = ? ORDER BY created_at DESC LIMIT 1"); $stmt->execute([$email]); } $order = $stmt->fetch(PDO::FETCH_ASSOC) ?? null; echo json_encode($order ? ['success' => true, 'data' => $order] : ['success' => false, 'error' => 'Order not found'] ); break; case 'lookup_account': $accountId = $params['account_id'] ?? ''; $phone = $params['phone'] ?? ''; $email = $params['email'] ?? ''; if ($accountId) { $stmt = $pdo->prepare("SELECT * FROM customers WHERE account_id = ?"); $stmt->execute([$accountId]); } elseif ($phone) { $stmt = $pdo->prepare("SELECT * FROM customers WHERE phone = ?"); $stmt->execute([$phone]); } elseif ($email) { $stmt = $pdo->prepare("SELECT * FROM customers WHERE email = ?"); $stmt->execute([$email]); } $account = $stmt->fetch(PDO::FETCH_ASSOC) ?? null; echo json_encode($account ? ['success' => true, 'data' => $account] : ['success' => false, 'error' => 'Account not found'] ); break; default: echo json_encode(['success' => false, 'error' => "Unknown action: {$action}"]); }
WordPress / WooCommerce
// Add to your theme's functions.php or create a custom plugin add_action('rest_api_init', function() { register_rest_route('vexar/v1', '/data-api', [ 'methods' => 'POST', 'callback' => 'vexar_data_api_handler', 'permission_callback' => 'vexar_verify_api_key', ]); }); function vexar_verify_api_key($request) { $auth = $request->get_header('Authorization'); return $auth === 'Bearer YOUR_SECRET_KEY'; } function vexar_data_api_handler($request) { $action = $request['action'] ?? ''; $params = $request['params'] ?? []; switch ($action) { case 'ping': return ['success' => true, 'data' => ['status' => 'ok']]; case 'search_products': $args = [ 'post_type' => 'product', 's' => $params['query'] ?? '', 'posts_per_page' => min(10, $params['limit'] ?? 5), 'post_status' => 'publish', ]; $products = []; foreach (wc_get_products($args) as $p) { if (isset($params['max_price']) && $p->get_price() > $params['max_price']) continue; $products[] = [ 'id' => $p->get_id(), 'name' => $p->get_name(), 'price' => (float)$p->get_price(), 'currency' => get_woocommerce_currency(), 'url' => $p->get_permalink(), 'in_stock' => $p->is_in_stock(), ]; } return ['success' => true, 'data' => $products]; // Add more cases as needed... default: return ['success' => false, 'error' => "Unknown action"]; } } // API URL for Vexar.Chat: https://your-site.com/wp-json/vexar/v1/data-api
Node.js (Express)
const express = require('express'); const app = express(); app.use(express.json()); // Auth middleware const verifyKey = (req, res, next) => { const auth = req.headers.authorization || ''; if (auth !== 'Bearer YOUR_SECRET_KEY') return res.status(401).json({ success: false, error: 'Unauthorized' }); next(); }; app.post('/vexar-api', verifyKey, async (req, res) => { const { action, params = {} } = req.body; switch (action) { case 'ping': return res.json({ success: true, data: { status: 'ok' } }); case 'search_products': // Replace with your DB query const products = await db.query(`SELECT * FROM products WHERE name ILIKE $1 LIMIT $2`, [`%${params.query || ''}%`, params.limit || 5]); return res.json({ success: true, data: products.rows }); case 'lookup_account': const id = params.account_id || params.phone || params.email || ''; const account = await db.query( `SELECT * FROM customers WHERE account_id = $1 OR phone = $1 OR email = $1 LIMIT 1`, [id]); return res.json(account.rows[0] ? { success: true, data: account.rows[0] } : { success: false, error: 'Account not found' }); default: return res.json({ success: false, error: `Unknown action: ${action}` }); } }); app.listen(3000);
7. Rules & Limits
| Rule | Value |
|---|---|
| Max items per response | 10 items |
| Default timeout | 5 seconds |
| Max timeout | 30 seconds |
| Response format | JSON only |
| HTTP method | POST only |
| Max tool iterations per message | 3 (AI can call your API up to 3 times per visitor message) |
| Supported AI providers | OpenAI, Anthropic (Claude), Google Gemini |
| Not supported | DeepSeek (no function calling support) |
- Your API must respond within the configured timeout (default 5 sec). Slow responses will be treated as errors.
- Always implement the
pingaction for connection testing. - Return proper error messages in the
errorfield — the AI will use them to inform the visitor. - Keep your API key secret. Rotate it regularly.
Need help implementing the API?
Contact Support