Curio
Built on Microsoft Commerce IQ

Better shopping starts with better commerce grounding.

Curio is a working demo of the Commerce IQ API: one call returns up to 50 live, structured product offers from across the web. Curio adds personal context and AI ranking on top. This page covers what the API does, how to call it, and what we learned building with it.

50
offers per call
~0.5s
typical response
1
header to authenticate

The idea

Why Commerce IQ

AI shopping assistants usually fail in one of two ways: they make up products, or they scrape pages that break and go stale. Commerce IQ gives the model real data instead: live offers with prices, sellers, photos, specs and links, returned as clean JSON.

Grounded, not generated

Every product Curio shows is a real offer from the API. The AI only ranks and explains; it never invents items.

Structured by default

Prices, currencies, sellers, images and spec tables come back as fields, so there's no HTML parsing or brittle scrapers.

Many retailers, one call

Big marketplaces, brand stores and specialty shops come back together, often with several offers for the same product.

Fast enough for chat

Responses usually arrive in about half a second, so you can fan out into several queries and still answer quickly.

Market-aware

The region and language fields localize the catalog, currency and sellers, letting one integration serve many countries.

Built for agents

Plain-language queries work as-is, so an LLM planner can send what it decided straight to the API.

5 minutes

Quickstart

  1. Create a WebIQ / Grounding API key on a profile (App ID) whose Allowed Services include Commerce Beta.
  2. Keep the key on your server. Never ship it to a browser.
  3. Send a POST with the key in the x-apikey header (one hyphen).
cURL
curl -X POST "https://api.microsoft.ai/v3/search/commerce?features=ads3poff" \
  -H "x-apikey: $COMMERCE_IQ_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "query": "wireless headphones",
    "maxResults": 50,
    "language": "en",
    "region": "US"
  }'
TypeScript (server)
const res = await fetch("https://api.microsoft.ai/v3/search/commerce?features=ads3poff", {
  method: "POST",
  headers: {
    "x-apikey": process.env.COMMERCE_IQ_API_KEY!,
    "content-type": "application/json",
  },
  body: JSON.stringify({ query, maxResults: 50, language: "en", region: "US" }),
});
if (!res.ok) throw new Error(`Commerce IQ ${res.status}: ${await res.text()}`);
const { products } = await res.json();
Common gotcha: the header is x-apikey. It is not x-api-key, Authorization: Bearer or Ocp-Apim-Subscription-Key. Our first attempts failed with 401 for exactly this reason.

Reference

Request

POST https://api.microsoft.ai/v3/search/commerce

FieldTypeDescription
query*stringWhat the shopper wants, in plain language. Keywords work, and so do phrases like “men's slim jeans 34x32” or “quiet espresso machine under $400”.
maxResultsnumberHow many products to return. Curio always asks for 50 to get the widest set to re-rank.
languagestringLanguage code, for example en.
regionstringISO country code, for example US. Sets the catalog, currency and sellers.
?features=ads3poffquery paramWidens the result set. Curio turns it on to see more offers per query.

Reference

Response

The response is a list of products. Each product holds one or more offers, meaning the same item sold by different sellers. Prices are in minor units (cents).

Shape (abridged)
{
  "products": [
    {
      "offers": [
        {
          "id": "…",
          "name": "Sony WH-1000XM5 Wireless Noise Canceling Headphones",
          "description": "…",
          "seller": { "name": "Best Buy" },
          "price": { "offeredPrice": 32999, "listPrice": 39999, "currency": "USD" },
          "images": [{ "url": "https://…" }],
          "specifications": [
            { "name": "Brand", "values": ["Sony"] },
            { "name": "Type",  "values": ["Headphones"] }
          ],
          "clickUrl": "https://…",
          "shippingInfo": "Free shipping",
          "condition": "New"
        }
      ]
    }
  ]
}
  • Discounts: compare offeredPrice with listPrice to show a sale.
  • Price comparison: offers.length shows how widely a product is sold. Curio uses it as a popularity signal.
  • Specs: specifications provides Brand, Type, sizes and more, ready for filters and fit checks.

Field notes

Patterns we built with Commerce IQ

Situational fan-out

“3-day camping trip in Yosemite” becomes tents, sleeping bags, pads, pillows and cookware. Each category gets its own parallel Commerce IQ call and its own result section.

Rank on top of real data

We score all 50 offers deterministically first, then an LLM re-ranks them and writes a one-line reason per pick. If the AI step fails, the scored list still works.

Personalize the query

Filtering after the fact loses results. Rewriting “jeans” to “men's jeans” for a men's shopper returned far more relevant items than filtering the generic results.

Size-aware variants

With a saved size guide, Curio adds size-specific queries (“pants 44”, “shoes size 12”) to the fan-out and drops listings that don't fit.

Enrich your own data

Imported Gmail receipts often lack photos. A Commerce IQ lookup by name, brand and preferred store adds photos and product links.

Raw mode

An owner-only switch shows the untouched API output in about 2 seconds. It shows how good the grounding is before any harness touches it.

The Curio pipeline
query ─▶ AI planner ─▶ N queries (fan-out, size + department variants)
                              │ parallel
                              ▼
                     Commerce IQ × N  (50 offers each)
                              ▼
           dedupe ─▶ deterministic score ─▶ LLM re-rank + reasons
                              ▼
          grouped results · membership pricing · retailer logos

Same key

Companion: image search

The same key can call WebIQ image search. Curio falls back to it when Commerce IQ has no photo for an item. It can be limited to a preferred store's domain, for example walmart.com for a Walmart favorites import.

Request
POST https://api.microsoft.ai/v3/search/images
x-apikey: <key>
{ "query": "Great Value whole milk 1 gal", "maxResults": 8, "language": "en", "region": "US" }

→ { "imageResults": [{ "url", "thumbnailUrl", "hostPageUrl", "isAdult" }] }

Resilience

Errors & limits

401 / 403Wrong header or key, or the profile doesn't include Commerce Beta. Check that the header is x-apikey and that the profile's Allowed Services list it.
429Rate limited. Back off and retry. Curio pauses background photo matching and keeps live searches running.
5xxTemporary error. Show a friendly retry. Never show a stale or made-up result.

Ship it

Best practices

  • Keep the key on the server. Make every call from a server function and remove long tokens from logs.
  • Ask for 50 and let your model re-rank. A wider candidate set gives the AI step better items to choose from.
  • Put personalization in the query (department, size, brand tier), not just in later filtering.
  • Run calls in parallel. Fast responses let one question become five searches without the user noticing.
  • Plan for degraded mode. Grounded results should still show if your AI layer is down.
  • Normalize once. Map the response into your own product type in one module, so changes to the beta schema stay contained.

See it in action

Every search on Curio runs on Commerce IQ.

Start searching