How a Fashion Product Data API Lets Apps Show Only the Sizes That Are Actually In Stock
A fashion product data API can return clothing at the size level, and that is what lets an app show shoppers only the sizes they can actually buy. Choosing a size, tapping add to bag, and finding out it is gone is one of the quickest ways to lose a shopper's trust. The fix starts in the data, before any interface work.
Affiliate.com's normalized product data covers more than 30 networks and over a billion products, and for most clothing it is organized one record per size, each with its own availability. This article uses real records to show how that works, where merchants differ in what they report, how to group sizes into one product page, and how to avoid common mistakes such as sorting sizes alphabetically. The examples were pulled on October 5, 2026, and stock changes constantly, so treat every number as a snapshot.
The Core Idea: One Record Per Size
Take a real shirt. At one large retailer, a black linen-blend shirt appeared as seven separate records, one for each size the merchant lists. Each record carried its own availability:
| Size | Availability | Price (USD) |
|---|---|---|
| 2 | InStock | 39.99 |
| 4 | InStock | 39.99 |
| 6 | InStock | 39.99 |
| 8 | OutOfStock | 39.99 |
| 10 | InStock | 39.99 |
| 12 | OutOfStock | 39.99 |
| 14 | InStock | 39.99 |
Five sizes can be bought and two cannot. An app that reads this correctly shows sizes 2, 4, 6, 10, and 14 as selectable and 8 and 12 as unavailable. An app that only looks at the style would see "linen shirt, black, 39.99" and imply that every size is available.
Each record also has its own SKU and, at many merchants, its own barcode. That matters because a barcode identifies a single size, not the whole style.
Not Every Merchant Reports Sold-Out Sizes
This is the most important behavior to design for. In a sample of 6,024 women's linen shirts priced between 30 and 60 USD, 46 merchants had in-stock records. Only 11 of them had any out-of-stock records at all. The other 35 appear to list only the sizes they currently have, so a sold-out size is simply missing from the data. A single merchant accounted for 2,129 of the sample's 2,694 out-of-stock records.
That gives you two patterns:
- Merchants that list sold-out sizes. You see the size with an availability of OutOfStock, so you can show it greyed out.
- Merchants that drop sold-out sizes. The size is absent. It may be sold out, or it may never have been offered, and the data cannot tell you which.
For a size selector, the safe rule is to show a size as available only when a record for it exists and its availability is InStock. If you want to show a full size run with some greyed out, build the list of standard sizes yourself and mark anything without an in-stock record as unavailable. Do not assume a missing size is sold out and do not assume it is available.
Grouping Size Records Into One Product
The data does not hand you a ready-made style grouping, so the app builds one. The right key depends on the merchant, and the examples show why no single field works everywhere.
| Possible key | What we saw |
|---|---|
| Product link | At one merchant, every size of a product shared the same product ID in the link path. This was the most reliable key. |
| MPN | At another merchant, one style number was shared by 13 records. But at a third, the same MPN appeared on both a standard and a plus-size version of a shirt, so MPN alone would merge two different products. |
| SKU or barcode | Unique to each size record, so these identify a size and cannot group a style. |
| Name, color, and merchant | A reasonable fallback when no link ID is available, though names can vary. |
Two further wrinkles came up. First, the product ID sits in the link path for some merchants and in a query parameter for others, so the extraction logic has to be written per merchant. Second, one style had 13 records but only six size labels. The size "M" appeared three times, each under a different variant code in the link. The data does not say what the variants mean, which may be fit or length options, so check the merchant page before deciding how to present them.
The merchantRule function is yours: a small lookup that says which extractor applies to which merchant.
The Fields That Decide Whether a Size Is Shown
Availability is the field to use. It returns InStock, OutOfStock, or Unknown. In the sample, 53.4% of records were InStock, 44.7% were OutOfStock, and 1.9% were Unknown.
The in-stock flag is a trap. Filtering on it returned exactly the same 3,218 records as filtering on InStock availability. But on a record we inspected, the in-stock value in the response was empty even though availability said InStock. Filter on availability, and read availability when you display a size.
Stock quantity was empty on every record in the sample and on every record we inspected here. A "only 2 left" message cannot rest on it.
Updated timestamp tells you how recent a record is. In the sample, 99.4% of records had been updated within the previous day and 90.6% had been updated on the same day. That is frequent, and it is the reason to refresh a product when a shopper opens it, not only when the catalog syncs. The freshness fields explain how to use the timestamp alongside availability, and the difference between updated and added dates is worth understanding before you rely on either.
Price per size. In both examples every size shared one price. Since each size is its own record, a merchant could price them differently, so read the price from the record the shopper selects.
Building the Size Selector
A practical sequence:
- Fetch all size records for the product. Search by the product ID in the link, with no availability filter, so unavailable sizes come back too.
- Group and label. Group the records, then label each size available, unavailable, or unconfirmed based on its availability.
- Sort sizes yourself. Sorting by the size field sorts as text, so the seven sizes above came back as 10, 12, 14, 2, 4, 6, 8. Put them in a sensible order in the app, such as XS to XXL for letter sizes and ascending order for numbers.
- Hide a product with no available sizes. A plus-size version of the same shirt had five sizes, 14 through 22, and all five were out of stock. Showing that product with an empty selector is worse than not showing it.
- Pick a sensible default. Preselect the shopper's saved size if it is available. If not, leave nothing selected and say why.
A request to fetch a full size run for one product looks like this:
{
"search": [
{ "field": "merchant.id", "value": "128518", "operator": "=" },
{ "field": "direct_url", "value": "209714909", "operator": "LIKE" }
],
"fields": ["id", "name", "size", "color", "availability", "final_price", "currency", "sku", "direct_url", "updated_at"],
"per_page": 50
}
For a browse view that should show only items available in the shopper's size, add the filters instead:
{
"search": [
{ "field": "any", "value": "linen shirt", "operator": "LIKE" },
{ "field": "gender", "value": "women", "operator": "LIKE" },
{ "field": "size", "value": "M", "operator": "LIKE" },
{ "field": "availability", "value": "InStock", "operator": "=" },
{ "field": "currency", "value": "USD", "operator": "=" }
],
"per_page": 24
}
Remember that size matching works on whole values, so "M" also returns "S/M" and a lowercase "m". Decide in the app whether a combined size counts as the shopper's size.
Handling Unknown and Missing Values
Treat Unknown availability as unconfirmed. Show it with a "check availability" state or leave it out, but do not present it as ready to buy. Handle the missing-size case as described above, and handle a missing stock quantity by simply not showing one.
The same care applies on sale pages. Discount filters that check stock keep a markdown rail from promoting sizes that are gone, and validating stock alongside identifiers and offers is a good habit for anything that sends a shopper to a merchant.
Telling Shoppers When Their Size Returns
If a shopper's size is sold out, the Product Watches API can monitor that specific size record for a change in availability and send a webhook notification. Watches are checked every 6 hours, so describe the alert as "we'll let you know when it's back," not as instant. The next article in this series covers watches in detail.
A Checklist
- Filter on availability equal to InStock for any view that sells directly.
- Show a size as available only when its record exists and says InStock.
- Group size records per merchant, using the product ID from the link where possible.
- Sort sizes in your own code, never by the size text.
- Hide a product when no size is available.
- Treat Unknown as unconfirmed and never rely on stock quantity.
- Refresh a product's records when a shopper opens it, and confirm stock on the merchant's page before any promotion that depends on it.
See It in the Query Builder
Open the Affiliate.com Query Builder, search a clothing brand, and pick one style. Filter by the product ID from its link to see every size record, then turn the availability filter on and off. The difference is exactly the gap between a size selector built on stock data and one that is not.
A few notes on this draft, outside the article:
- What changed from my first draft.
- My first outline said grouping sizes by name, brand, color, and merchant was the usual key. The real records showed the product link is more reliable, and MPN can merge different products.
- I had not known that 35 of 46 merchants drop sold-out sizes instead of marking them out of stock. That is now a section of its own.
- I added the alphabetical sort problem and the empty in-stock flag, both new.
- Something to patch in article 2. Its availability section says nearly half the sample was out of stock, which is true. But one merchant accounts for 2,129 of those 2,694 records, so the number is driven by a single merchant's feed and does not describe retailers in general. I can add that nuance to article 2 if you want it.
- Possible data issue. The 13-record example came from a Canadian storefront whose records were labeled USD. I haven't confirmed the currency is wrong, but it is worth checking on your side. I left that storefront unnamed in the article.
- Naming: the ASOS shirt is described as "one large retailer" in the prose and only appears by merchant ID in the request example, so no retailer is named in the text. If you would rather include names, say so.