{✦} Stylumia Developers

Product

What it is

A Product row is a capture of one retailer's listing at the moment Stylumia's crawler saw it — not a normalized master product, and not a merged view across retailers. Two retailers selling what is obviously the same physical item produce two independent rows, with no built-in link between them.

The identity contract

Two identifiers matter here, and they mean different things:

  • sku is the retailer's own identifier for the listing. It's unique within a retailer, and only within that retailer — the same string can mean something else at a different retailer.
  • product_id is a Stylumia content hash (prd_ followed by 24 hex characters). It identifies a listing by its content, not by a stable database row: if a retailer edits a listing's title, the next crawl mints a new product_id — the old row isn't deleted, it persists alongside the new one. Resolving which candidate is current means preferring the one with non-empty normalized attributes, then falling back to the most recent crawl_date.

This surface returns both on every row. sku is the identifier you'll filter and page by here. The product_id behavior above is documented because it's the reason the same physical listing can appear to change identity between crawls; worth knowing before you build anything that assumes a stable per-listing id over time.

Representations

The row this API returns is lean — the 17 fields in the data dictionary: product_id, sku, url, domain, retailer, department, category, brand, model_number, title, mrp, selling_price, discount_pct, currency, color, image_url, crawl_date. There is no separate "full detail" call on this generic surface — what you see in /v1/catalog and /v1/sample is everything there is.

Price is three fields, not one: mrp is the list price, selling_price is what was actually charged at capture time, and discount_pct is derived from the two. There is no single price field.

Field coverage

Not every field is populated for every row. Published up front, so you can design around it instead of discovering it in production:

Field group Coverage
Ratings ~46% of rows
Seller ~68% of rows
Shipment ~1% of rows — effectively absent
Variants Not available on this surface

Read the table before you integrate and you can design around the gaps. Discover them in production and you're debugging null fields instead — or opening a support ticket about them.

crawl_date semantics

crawl_date is when Stylumia's crawler captured the row — not when the retailer last changed the listing. A row with an old crawl_date may still describe the retailer's current listing; it just means we haven't recaptured it recently. crawl_date is also what start_date/end_date filter on on every endpoint. Cadence and window depth per retailer live on Coverage & freshness — a stub today.

Example row

{
  "product_id": "prd_5741354fa5d111f0a1ce7bcc",
  "sku": "1003097550",
  "url": "https://www.homedepot.com/p/1003097550",
  "domain": "homedepot.com",
  "retailer": "home_depot",
  "department": "tools",
  "category": "power_tools",
  "brand": "DEWALT",
  "model_number": "DCD771C2",
  "title": "20V MAX Cordless Drill/Driver Kit",
  "mrp": 179.0,
  "selling_price": 139.0,
  "discount_pct": 22.3,
  "currency": "USD",
  "color": "Yellow",
  "image_url": "https://images.example.com/1003097550.jpg",
  "crawl_date": "2026-06-14"
}

View as markdown