MainMarketAPI Reference
Get Access
Overview
  • Introduction
  • Authentication
  • Errors
Stores
  • List stores
  • Get a store
  • Store sentiment
  • Store coupons
  • Store aisles
Chains
  • List chains
  • Get a chain
  • Chain aisles
  • Resolve a list
Products
  • Catalog search
  • Get a product
  • Coupons for product
Prices
  • Search prices
  • Prices by UPC
  • Prices at a store
  • Cheapest nearby
Coupons
  • List coupons
  • Get a coupon
  • Coupon savings
Indices
  • Published indices
Discovery & meta
  • Discovery routes
  • OpenAPI spec
  • Agent skill spec
Overview
  • Introduction
  • Authentication
  • Errors
Stores
  • List stores
  • Get a store
  • Store sentiment
  • Store coupons
  • Store aisles
Chains
  • List chains
  • Get a chain
  • Chain aisles
  • Resolve a list
Products
  • Catalog search
  • Get a product
  • Coupons for product
Prices
  • Search prices
  • Prices by UPC
  • Prices at a store
  • Cheapest nearby
Coupons
  • List coupons
  • Get a coupon
  • Coupon savings
Indices
  • Published indices
Discovery & meta
  • Discovery routes
  • OpenAPI spec
  • Agent skill spec

Get a store

Fetch a single store by canonical id, with three opt-in expansions: chain online-shopping config, weekly hours, and SerpAPI / GPT place enrichment (rating, sentiment, popular times). The store-detail page primary endpoint.

GET/v1/stores/{store_id}Free
ℹ
Free, ID-resilient, expand on demand
Free route — no auth, no payment, CDN-cached for 5 minutes. Soft-deleted dup ids from the 2026-04-25 dedup pass are auto-resolved to their canonical survivor. Default response stays minimal; pass ?include=... to opt into the nested expansions you actually need.

Path parameters

NameTypeDescription
store_idrequireduuidCanonical store id from GET /v1/stores. Soft-deleted dup ids resolve transparently to their canonical survivor.

Query parameters

NameTypeDescription
includestringComma-separated opt-in fields: chain_online_config, hours, places_enrichment. Each adds a nested object on the response. Combine freely, e.g. ?include=chain_online_config,hours,places_enrichment.

The three expansions

chain_online_config
Adds a nested chain object with the same shape as Get a chain: search URL templates, login URL, native app URL schemes, add-to-cart detection pattern. Use this on a Store Detail screen so a single round-trip gets you everything needed for the "Shop Online" button.
hours
Adds a nested hours array: 0-7 rows per store with day_of_week (0 = Sunday), open_time, close_time in 24h format. A store closed on a given day omits that row entirely — never assume seven entries.
places_enrichment
Adds a nested places object: Google rating, review count, weekly busyness histogram (popular_times), highlights, GPT-generated shopper sentiment with 5 grounded axes. Returns null for stores not yet seeded (most stores today — only the Brooklyn pilot is fully enriched). See Store sentiment for the full place-data spec.
ℹ
Stale ids resolve automatically
After the 2026-04-25 store dedup pass, ids of merged loser rows now 404 — except when accessed through this endpoint, which looks them up in store_id_redirects and returns the surviving canonical row. Cache the returned id to avoid the redirect on subsequent calls.

Request

Request
curl 'https://api.mainmarket.com/v1/stores/8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10?include=hours,places_enrichment'

Response

200 OKjson
{
  "id": "8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10",
  "name": "Wegmans Brooklyn",
  "display_name": "Wegmans Brooklyn",
  "banner_name": "Wegmans",
  "web_external_id": "59",
  "chain_name": "Wegmans",
  "chain_slug": "wegmans",
  "chain_logo_url": "https://.../wegmans.png",
  "address": "21 Flushing Ave",
  "city": "Brooklyn",
  "state": "NY",
  "zip": "11205",
  "lat": 40.6982,
  "lng": -73.9772,
  "metro": "nyc",
  "borough": "brooklyn",
  "format": "supermarket",
  "has_pickup": true,
  "has_delivery": true,
  "is_active": true,
  "hours": [
    { "day_of_week": 0, "open_time": "06:00", "close_time": "00:00" },
    { "day_of_week": 1, "open_time": "06:00", "close_time": "00:00" }
  ]
}

