Pull current shelf prices for one or more products at a specific store. The standard pattern for shopping apps, basket-pricing flows, and store-detail pages. Returns a tier-aware row per (store, product) pair so you always know whether the price came from this exact store, a sibling, or a chain fallback.
/v1/prices?store_id={id}$0.01source_tier field tells you which path was taken — see "Tiered fallback" below.Every /v1/prices call needs at least one parameter from each side. For this workflow:
| Name | Type | Description |
|---|---|---|
store_id | uuid | Single canonical store id. Triggers tier resolution if the store has no own scrape. |
store_ids | string | Comma-separated UUIDs. Each one is resolved independently — useful for comparing 2-3 nearby stores in one call. |
| Name | Type | Description |
|---|---|---|
q | string | Trigram text search on product name + brand. Best when the user typed a query. |
barcode | string | UPC or EAN, 6-32 digits. |
product_id | uuid | Single canonical product UUID. |
product_ids | string | Comma-separated UUIDs (cap 50). The basket-pricing path: hydrate every item in a shopping list with one call. |
curl 'https://api.mainmarket.com/v1/prices?store_id=8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10&barcode=00016000275287' \
-H "Authorization: Bearer mm_live_..."The basket-pricing pattern. Pass up to 50 product UUIDs in one call to avoid N+1 round-trips. Each row is tier-aware, so you know which items have specific prices vs. fallback estimates.
curl 'https://api.mainmarket.com/v1/prices?store_id=4f2a...&product_ids=9d4e...,a1b2...,c3d4...&limit=50' \
-H "Authorization: Bearer mm_live_..."Pass store_ids with a comma-separated list. The response includes per-store rows so you can show a side-by-side price comparison.
curl 'https://api.mainmarket.com/v1/prices?store_ids=8c1a...,ee44...,ff55...&product_id=9d4e...&limit=10' \
-H "Authorization: Bearer mm_live_..."{
"count": 3,
"results": [
{
"product_id": "9d4e1c80-78a3-4a6d-9b1f-2cdb3d0c7e90",
"name": "Cheerios Cereal, 18 oz",
"brand": "Cheerios",
"upc": "00016000275287",
"store_id": "8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10",
"store_name": "Wegmans Brooklyn",
"chain_slug": "wegmans",
"price": 4.99,
"regular_price": 5.49,
"sale_price": 4.99,
"is_on_sale": true,
"unit_price": 0.28,
"unit_price_uom": "oz",
"aisle": "Aisle 4",
"section": "Cereal",
"available": true,
"source_store_id": "8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10",
"source_store_name": "Wegmans Brooklyn",
"source_tier": "specific",
"source_distance_mi": 0.0,
"pricing_scope": "per_store"
}
]
}The most important field on a store-scoped query is source_tier. Treat each value differently:
specificsource_distance_mi = 0.regionalchainpricing_scope = "chain_level" (Lidl, Trader Joe's, Aldi); a directional estimate for per_store chains. Always disclose the tier in your UI.source_tier = "specific" before sorting by price. Mixing tiers produces phantom "cheapest" results that aren't actually purchasable at the named store.store_id_redirects automatically — you'll get prices for the right store with no special handling.?normalize_aisles=true to get the aisle in the same vocabulary as /v1/stores/{id}/aisles — useful for in-store route planning.| Name | Type | Description |
|---|---|---|
422 | Unprocessable Entity | Missing product or store filter, malformed UUID, or store_ids over 50. |
402 | Payment Required | Paid route — no payment proof. |
aisle field for in-store routing.