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:
skuis 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_idis 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 newproduct_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 recentcrawl_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"
}