Filters
The filter vocabulary shared by every marketplace search — names, units, and which marketplace accepts which.
Search narrows the same way everywhere. One name per concept, one unit per concept, and a marketplace either honours a filter or rejects it by name.
Every filter is optional, and filtering costs nothing extra — except brands and facets on
Amazon, which cost 2 units (see below).
The Vocabulary
| Parameter | Type | Meaning |
|---|---|---|
priceMin | number | Lowest price to return, in decimal major units (40, 10.5) |
priceMax | number | Highest price to return, same unit |
brands | string list | Brand names as the marketplace spells them: brands=Nike,Adidas |
ratingMin | number | Lowest average star rating, on the marketplace's 0–5 scale |
condition | enum | new · used · refurbished |
freeShipping | boolean | Only listings the marketplace advertises as shipping free |
inStock | boolean | Only listings the marketplace reports as purchasable now |
sort | enum | Result ordering — see below |
categoryId | string | The marketplace's own category id — see below |
facets | list | Narrowings from the result's own filter rail: facets=Sock Rise:Ankle,Color:Black |
priceMin/priceMax are in the same unit the response reports. Money.amount is decimal major units,
so priceMin=40 and a returned {"currency":"USD","amount":40} mean the same thing. Marketplaces that
want minor units convert internally; you never see cents.
A list is comma-separated over a query string and a real array over a JSON body. Both are the same request:
?brands=Nike,Adidas {"brands": ["Nike", "Adidas"]}Booleans accept true/false/1/0. freeShipping=false really means false.
Who Accepts What
| Amazon | Shopify | Walmart | Aliexpress | |
|---|---|---|---|---|
priceMin / priceMax | ✅ | ✅ | ✅ | ✅ |
categoryId | ✅ | ✅ | ✅ | ✅ |
sort | ✅ | — | ✅ | ✅ |
brands | ✅ (costs 2) | — | ✅ | — |
ratingMin | ⚠️ 4 only | ✅ | ✅ | — |
condition | — | ⚠️ no refurbished | — | — |
inStock | — | ✅ | — | — |
facets | ✅ (costs 2) | — | ✅ | — |
freeShipping is part of the shared vocabulary, but no marketplace currently served accepts it.
A dash means a 400 naming the parameter, not a quiet no-op.
The gaps are the marketplaces', not ours. Where a filter is missing it is because the marketplace has
none: AliExpress's search has no rating refinement, Shopify sells no refurbished tier (so
condition=refurbished is refused rather than folded into used — different claims) and offers no sort
at all.
Amazon's rating rail has exactly one threshold, "4 Stars & Up" — hence ratingMin=4 and a 400 for
anything else, rather than quietly answering a ratingMin=3 request with 4-and-up results.
categoryId
There is no shared category taxonomy, so the id is the marketplace's own: a browse node on Amazon
(679416011), a cat_id on Walmart (4171), a category id on AliExpress (200000345), a Standard Product
Taxonomy id on Shopify (aa-1-13-8).
Where the ids come from. Ask for them: categories lists a level of the marketplace's own
taxonomy, and browse takes what it returns. Call it with no categoryId for the top level and walk
down, or start from an id in a Product.category[].
Two cautions the endpoint pages spell out: an id is not always usable on every operation (Walmart's
search takes a bare cat_id, its browse needs the underscore chain that categories returns), and
a few levels are navigational only, marked "browsable": false.
On search it narrows a keyword query rather than replacing it, and query stays required.
To list a category with no keyword at all, use the browse operation instead, where categoryId
is required and query is rejected. Every marketplace except Shopify has it, and it takes the same
filters search does. Two things differ from search and are worth knowing before you call it:
- The id can be a different kind of thing. Walmart's
browsewants the underscore-joined chain (3944_133251_1095191_1230614_1230478), not the barecat_iditssearchtakes. - A bad id is not always an error. AliExpress returns an empty
items— it does not distinguish an unknown category from an empty one.
Facets — the Marketplace's Own Filter Rail
The typed filters above are the ones every marketplace has in common. They are a small slice of what a site actually offers: one Walmart socks search renders 25 filter groups, of which four map onto a typed parameter. The other twenty-one — Sock Rise, Sleeve Length, Fabric Material, Weather Suitability — are specific to that query. Search a laptop and they are replaced by Screen Size and RAM.
Because the rail is per-query, it is discovered rather than declared. A search response carries it:
{
"items": [ "…" ],
"facets": [
{ "id": "sock_rise", "name": "Sock Rise", "kind": "select",
"values": [ { "value": "Ankle", "name": "Ankle", "count": 412 } ] },
{ "id": "brand", "name": "Brand", "kind": "select", "maps_to": "brands",
"values": [ { "value": "Hanes", "name": "Hanes" } ] },
{ "id": "price", "name": "Price", "kind": "range", "maps_to": "priceMin", "min": 0, "max": 45 }
]
}Send a value back with facets:
curl "https://gateway.apinoa.com/v1/walmart/search?query=socks&facets=sock_rise:Ankle,color:Black" \
-H "x-api-key: $APINOA_API_KEY"maps_to names the typed filter covering the same concept, where there is one. Prefer the typed
parameter — it means the same thing on every marketplace, and facets does not.
Who Has a Rail
| Discover | Apply | Notes | |
|---|---|---|---|
| walmart | ✅ | ✅ | free both ways |
| amazon | ✅ include=facets | ✅ | discovery is 1 unit; applying is 2 — see below |
| shopify | [] | — | Shopify search has no filter rail |
| aliexpress | — | — | no rail |
An absent facets means no rail was returned. An empty one means there is no rail for this
query. Shopify reports [].
Amazon: Discovery Is 1 Unit, Applying Is 2
Two different things, and only one of them costs extra.
include=facets costs 1 unit — the same as a search without it.
brands and facets cost 2 units. cost.search is 1..2. Everything else on Amazon still
costs 1.
A label the rail does not carry is a 400 naming it, with a sample of what the rail did offer. Amazon truncates its rail, so an unmatched label is genuinely ambiguous — returning unfiltered results would hide that, and returning none would be a guess.
Sort
| Value | Meaning | Amazon | Walmart | Aliexpress |
|---|---|---|---|---|
best_match | the marketplace's own relevance | ✅ | ✅ | — |
price_asc | price, low to high | ✅ | ✅ | ✅ |
price_desc | price, high to low | ✅ | ✅ | ✅ |
newly_listed | most recently listed | ✅ | ✅ | — |
best_seller | by units sold | — | ✅ | ✅ |
avg_review | by average rating | ✅ | — | — |
The names are ours; each marketplace's own code is internal. A value a marketplace cannot do is a 400.
Examples
# under $40, four stars and up
curl "https://gateway.apinoa.com/v1/amazon/search?query=running+shoes&priceMax=40&ratingMin=4" \
-H "x-api-key: $APINOA_API_KEY"
# Nike only, rated 4+, cheapest first
curl "https://gateway.apinoa.com/v1/walmart/search?query=running+shoes&brands=Nike&ratingMin=4&sort=price_asc" \
-H "x-api-key: $APINOA_API_KEY"
# in stock, $20-$60, rated 4+
curl "https://gateway.apinoa.com/v1/shopify/search?query=wool+socks&priceMin=20&priceMax=60&ratingMin=4&inStock=true" \
-H "x-api-key: $APINOA_API_KEY"One Caveat Worth Knowing
A price bound filters the listing, and some listings carry a price range rather than a price. A
product whose variants run $28–$50 satisfies a priceMin=40 request through its $50 variant, while its
card reports the "from" price of $28.
So a few returned rows can sit just outside the band you asked for. Measured, 90–95% land inside it. If
you need a hard bound, filter the returned price yourself — the marketplaces behave this way and we
report what they return rather than hiding rows.