Field reference

Same StoreResponse shape as GET /v1/stores (single object, not wrapped). See List stores for the full field reference.

Workflow: Store Detail screen

The "all-in-one" call powering a typical store-detail page. One free round-trip gets every piece of metadata you need to render headers, hours, deep-links, and sentiment.

Request
import httpx

store_id = "8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10"
r = httpx.get(
    f"https://api.mainmarket.com/v1/stores/{store_id}",
    params={"include": "chain_online_config,hours,places_enrichment"},
).json()

# Cache-busting check: returned id may differ if we resolved a stale dup id
if r["id"] != store_id:
    print(f"Note: id was redeemed — update your cache: {store_id} → {r['id']}")

# Header
print(f"{r['name']}  ({r['chain_name']})")
print(f"{r['address']}, {r['city']}, {r['state']} {r['zip']}")

# Hours
if r.get("hours"):
    days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
    for h in r["hours"]:
        print(f"  {days[h['day_of_week']]}  {h['open_time']} - {h['close_time']}")

# Sentiment (only present for seeded stores)
if r.get("places", {}).get("sentiment"):
    s = r["places"]["sentiment"]
    print(f"\nSentiment: {s['score']}/100 — {s['label']}")
    print(s["summary"])

# Deep link
chain = r.get("chain") or {}
if chain.get("online_shopping_enabled") and chain.get("storefront_url"):
    deep_link = chain["storefront_url"].replace("{store_id}", r["web_external_id"])
    print(f"\nShop Online: {deep_link}")

The dedup-redirect dance

On 2026-04-25 we collapsed ~3,000 duplicate store rows into their canonical survivors. Pre-existing client caches still hold the loser ids. This endpoint handles that gracefully:

Loser ids redirect transparently
When you call GET /v1/stores/<loser_id>, the endpoint looks up store_id_redirects, resolves to the canonical id, and returns the canonical row. Returned id may differ from the requested id.
Detection signal for clients
Compare response.id to the id you sent. When they differ, a redirect happened — update your local cache to the canonical id so subsequent calls skip the redirect (small but real perf win at scale).
Other endpoints don't redirect
Only GET /v1/stores/{id}, /v1/stores/{id}/aisles, and /v1/stores/{id}/coupons resolve loser ids. Other endpoints (e.g. /v1/prices?store_id=...) 404 on a stale id. Use this endpoint as a one-time migration step.

Notable behavior

  • Soft-deleted dedup losers resolve to the canonical survivor. The returned id may differ from the requested id; refresh your client cache when this happens.
  • Hours day_of_week is 0-indexed Sunday. 0 = Sunday, 6 = Saturday. A store closed on a given day omits that row entirely — do not assume seven entries.
  • places is null for most stores. Only the 26-store Brooklyn pilot is fully seeded today. Production seed pending (~$150 SerpAPI cost for ~11.5k chain-active stores). Always null-check before rendering sentiment / popular times.
  • Default response is byte-stable for clients without includes. A bare GET /v1/stores/{id} returns exactly the same shape it did before the include token expanded — no new fields silently appearing in existing client responses.

Caching

Store metadata changes infrequently. Responses send Cache-Control: public, max-age=300, stale-while-revalidate=600 — a 5-minute cache that's CDN-shareable. Browser and edge caches respect that automatically. The id-redirect path is also cached, so repeat calls with the same loser id are still fast.

Related

  • List stores — geo-search to find a store_id in the first place. Same field shape, just wrapped in a list.
  • Store sentiment — focused deep-dive on the places expansion (sentiment axes, popular times, highlights).
  • Store aisles — frequency-ranked aisle vocabulary for in-store routing.
  • Store coupons — every active coupon valid at this store.

Errors

NameTypeDescription
404Not Foundstore_id is not a known canonical or redirect id.
422Unprocessable Entitystore_id is not a valid UUID, or include= contains an unknown key.
500Internal Server ErrorUnexpected server fault.