V2 Search Products
Search products across the BuyWhere catalog with full-text search, filters, and regional targeting.
Base URL: https://api.buywhere.ai/v2/search
Overview
The V2 Search endpoint provides full-text search across millions of products from multiple Southeast Asian and US e-commerce platforms. It supports regional filtering, price range filtering, availability filtering, and currency conversion.
HTTP Method
GET /v2/search
Authentication
Requires API key in the Authorization header:
Authorization: Bearer bw_live_xxxxxxxxxxxxxxxx
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Yes | - | Full-text search query (max 500 chars) |
category | string | No | - | Filter by category name (partial, case-insensitive) |
platform | string | No | - | Filter by source platform (e.g., shopee_sg, lazada_sg) |
min_price | number | No | - | Minimum price filter in SGD |
max_price | number | No | - | Maximum price filter in SGD |
country | string | No | - | Filter by country code(s), comma-separated (e.g., SG,MY,US) |
region | string | No | auto | Filter by region: us, sg, sea |
in_stock | boolean | No | - | Filter by availability |
limit | integer | No | 20 | Results per page (1-100) |
offset | integer | No | 0 | Pagination offset |
currency | string | No | SGD | Response currency: SGD, MYR, THB, PHP, VND, USD |
Request Example
cURL
curl -X GET "https://api.buywhere.ai/v2/search?q=laptop+gaming&category=electronics&min_price=500&max_price=3000&limit=10" \
-H "Authorization: Bearer bw_live_xxxxxxxxxxxxxxxx"
Python
import httpx
API_KEY = "bw_live_xxxxxxxxxxxxxxxx"
BASE_URL = "https://api.buywhere.ai"
headers = {"Authorization": f"Bearer {API_KEY}"}
response = httpx.get(
f"{BASE_URL}/v2/search",
params={
"q": "laptop gaming",
"category": "electronics",
"min_price": 500,
"max_price": 3000,
"limit": 10
},
headers=headers
)
data = response.json()
print(f"Found {data['total']} products")
for item in data['items']:
print(f" - {item['title']}: {item['currency']} {item['price']}")
JavaScript (Node.js)
const API_KEY = "bw_live_xxxxxxxxxxxxxxxx";
const BASE_URL = "https://api.buywhere.ai";
const response = await fetch(
`${BASE_URL}/v2/search?q=laptop+gaming&category=electronics&min_price=500&max_price=3000&limit=10`,
{
headers: { "Authorization": `Bearer ${API_KEY}` }
}
);
const data = await response.json();
console.log(`Found ${data.total} products`);
data.items.forEach(item => {
console.log(` - ${item.title}: ${item.currency} ${item.price}`);
});
Go
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
func searchProducts(apiKey, query string) error {
baseURL, _ := url.Parse("https://api.buywhere.ai/v2/search")
params := url.Values{}
params.Set("q", query)
params.Set("category", "electronics")
params.Set("min_price", "500")
params.Set("max_price", "3000")
params.Set("limit", "10")
baseURL.RawQuery = params.Encode()
req, _ := http.NewRequest("GET", baseURL.String(), nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
total := int(result["total"].(float64))
fmt.Printf("Found %d products\n", total)
items := result["items"].([]interface{})
for _, item := range items {
m := item.(map[string]interface{})
fmt.Printf(" - %s: %s %s\n", m["title"], m["currency"], m["price"])
}
return nil
}
Response
Success Response (200 OK)
{
"query": "laptop gaming",
"total": 1247,
"limit": 10,
"offset": 0,
"has_more": true,
"items": [
{
"id": 18472931,
"sku": "ASUS-ROG-STRIX-G16",
"source": "shopee_sg",
"title": "ASUS ROG Strix G16 Gaming Laptop",
"description": "Intel Core i9, 32GB RAM, RTX 4070, 1TB SSD",
"price": "2499.00",
"currency": "SGD",
"buy_url": "https://shopee.sg/product/123456",
"affiliate_url": "https://buywhere.ai/track/abc123",
"image_url": "https://cf.shopee.sg/file/xxxxx",
"brand": "ASUS",
"category": "Computers & Laptops",
"rating": 4.8,
"review_count": 342,
"is_available": true,
"in_stock": true,
"stock_level": null,
"updated_at": "2026-04-15T10:30:00Z"
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
query | string | The search query that was executed |
total | integer | Total number of matching products |
limit | integer | Results per page for this request |
offset | integer | Current offset |
has_more | boolean | Whether more results are available |
items | array | Array of product objects |
Product Object Fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique BuyWhere product ID |
sku | string | Product SKU from source platform |
source | string | Source platform identifier |
title | string | Product title |
description | string | Product description |
price | string | Price as decimal string |
currency | string | ISO currency code |
buy_url | string | Direct link to product on source |
affiliate_url | string | BuyWhere tracked affiliate link |
image_url | string | Product image URL |
brand | string | Brand name |
category | string | Primary category |
rating | float | Average rating (0-5) |
review_count | integer | Number of reviews |
is_available | boolean | Currently in stock |
in_stock | boolean | Stock status |
stock_level | string | Stock level indicator |
updated_at | datetime | Last update timestamp |
Error Responses
401 Unauthorized
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}
422 Validation Error
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"errors": [
{
"field": "q",
"message": "String exceeds maximum length of 500 characters",
"type": "string_too_long"
}
]
}
}
}
429 Rate Limited
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"details": {
"retry_after": 60
}
}
}
Regional Filtering
The region parameter supports three values:
| Region | Countries | Description |
|---|---|---|
us | US | United States |
sg | SG | Singapore |
sea | SG, MY, TH, PH, VN, ID | Southeast Asia |
If not specified, the API attempts to detect the region from request headers.
Currency Conversion
Specify the currency parameter to receive prices in your preferred currency. Supported currencies:
SGD- Singapore Dollar (default)MYR- Malaysian RinggitTHB- Thai BahtPHP- Philippine PesoVND- Vietnamese DongUSD- US Dollar
Caching
Search results are cached for 60 seconds to improve performance for repeated queries.
Client-side caching: Use Cache-Control: max-age=60 for browser caching.
Cache invalidation: Vary query parameters to get fresh results; identical queries return cached responses.
Performance Characteristics
Performance varies based on query complexity, result size, and load conditions:
| Condition | Expected Latency | Notes |
|---|---|---|
| Baseline (simple query, 10 results) | p50 < 50ms, p99 < 150ms | Low traffic, warm cache |
| Baseline (complex query, 50 results) | p50 < 100ms, p99 < 300ms | Full-text search overhead |
| Moderate load (100 concurrent) | p50 < 200ms, p99 < 500ms | Typical API usage |
| Heavy load (1000+ concurrent) | p50 < 500ms, p99 < 1200ms | Peak traffic scenarios |
Performance tips:
- Use specific queries: Broader searches take longer
- Limit results: Smaller result sets return faster
- Cache aggressively: Search results are cacheable for 60s
Rate Limits
| Tier | Requests/minute | Notes |
|---|---|---|
| Free | 60 | Default limit |
| Pro | 300 | Higher throughput |
| Enterprise | 1000+ | Custom limits |
When rate limited (429):
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"details": {
"retry_after": 32
}
}
}
Implement exponential backoff for retries:
import time
import random
def fetch_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
wait = int(response.headers.get("Retry-After", 60))
time.sleep(wait * (2 ** attempt) + random.random())
continue
return response
raise Exception("Max retries exceeded")
Related Endpoints
- V2 Product List - List products without search
- V2 Product Detail - Get single product by ID
- V2 Batch Details - Batch lookup multiple products
- Agent Native Search - AI-optimized search with confidence scores