Claude tool_use Integration Guide

Use Claude's native tool_use (function calling) to give Claude real-time access to the BuyWhere product catalog.

Overview

Claude's tool_use capability works similarly to OpenAI's function calling — you provide tool definitions with input schemas, Claude decides when to call them, and you execute the tools and return results.

Base URL: https://api.buywhere.ai

Authentication: Authorization: Bearer <your_api_key>


Tool Definitions

Attach these to your Claude tools array to enable Claude to search products, compare prices, and find deals.

1. search_products

Full-text search across the BuyWhere catalog (Lazada, Shopee, Qoo10, Carousell, and more).

{
  "name": "search_products",
  "description": "Search the BuyWhere product catalog by keyword. Returns ranked results from Singapore e-commerce platforms (Lazada, Shopee, Qoo10, Carousell).",
  "input_schema": {
    "type": "object",
    "properties": {
      "q": {
        "type": "string",
        "description": "Product search query (e.g. 'iphone 15 pro', 'running shoes')"
      },
      "category": {
        "type": "string",
        "description": "Optional category filter (e.g. 'Electronics', 'Fashion')"
      },
      "min_price": {
        "type": "number",
        "description": "Minimum price in SGD"
      },
      "max_price": {
        "type": "number",
        "description": "Maximum price in SGD"
      },
      "source": {
        "type": "string",
        "description": "Platform filter: lazada_sg, shopee_sg, qoo10_sg, carousell_sg, etc."
      },
      "brand": {
        "type": "string",
        "description": "Filter by brand name (partial match)"
      },
      "min_rating": {
        "type": "number",
        "description": "Minimum product rating (0-5)"
      },
      "limit": {
        "type": "integer",
        "description": "Max results (default 20, max 100)"
      },
      "offset": {
        "type": "integer",
        "description": "Pagination offset (default 0)"
      },
      "include_facets": {
        "type": "boolean",
        "description": "Include facet counts for categories, platforms, brands, and price ranges"
      }
    },
    "required": ["q"]
  }
}

Example API call:

import httpx

response = httpx.get(
    "https://api.buywhere.ai/v1/products",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={
        "q": "iphone 15 pro",
        "max_price": 1500,
        "limit": 10
    }
)
data = response.json()
products = data["items"]

Example Claude usage:

from anthropic import Anthropic

client = Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=[
        {
            "name": "search_products",
            "description": "Search the BuyWhere product catalog by keyword.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "q": {"type": "string", "description": "Product search query"},
                    "max_price": {"type": "number", "description": "Maximum price in SGD"},
                    "limit": {"type": "integer", "description": "Max results (default 20, max 100)"}
                },
                "required": ["q"]
            }
        }
    ],
    messages=[{"role": "user", "content": "Find me the best iphone 15 pro deal in Singapore"}]
)

for tool_use in response.content:
    if tool_use.type == "tool_use":
        args = tool_use.input
        # Call BuyWhere API with args["q"], args.get("max_price"), etc.

2. best_price

Find the cheapest listing for a product across all platforms.

