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.
/v1/chains/{slug}FreeCache-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.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:
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.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.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.| Name | Type | Description |
|---|---|---|
slugrequired | string | Chain slug, e.g. heb, wegmans, kroger. Lowercase. |
curl 'https://api.mainmarket.com/v1/chains/heb'{
"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"
}| Name | Type | Description |
|---|---|---|
slug | string | URL-safe canonical chain key. |
name | string | Human chain name. |
logo_url | string | null | Public CDN logo URL (PNG, transparent background). |
website_url | string | null | Marketing site root. |
online_shopping_enabled | boolean | True when the chain has a working online-shopping deep link. |
online_search_url_prefix | string | null | Prefix for a chain-wide search URL. |
online_search_space_char | string | null | Character used in place of a literal space in the search URL (e.g. +, %20). |
online_search_url_suffix | string | null | Suffix for the chain-wide search URL (often empty). |
storefront_url | string | null | Per-store landing URL with {store_id} placeholder. Uses the chain's own external id, not our canonical id. |
search_url_template | string | null | Per-store search URL with {store_id} + {query} placeholders. |
login_url | string | null | Login page URL when the chain requires auth for prices. |
requires_auth | boolean | True when prices/cart actions require a logged-in session. |
session_cookie_domains | string[] | Cookie domains the session is bound to. Use to scope client-side cookie injection. |
user_agent_override | string | null | Custom UA the chain expects on its mobile/web endpoints (rarely set). |
add_to_cart_detection_type | string | Strategy for detecting a successful add-to-cart inside a WebView (e.g. url_match, response_body). |
add_to_cart_detection_pattern | string | Pattern to match for the detection_type. |
online_shopping_referral_params | string | null | Tracking params to append to outbound deep links. |
ios_app_url_scheme | string | null | iOS universal-link scheme, e.g. heb://. |
android_app_url_scheme | string | null | Android intent URL. |
config_updated_at | timestamp | Last time the row changed. Use as a cache-busting key. |
The most common use case. Combine search_url_template with a store's web_external_id + a URL-encoded query.
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)About a third of chains require a logged-in session before exposing prices in their storefront. The relevant fields:
requires_auth = truelogin_url first, then the storefront URL after a successful login. Cart's WebView reuses the login session via session_cookie_domains.session_cookie_domainsuser_agent_override/v1/kroger/oauth/* routes (internal-only, Cart app) handle the authorize → exchange → refresh dance and persist tokens server-side.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.Cache-Control: public, max-age=300, stale-while-revalidate=600. Browsers and CDN edges respect that automatically.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).| Name | Type | Description |
|---|---|---|
404 | Not Found | Slug is not a known chain. |
500 | Internal Server Error | Unexpected server fault. |