BuyWhere API Documentation
Developer-facing documentation for the BuyWhere product catalog API. Target audience: AI agent developers integrating product search.
Getting Started
Overview
The BuyWhere API provides structured access to a product catalog spanning multiple Singapore and Southeast Asian e-commerce platforms. Built for AI agent workflows with features like batch lookups, confidence scoring, and real-time streaming.
Base URL
https://api.buywhere.ai
Quick Start
1. Get an API Key
Sign up at https://api.buywhere.ai/v1/developers/signup to receive your API key.
Your key will look like: bw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2. Make Your First Request
curl -H "Authorization: Bearer bw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
"https://api.buywhere.ai/v2/search?q=iphone+15+pro&limit=5"
3. Understand the Response
{
"query": "iphone 15 pro",
"total": 1247,
"limit": 5,
"offset": 0,
"has_more": true,
"items": [
{
"id": 18472931,
"sku": "IPHONE15PRO256",
"source": "shopee_sg",
"name": "iPhone 15 Pro 256GB Natural Titanium",
"price": "1349.00",
"currency": "SGD",
"buy_url": "https://shopee.sg/product/...",
"affiliate_url": "https://buywhere.ai/click/...",
"image_url": "https://cf.shopee.sg/file/...",
"brand": "Apple",
"category": "Mobile Phones",
"rating": "4.8",
"review_count": 2341,
"is_available": true,
"confidence_score": 0.95,
"data_freshness": "recent"
}
]
}
Response Format
All API responses are JSON with consistent wrapper fields:
| Field | Type | Description |
|---|---|---|
total | integer | Total matching products |
limit | integer | Results per page |
offset | integer | Current offset |
has_more | boolean | More results available |
items | array | Array of product objects |
Product objects include these core fields:
| Field | Type | Description |
|---|---|---|
id | integer | Unique BuyWhere product ID |
sku | string | Product SKU from source |
source | string | Platform source (e.g., shopee_sg, lazada_sg) |
name | string | Product title |
price | string | Price as decimal string |
currency | string | ISO currency code (SGD, MYR, THB, etc.) |
buy_url | string | Direct link to product |
affiliate_url | string | BuyWhere tracked link for commissions |
image_url | string | Product image URL |
brand | string | Brand name |
category | string | Product category |
rating | string | Average rating (0-5) |
review_count | integer | Number of reviews |
is_available | boolean | Currently in stock |
confidence_score | float | Data quality score (0-1) |
data_freshness | string | fresh, recent, stale, very_stale |
Authentication
API Key Authentication
All API requests require authentication via Bearer token or X-API-Key header.
Option 1: Authorization Header (Recommended)
curl -H "Authorization: Bearer bw_live_xxxxxxxx" \
"https://api.buywhere.ai/v2/products/123"
Option 2: X-API-Key Header
curl -H "X-API-Key: bw_live_xxxxxxxx" \
"https://api.buywhere.ai/v2/products/123"
Key Tiers
| Tier Prefix | Rate Limit | Use Case |
|---|---|---|
bw_free_* | 60 req/min | Demo, testing |
bw_live_* | 600 req/min | Production |
bw_partner_* | Unlimited | Platform data partners |
Scopes
API keys support granular scopes:
| Scope | Permission |
|---|---|
products:read | Read product data |
products:write | Submit product updates |
deals:read | Access deals endpoints |
analytics:read | View usage analytics |
webhooks:manage | Create and manage webhooks |
Key Rotation
Rotate your key without downtime:
POST /v1/keys/{id}/rotate
The old key remains valid for 24 hours during transition.
Rate Limits
Rate limits are enforced per API key and reset on a sliding window.
| Tier | Limit | Window |
|---|---|---|
| Free | 60 requests | 1 minute |
| Live | 600 requests | 1 minute |
| Partner | Unlimited | - |
Rate Limit Headers
Response headers show your current limit status:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 547
X-RateLimit-Reset: 1713202500
Handling Rate Limits
When rate limited, the API returns 429 Too Many Requests:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"details": {
"retry_after": 60
}
}
}
Retry strategy: Use exponential backoff starting at 2 seconds.
Error Reference
HTTP Status Codes
| Code | Meaning | Cause |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Malformed request syntax |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Valid key but insufficient scope |
| 404 | Not Found | Resource does not exist |
| 422 | Unprocessable Entity | Validation error in parameters |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | BuyWhere server error |
| 503 | Service Unavailable | Temporary downtime |
Error Response Format
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description",
"details": {}
}
}
Validation Errors (422)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"errors": [
{
"field": "price_min",
"message": "Value must be greater than or equal to 0",
"type": "greater_than_equal"
}
],
"count": 1
}
}
}
Common Errors
MISSING_API_KEY
HTTP: 401
Cause: No API key provided
Fix: Add Authorization: Bearer <key> header
# Wrong
curl "https://api.buywhere.ai/v2/products"
# Correct
curl -H "Authorization: Bearer bw_live_xxx" \
"https://api.buywhere.ai/v2/products"
INVALID_API_KEY
HTTP: 401
Cause: API key not found or revoked
Fix: Generate a new key at /v1/developers/signup
INVALID_CURSOR
HTTP: 400
Cause: Malformed pagination cursor
Fix: Re-fetch initial query to get a fresh cursor
INVALID_REGION
HTTP: 422
Cause: Invalid region parameter
Fix: Use us, sg, or sea
# Wrong
/v2/products?region=asiapacific
# Correct
/v2/products?region=sea
QUERY_TOO_LONG
HTTP: 422
Cause: Search query exceeds 500 characters
Fix: Shorten your search query
MAX_LIMIT_EXCEEDED
HTTP: 422
Cause: limit parameter exceeds maximum
Fix: Keep limit ≤ 100 for standard endpoints
UNSUPPORTED_CURRENCY
HTTP: 422
Cause: Currency code not supported
Fix: Use one of: SGD, MYR, THB, PHP, VND, USD
PRODUCT_NOT_FOUND
HTTP: 404
Cause: Product ID does not exist
Fix: Verify the product ID, or search for the product first
RATE_LIMIT_EXCEEDED
HTTP: 429
Cause: Too many requests in the current window
Fix: Wait retry_after seconds and retry with exponential backoff
INTERNAL_ERROR
HTTP: 500
Cause: Unexpected server error
Fix: Retry after 30 seconds. If persistent, contact support.
Agent-Native Features
The BuyWhere API includes features specifically designed for AI agent workflows.
Batch Lookups
Fetch multiple products in a single request:
POST /v2/products/batch-details
Content-Type: application/json
Authorization: Bearer bw_live_xxx
{
"product_ids": [18472931, 18347291, 18234521]
}
Streaming Updates
Subscribe to real-time product updates via SSE:
GET /v2/products/stream?category=Mobile+Phones
Authorization: Bearer bw_live_xxx
Accept: text/event-stream
Price Change Stream
Monitor price changes for specific products:
GET /v2/prices/stream?product_ids=18472931,18347291&min_price_change_pct=5
Authorization: Bearer bw_live_xxx
Accept: text/event-stream
Confidence Score
Each product includes a confidence_score (0-1) indicating data quality:
- 0.9-1.0: High confidence, complete data with image, rating, reviews
- 0.7-0.9: Medium confidence, partial data
- 0.5-0.7: Lower confidence, limited source data
- <0.5: Minimal data, use with caution
Session Context
Pass session context for personalized results:
curl -H "X-Session-Context: eyJidWRnZXRfbWF4Ijo1MDAwLCJ0YXJnZXRfY3VycmVuY3kiOiJTR0QifQ==" \
-H "Authorization: Bearer bw_live_xxx" \
"https://api.buywhere.ai/v2/agents/search?q=headphones"
The header is base64-encoded JSON with fields:
budget_min,budget_max: Price range filtertarget_currency: Preferred currencypreferred_sources: Comma-separated platform list
Code Examples
Python
import httpx
API_KEY = "bw_live_xxxxxxxxxxxxxxxx"
BASE_URL = "https://api.buywhere.ai"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Search products
response = httpx.get(
f"{BASE_URL}/v2/search",
params={"q": "wireless headphones", "limit": 10},
headers=headers
)
data = response.json()
print(f"Found {data['total']} products")
# Batch lookup
response = httpx.post(
f"{BASE_URL}/v2/products/batch-details",
json={"product_ids": [18472931, 18347291]},
headers=headers
)
products = response.json()["products"]
JavaScript/Node.js
const API_KEY = "bw_live_xxxxxxxxxxxxxxxx";
const BASE_URL = "https://api.buywhere.ai";
const headers = { "Authorization": `Bearer ${API_KEY}` };
// Search products
const searchResponse = await fetch(
`${BASE_URL}/v2/search?q=wireless+headphones&limit=10`,
{ headers }
);
const { total, items } = await searchResponse.json();
console.log(`Found ${total} products`);
// Batch lookup
const batchResponse = await fetch(
`${BASE_URL}/v2/products/batch-details`,
{
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ product_ids: [18472931, 18347291] })
}
);
const { products } = await batchResponse.json();
cURL
# Search
curl "https://api.buywhere.ai/v2/search?q=laptop&limit=5" \
-H "Authorization: Bearer bw_live_xxx"
# Batch lookup
curl -X POST "https://api.buywhere.ai/v2/products/batch-details" \
-H "Authorization: Bearer bw_live_xxx" \
-H "Content-Type: application/json" \
-d '{"product_ids": [18472931, 18347291]}'
# Price comparison
curl "https://api.buywhere.ai/v2/agents/price-comparison?product_name=iphone+15" \
-H "Authorization: Bearer bw_live_xxx"