{
  "name": "best_price",
  "description": "Find the cheapest single listing for a product across all Singapore e-commerce platforms (Lazada, Shopee, Qoo10, Carousell). Returns one product with the lowest price.",
  "input_schema": {
    "type": "object",
    "properties": {
      "q": {
        "type": "string",
        "description": "Product name to search for (e.g. 'dyson vacuum', 'playstation 5')"
      },
      "category": {
        "type": "string",
        "description": "Optional category to narrow the search"
      }
    },
    "required": ["q"]
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/products/best-price",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"q": "dyson vacuum"}
)
product = response.json()
# product is a single ProductResponse object, not a list

3. compare_products

Compare the same product across all sources. Takes a search query and returns all matching products from different platforms, with cheapest_product_id, best_rated_product_id, and fastest_shipping_product_id highlights.

{
  "name": "compare_products",
  "description": "Search for a product and return all matches across platforms to compare prices. Returns highlights for cheapest, best rated, and fastest shipping options.",
  "input_schema": {
    "type": "object",
    "properties": {
      "q": {
        "type": "string",
        "description": "Product search query (e.g. 'iphone 15', 'nike air max')"
      },
      "limit": {
        "type": "integer",
        "description": "Max seed products to search for matches (default 10, max 50)"
      }
    },
    "required": ["q"]
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/products/compare",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"q": "iphone 15 pro", "limit": 10}
)
data = response.json()
# data["items"] = list of matching products
# data["cheapest_product_id"] = ID of cheapest listing
# data["best_rated_product_id"] = ID of highest rated listing

4. get_product

Retrieve full details for a specific product by its BuyWhere ID.

{
  "name": "get_product",
  "description": "Retrieve full details for a specific product by its BuyWhere product ID.",
  "input_schema": {
    "type": "object",
    "properties": {
      "product_id": {
        "type": "integer",
        "description": "The BuyWhere product ID (integer)"
      }
    },
    "required": ["product_id"]
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/products/12345",
    headers={"Authorization": "Bearer bw_live_xxxxx"}
)
product = response.json()

5. get_deals

Find products with significant price drops compared to their historical price.

{
  "name": "get_deals",
  "description": "Find products with significant price drops compared to their original/historical price. Returns deals sorted by discount percentage (best deals first).",
  "input_schema": {
    "type": "object",
    "properties": {
      "category": {
        "type": "string",
        "description": "Optional category filter (e.g. 'Electronics')"
      },
      "min_discount_pct": {
        "type": "number",
        "description": "Minimum discount percentage (default 10)"
      },
      "source": {
        "type": "string",
        "description": "Platform filter: lazada_sg, shopee_sg, qoo10_sg, etc."
      },
      "limit": {
        "type": "integer",
        "description": "Max results (default 20, max 100)"
      },
      "offset": {
        "type": "integer",
        "description": "Pagination offset (default 0)"
      }
    }
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/deals",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"min_discount_pct": 20, "limit": 20}
)
data = response.json()
deals = data["items"]

6. list_categories

Browse the flat list of product categories.

{
  "name": "list_categories",
  "description": "List all available product categories with product counts. Returns a flat list of categories sorted by product count.",
  "input_schema": {
    "type": "object",
    "properties": {}
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/categories",
    headers={"Authorization": "Bearer bw_live_xxxxx"}
)
data = response.json()
# data["categories"] = list of {id, name, slug, count}

7. get_category_tree

Get the hierarchical category tree.

{
  "name": "get_category_tree",
  "description": "Get the hierarchical category tree with product counts. Use this to let users browse categories.",
  "input_schema": {
    "type": "object",
    "properties": {
      "depth": {
        "type": "integer",
        "description": "Maximum tree depth (1-10, default 2)"
      },
      "include_empty": {
        "type": "boolean",
        "description": "Include categories with zero products (default false)"
      }
    }
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/categories/tree",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"depth": 2}
)

8. get_category_products

Get products within a specific category.

{
  "name": "get_category_products",
  "description": "Get products within a specific category. Use list_categories or get_category_tree first to find the category ID.",
  "input_schema": {
    "type": "object",
    "properties": {
      "category_id": {
        "type": "string",
        "description": "The category ID (e.g. 'electronics', 'mobile_phones')"
      },
      "limit": {
        "type": "integer",
        "description": "Max results (default 20, max 100)"
      },
      "offset": {
        "type": "integer",
        "description": "Pagination offset (default 0)"
      },
      "min_price": {
        "type": "number",
        "description": "Minimum price filter"
      },
      "max_price": {
        "type": "number",
        "description": "Maximum price filter"
      },
      "source": {
        "type": "string",
        "description": "Filter by platform (e.g. 'shopee_sg')"
      }
    },
    "required": ["category_id"]
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/categories/electronics/products",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"limit": 20}
)
data = response.json()
# data["items"] = list of products in this category

9. get_trending_products

Get trending products ranked by query volume and clicks.

{
  "name": "get_trending_products",
  "description": "Get trending products ranked by user views and clicks. Good for 'what's popular' recommendations.",
  "input_schema": {
    "type": "object",
    "properties": {
      "period": {
        "type": "string",
        "description": "Trending period: '24h', '7d', or '30d' (default '7d')"
      },
      "category": {
        "type": "string",
        "description": "Filter by category name"
      },
      "limit": {
        "type": "integer",
        "description": "Max results (default 50, max 100)"
      }
    }
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/products/trending",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"period": "7d", "limit": 20}
)

10. get_product_matches

Get matching products across platforms for a specific product ID.

{
  "name": "get_product_matches",
  "description": "Given a BuyWhere product ID, find the same product listed on other platforms (same model/make from a different merchant).",
  "input_schema": {
    "type": "object",
    "properties": {
      "product_id": {
        "type": "integer",
        "description": "The BuyWhere product ID"
      },
      "min_confidence": {
        "type": "number",
        "description": "Minimum match confidence score (0-1, default 0.0)"
      }
    },
    "required": ["product_id"]
  }
}

Example API call:

response = httpx.get(
    "https://api.buywhere.ai/v1/products/12345/matches",
    headers={"Authorization": "Bearer bw_live_xxxxx"},
    params={"min_confidence": 0.5}
)

Complete Python Example

import json
from anthropic import Anthropic
import httpx

client = Anthropic(api_key="sk-ant-...")

BUYWHERE_API_KEY = "bw_live_xxxxx"
BUYWHERE_BASE = "https://api.buywhere.ai"

TOOLS = [
    {
        "name": "search_products",
        "description": "Search the BuyWhere product catalog by keyword.",
        "input_schema": {
            "type": "object",
            "properties": {
                "q": {"type": "string", "description": "Product search query"},
                "max_price": {"type": "number", "description": "Maximum price in SGD"},
                "limit": {"type": "integer", "description": "Max results (default 20, max 100)"}
            },
            "required": ["q"]
        }
    },
    {
        "name": "best_price",
        "description": "Find the cheapest listing for a product across all platforms.",
        "input_schema": {
            "type": "object",
            "properties": {
                "q": {"type": "string", "description": "Product name"},
                "category": {"type": "string", "description": "Optional category filter"}
            },
            "required": ["q"]
        }
    },
    {
        "name": "get_product",
        "description": "Retrieve full details for a specific product by its BuyWhere ID.",
        "input_schema": {
            "type": "object",
            "properties": {
                "product_id": {"type": "integer", "description": "The BuyWhere product ID"}
            },
            "required": ["product_id"]
        }
    },
    {
        "name": "get_deals",
        "description": "Find products with significant price drops.",
        "input_schema": {
            "type": "object",
            "properties": {
                "min_discount_pct": {"type": "number", "description": "Minimum discount percentage"},
                "limit": {"type": "integer", "description": "Max results"}
            }
        }
    }
]


def search_buywhere(q: str, max_price: float | None = None, limit: int = 20):
    headers = {"Authorization": f"Bearer {BUYWHERE_API_KEY}"}
    params = {"q": q, "limit": limit}
    if max_price:
        params["max_price"] = max_price
    resp = httpx.get(f"{BUYWHERE_BASE}/v1/products", headers=headers, params=params)
    resp.raise_for_status()
    return resp.json()


def best_price_buywhere(q: str, category: str | None = None):
    headers = {"Authorization": f"Bearer {BUYWHERE_API_KEY}"}
    params = {"q": q}
    if category:
        params["category"] = category
    resp = httpx.get(f"{BUYWHERE_BASE}/v1/products/best-price", headers=headers, params=params)
    resp.raise_for_status()
    return resp.json()


def get_product_buywhere(product_id: int):
    headers = {"Authorization": f"Bearer {BUYWHERE_API_KEY}"}
    resp = httpx.get(f"{BUYWHERE_BASE}/v1/products/{product_id}", headers=headers)
    resp.raise_for_status()
    return resp.json()


def get_deals_buywhere(min_discount_pct: float = 10, limit: int = 20):
    headers = {"Authorization": f"Bearer {BUYWHERE_API_KEY}"}
    resp = httpx.get(
        f"{BUYWHERE_BASE}/v1/deals",
        headers=headers,
        params={"min_discount_pct": min_discount_pct, "limit": limit}
    )
    resp.raise_for_status()
    return resp.json()


TOOL_FUNCTIONS = {
    "search_products": lambda args: search_buywhere(args["q"], args.get("max_price"), args.get("limit", 20)),
    "best_price": lambda args: best_price_buywhere(args["q"], args.get("category")),
    "get_product": lambda args: get_product_buywhere(args["product_id"]),
    "get_deals": lambda args: get_deals_buywhere(args.get("min_discount_pct", 10), args.get("limit", 20)),
}


def call_claude_with_product_search(user_query: str):
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        tools=TOOLS,
        messages=[{"role": "user", "content": user_query}]
    )

    for block in response.content:
        if block.type == "tool_use":
            tool_name = block.name
            tool_input = block.input
            tool_id = block.id

            results = TOOL_FUNCTIONS.get(tool_name, lambda _: {"error": f"Unknown tool: {tool_name}"})(tool_input)

            result_block = {
                "type": "tool_result",
                "tool_use_id": tool_id,
                "content": json.dumps(results)
            }

            response = client.messages.create(
                model="claude-sonnet-4-20250514",
                max_tokens=1024,
                tools=TOOLS,
                messages=[
                    {"role": "user", "content": user_query},
                    {"role": "assistant", "content": [block]},
                    {"role": "user", "content": [result_block]}
                ]
            )

            return response.content[0].text

    return response.content[0].text


# Usage
answer = call_claude_with_product_search(
    "What's the best price for a Dyson V15 vacuum cleaner in Singapore?"
)
print(answer)

Response Parsing Patterns

ProductListResponse (search, category products)

{
  "total": 1523,
  "limit": 20,
  "offset": 0,
  "has_more": true,
  "items": [
    {
      "id": 12345,
      "sku": "SHOPEE-SG-IPHONE15PRO-256-BLK",
      "source": "shopee_sg",
      "merchant_id": "shop_abc123",
      "name": "Apple iPhone 15 Pro 256GB Black",
      "description": "Latest Apple iPhone...",
      "price": 1499.00,
      "currency": "SGD",
      "price_sgd": null,
      "buy_url": "https://shopee.sg/iphone-15-pro",
      "affiliate_url": "https://affiliate.buywhere.ai/track/123",
      "image_url": "https://cf.shopee.sg/file/abc123",
      "barcode": null,
      "brand": "Apple",
      "category": "Mobile Phones",
      "category_path": ["Electronics", "Phones", "Smartphones"],
      "rating": 4.7,
      "review_count": 324,
      "avg_rating": 4.5,
      "is_available": true,
      "in_stock": true,
      "stock_level": "high",
      "last_checked": "2026-04-04T10:30:00Z",
      "metadata": {"model": "iPhone 15 Pro"},
      "updated_at": "2026-04-03T10:30:00Z",
      "price_trend": "stable"
    }
  ],
  "facets": null
}

DealItem

{
  "id": 67890,
  "sku": "LAZADA-SG-GALAXYBUDS2PRO-BLACK",
  "source": "lazada_sg",
  "name": "Samsung Galaxy Buds2 Pro",
  "price": 178.00,
  "currency": "SGD",
  "original_price": 279.00,
  "discount_pct": 36,
  "buy_url": "https://lazada.sg/galaxy-buds2-pro",
  "image_url": "https://...",
  "brand": "Samsung",
  "category": "Audio",
  "deal_score": 85.3,
  "is_available": true
}

ProductResponse (single product, best-price)

{
  "id": 12345,
  "sku": "lazada_sg_123456789",
  "source": "lazada_sg",
  "merchant_id": "lazada_sg",
  "name": "Dyson V15 Detect Vacuum Cleaner",
  "description": "...",
  "price": 649.00,
  "currency": "SGD",
  "price_sgd": null,
  "buy_url": "https://lazada.sg/dyson-v15",
  "affiliate_url": "https://affiliate.buywhere.ai/track/456",
  "image_url": "https://...",
  "barcode": null,
  "brand": "Dyson",
  "category": "Home Appliances",
  "category_path": ["Electronics", "Home Appliances", "Vacuum Cleaners"],
  "rating": 4.8,
  "review_count": 512,
  "avg_rating": 4.7,
  "is_available": true,
  "in_stock": true,
  "stock_level": "high",
  "last_checked": "2026-04-04T12:00:00Z",
  "metadata": null,
  "updated_at": "2026-04-04T12:00:00Z",
  "price_trend": "down"
}

Error Handling

import httpx

def search_safe(q: str, **kwargs):
    try:
        resp = httpx.get(
            f"{BUYWHERE_BASE}/v1/products",
            headers={"Authorization": f"Bearer {BUYWHERE_API_KEY}"},
            params={"q": q, **kwargs},
            timeout=15.0
        )
        resp.raise_for_status()
        return resp.json()
    except httpx.HTTPStatusError as e:
        if e.response.status_code == 401:
            raise RuntimeError("Invalid BuyWhere API key")
        elif e.response.status_code == 429:
            raise RuntimeError("BuyWhere rate limit exceeded — retry after a few seconds")
        elif e.response.status_code == 404:
            return {"items": [], "total": 0, "has_more": False}
        raise
    except httpx.RequestError as e:
        raise RuntimeError(f"BuyWhere API unreachable: {e}")

# In your Claude tool handler:
for block in response.content:
    if block.type == "tool_use":
        try:
            if block.name == "search_products":
                results = search_safe(**block.input)
            elif block.name == "get_product":
                results = get_product_buywhere(block.input["product_id"])
            elif block.name == "best_price":
                results = best_price_buywhere(block.input["q"], block.input.get("category"))
        except RuntimeError as e:
            results = {"error": str(e)}

Tips for AI Agents

  1. Parse tool_use blocks correctly — Claude returns tool_use blocks with name, input (dict), and id. Execute the tool and return a tool_result block.
  2. Validate tool arguments — Claude respects the input_schema. Always parse the input dict before passing to the API.
  3. Respect rate limits — BuyWhere allows 100–1000 req/min depending on your tier. Cache frequent queries.
  4. Use best_price for quick cheapest-listing lookups — it returns a single product (the cheapest), faster than compare_products for simple use cases.
  5. Use compare_products when you need full cross-platform comparison — it returns all matches and highlights (cheapest, best rated, fastest shipping).
  6. Chain list_categoriesget_category_treeget_category_products — first discover the category structure, then fetch products within a category.
  7. Handle empty results gracefully — if a search returns 0 products, try broadening the query or removing price filters.
  8. Use include_facets: true on search_products when building dynamic filter UIs — it returns counts per category, brand, platform, and price range.

Key Differences from OpenAI Function Calling

AspectClaude tool_useOpenAI function_call
Schema fieldinput_schemaparameters
Tool result formattool_result blocktool_call_id + content
Multi-tool callsMultiple tool_use blocks in one responsemessage.tool_calls array
ContinuationCreate new message with tool_resultPass tool role message

See Also