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

API Reference

Every public route in the MainMarket API. Discovery endpoints (stores, chains) are free; data endpoints (prices, products, coupons, indices) are $0.01 per call, settled via x402 wallet payment, internal token, or B2B API key.

All routes live under https://api.mainmarket.com and return JSON. See Authentication for how requests are charged and openapi.json for the machine-readable spec.

Free routes

Discovery routes return store and chain metadata. No payment, no token. CDN-cached for 60 seconds. Use them to build a search interface or pre-flight a paid call.

MethodPathReference
GET/v1/storesList stores
GET/v1/stores/{id}Get a store
GET/v1/stores/{id}?include=places_enrichmentStore sentiment & enrichment
GET/v1/chainsList chains
GET/v1/chains/{slug}Get a chain
GET/healthHealth + discovery routes

Paid routes ($0.01)

Data routes return live shelf prices, coupons, aisle layouts, list resolutions, and published indices. Each successful response (HTTP 200) deducts one cent from the configured payment source. Errors (4xx / 5xx) are not charged.

MethodPathReference
GET/v1/productsCatalog search
GET/v1/products?product_id=...Get a product
GET/v1/products/{id}/couponsCoupons for product
GET/v1/pricesSearch prices
GET/v1/couponsList coupons
GET/v1/coupons/{id}Get a coupon
GET/v1/coupons/{id}/savingsCoupon savings
GET/v1/stores/{id}/couponsStore coupons
GET/v1/stores/{id}/aislesStore aisles
GET/v1/chains/{slug}/aislesChain aisles
POST/v1/chains/{slug}/resolve-listResolve a list
GET/v1/indices/{slug}Published indices

Error responses

All errors return a JSON body of the form { "detail": <string|object> } with an appropriate HTTP status code. Pydantic validation errors (422) include a structured detail array pointing at the offending field.

CodeNameWhen you'll see it
200OKSuccessful response. Body matches the documented schema for the route.
304Not ModifiedReturned by /v1/coupons when the client's If-None-Match header matches the current ETag. No body.
400Bad RequestMalformed query parameter (e.g. lat/lng outside valid range, slug not lowercase).
401UnauthorizedMissing or invalid Authorization header on an internal or B2B route.
402Payment RequiredPaid route called without payment proof (x402 wallet header, internal token, or B2B key).
404Not Foundstore_id, coupon_id, or index slug does not exist.
422Unprocessable EntityPydantic validation failure — wrong type, missing required filter, period not 'YYYY-MM'.
429Too Many RequestsRate limit exceeded. Future. Not enforced in v1.
500Internal Server ErrorUnexpected server fault. Retry with exponential backoff; report persistent occurrences.
503Service UnavailableReturned by /health when the database ping fails. Indicates upstream Postgres or pooler issue.

Example error body

422 Unprocessable Entityjson
{
  "detail": "Provide at least one filter (q, barcode, product_id, product_ids, store_id, store_ids, chain, metro, state, or near)"
}

Conventions

  • All timestamps are ISO-8601 UTC. All monetary values are USD floats unless a unit is attached (e.g. unit_price_uom = "oz").
  • Collection responses are wrapped as { count, results } or { data, meta } — they never return bare arrays.
  • UUIDs are returned as canonical 36-character strings. Soft-deleted store ids are transparently resolved to their canonical survivor.
  • Cache headers (Cache-Control, ETag) are honored where present. The /v1/coupons route supports If-None-Match for 304 short-circuits.