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 chain

Single chain detail with full online-shopping configuration: search URL templates, login URL, cookie domains, app URL schemes, and add-to-cart detection. Powers Cart's 'Shop Online' deep-link flow + WebView session bridging.

GET/v1/chains/{slug}Free
ℹ
Free + cached
Chain metadata changes infrequently (a few times a year per chain). Responses carry Cache-Control: public, max-age=300, stale-while-revalidate=600 so you can poll cheaply. Use config_updated_at to invalidate any client-side cache without a server round-trip.

What this powers

The Cart-app "Shop Online" feature is the canonical consumer of this endpoint — but the same payload is useful for any client that needs to deep-link a user into the chain's storefront. Three workflows it enables:

Per-store deep link
Use storefront_url with the store's web_external_id from Get a store to land the user on a specific store's homepage. e.g. https://www.heb.com/store/567.
Per-store search
Use search_url_template to deep-link a search query into the chain's site already scoped to the user's home store. The Cart app does this when the user taps "Shop Online" from a basket — every item opens directly to the chain's search results for that SKU at that store.
Native app handoff
ios_app_url_scheme and android_app_url_scheme let you launch the chain's native app instead of a WebView. Falls back to storefront_url when the app isn't installed.

Path parameters

NameTypeDescription
slugrequiredstringChain slug, e.g. heb, wegmans, kroger. Lowercase.

Request

Request
curl 'https://api.mainmarket.com/v1/chains/heb'

Response

200 OKjson
{
  "slug": "heb",
  "name": "HEB",
  "logo_url": "https://.../heb.png",
  "website_url": "https://www.heb.com",
  "online_shopping_enabled": true,
  "online_search_url_prefix": "https://www.heb.com/search?q=",
  "online_search_space_char": "%20",
  "online_search_url_suffix": "",
  "storefront_url": "https://www.heb.com/store/{store_id}",
  "search_url_template": "https://www.heb.com/search?q={query}&store={store_id}",
  "login_url": "https://www.heb.com/login",
  "requires_auth": false,
  "session_cookie_domains": ["www.heb.com"],
  "user_agent_override": null,
  "add_to_cart_detection_type": "url_match",
  "add_to_cart_detection_pattern": "/cart",
  "online_shopping_referral_params": "utm_source=mainmarket",
  "ios_app_url_scheme": "heb://",
  "android_app_url_scheme": "heb://",
  "config_updated_at": "2026-04-29T12:30:00Z"
}

ChainResponse fields

NameTypeDescription
slugstringURL-safe canonical chain key.
namestringHuman chain name.
logo_urlstring | nullPublic CDN logo URL (PNG, transparent background).
website_urlstring | nullMarketing site root.
online_shopping_enabledbooleanTrue when the chain has a working online-shopping deep link.
online_search_url_prefixstring | nullPrefix for a chain-wide search URL.
online_search_space_charstring | nullCharacter used in place of a literal space in the search URL (e.g. +, %20).
online_search_url_suffixstring | nullSuffix for the chain-wide search URL (often empty).
storefront_urlstring | nullPer-store landing URL with {store_id} placeholder. Uses the chain's own external id, not our canonical id.
search_url_templatestring | nullPer-store search URL with {store_id} + {query} placeholders.
login_urlstring | nullLogin page URL when the chain requires auth for prices.
requires_authbooleanTrue when prices/cart actions require a logged-in session.
session_cookie_domainsstring[]Cookie domains the session is bound to. Use to scope client-side cookie injection.
user_agent_overridestring | nullCustom UA the chain expects on its mobile/web endpoints (rarely set).
add_to_cart_detection_typestringStrategy for detecting a successful add-to-cart inside a WebView (e.g. url_match, response_body).
add_to_cart_detection_patternstringPattern to match for the detection_type.
online_shopping_referral_paramsstring | nullTracking params to append to outbound deep links.
ios_app_url_schemestring | nulliOS universal-link scheme, e.g. heb://.
android_app_url_schemestring | nullAndroid intent URL.
config_updated_attimestampLast time the row changed. Use as a cache-busting key.

Workflow: build a per-store search URL

The most common use case. Combine search_url_template with a store's web_external_id + a URL-encoded query.

Request
import httpx
from urllib.parse import quote

# Step 1: get the chain config (free, cached)
chain = httpx.get("https://api.mainmarket.com/v1/chains/heb").json()

# Step 2: get the store (free)
store = httpx.get(
    "https://api.mainmarket.com/v1/stores/8c1a4d1e-30a7-4d92-9e1c-1cb43c6f2e10"
).json()

# Step 3: build the deep link
if not chain["online_shopping_enabled"]:
    print("This chain doesn't support online shopping yet")
elif chain.get("search_url_template"):
    url = (chain["search_url_template"]
           .replace("{store_id}", store["web_external_id"])
           .replace("{query}", quote("oat milk").replace("%20", chain["online_search_space_char"] or "%20")))
    print(url)
else:
    # Fall back to chain-wide search
    url = chain["online_search_url_prefix"] + quote("oat milk")
    print(url)

Auth-required chains

About a third of chains require a logged-in session before exposing prices in their storefront. The relevant fields:

requires_auth = true
The chain's site won't show prices to anonymous visitors. Send the user to login_url first, then the storefront URL after a successful login. Cart's WebView reuses the login session via session_cookie_domains.
session_cookie_domains
List of cookie domains the auth session is bound to. When you bridge a session from one WebView to another (e.g. login WebView → shopping WebView), copy cookies for these domains and only these domains.
user_agent_override
Some chains gate their pricing on UA fingerprint (typically expecting a mobile browser UA). Apply this UA on the WebView before navigating; rare but critical when set.
ℹ
Kroger has a dedicated OAuth path
Kroger and the Kroger family banners (Ralphs, Fred Meyer, etc.) use a true OAuth 2.0 flow rather than cookie-bridged login. The /v1/kroger/oauth/* routes (internal-only, Cart app) handle the authorize → exchange → refresh dance and persist tokens server-side.

Caching strategy

  • config_updated_at is a server-side timestamp that bumps on any field change. Use it as a cache-busting key client-side: re-fetch only when the timestamp moves forward.
  • The endpoint sends Cache-Control: public, max-age=300, stale-while-revalidate=600. Browsers and CDN edges respect that automatically.
  • For mobile clients with their own cache, persist the chain payload by slug and refresh once per session — fields rarely change between user-active windows.

Notable behavior

  • Slugs are case-insensitive on input but always returned lowercase. The slug is the public identifier; the internal UUID isn't exposed via this route.
  • requires_auth=true chains (Kroger, H-E-B pricing, Albertsons, some Wakefern) need a logged-in session for prices. Use /v1/chains/kroger/oauth/... for Kroger-specific flows (internal Cart only — not part of the public B2B surface).
  • online_shopping_enabled = false chains expose only the bare metadata (name, logo, website). Hide the "Shop Online" button entirely in your UI for those — there's no useful URL to deep-link to.
  • add_to_cart_detection_* fields tell a WebView host how to detect a successful add-to-cart event, which is how Cart fires its "added to your<chain> cart" toast. Three detection types in use today: url_match (URL contains pattern), response_body (body matches regex), dom_match (selector appears in DOM).

Related

  • List chains — browse every chain by enabled status, market position, or geo footprint.
  • Chain aisles — chain-wide aisle vocabulary, useful when a specific store has low coverage.
  • Resolve a list — bulk per-chain shopping-list resolution. Pulls the chain's PDP URL pattern from this endpoint internally.

Errors

NameTypeDescription
404Not FoundSlug is not a known chain.
500Internal Server ErrorUnexpected server fault.