Skip to content

Shop listing flow ​

The listing page has two display states — all items and filtered items — and two independent ways to move between them: search and filters. Both states come from the same endpoints; what changes is the body and query you send.

Stages ​

Same thing as a flow, if that reads better for the spec:

API calls by stage ​

StageActionAPI callAuth
1All itemsPOST /api/v1/mobile/tags-catalog — payload with the buckets to fetch; limit/offset, sortItem + sortType as query params. Guest mount: /mobile/open/tags-catalogCustomer or Brand
1Build the filter UI's optionsGET /api/v1/mobile/master-data/brand/category-brandname — "the facet values (categories + brand names) available for the token's brand"; GET /api/v1/mobile/master-data for the wider setBrand
2SearchPOST /api/v1/brand/mobile/search?query=… — Typesense. The term is a query param, not part of the body; options.page / options.per_page paginateBrand
2Search, the other waysearch is also a query param on tags-catalog and filter-catalog. Two different engines — pick one per screen, deliberatelyCustomer or Brand
2Apply filterPOST /api/v1/mobile/filter-catalog — payload is an array of { filterColumn, filterValue }; or the facet_* keys on the Typesense search's filtersBrand
1 ↔ 2Cancel search / Clear filterNo dedicated call — re-issue the stage 1 request without the search param or the filter bodyCustomer or Brand
→ detailTap a cardGET /api/v1/mobile/getproduct/:slug — see the purchase flowBrand

Live stock depends on the token, not the request ​

with_inventory defaults to true on the Typesense search, and with_inventory: true plus a hubId + roomId on the token routes the search to the hub-product collection (live stock). Without them it hits the global product collection. The same hubId / roomId pair is accepted as a query-param override on the catalogue endpoints, but only when the token doesn't already carry it — so which store's stock a shopper sees is a property of the mobile key they were issued.

Two filter vocabularies ​

The Typesense filters object accepts a legacy shape (category, subCategory, brandName, tags) and a newer facet_* shape (facet_categories, facet_sub_categories, …). They normalise to the same thing server-side; the API docs say to prefer facet_* for new work. negate_filters takes the same keys to exclude rather than include.

Paths ​

Search Shop Listing Page → all items → search → filtered items

Cancel search Shop Listing Page → filtered items → cancel search → all items

Apply filter Shop Listing Page → all items → apply filter → filtered items

Clear filter Shop Listing Page → filtered items → clear filter → all items

Open questions ​

  • Search and filter are drawn here as producing the same "filtered items" state, but they're separate mechanisms. What happens when both are active? Three cases worth pinning down:

    • Search while a filter is applied — does search run within the filtered set, or reset the filter?
    • "Cancel search" while a filter is applied — back to all items, or back to filtered-only?
    • "Clear filter" while a search is active — same question in reverse.

    If they're meant to compose, the states are really all / search only / filter only / both, and each clear action only removes its own layer. Worth deciding before build. The API composes cleanly either way: on the Typesense search, query and filters are independent inputs to one call, so "both active" is a single request — as long as the client keeps the two pieces of state separately and always sends the full picture.

  • Zero results: no path defined for either search or filter. Both endpoints answer with the normal { success: true, result: … } envelope and an empty set, so it is a UI state, not an error branch.

  • Where does the filter live — a bottom sheet, a side panel, a separate screen? "Apply filter" implies a surface with its own open/cancel actions that isn't in the flow yet.

  • Are filters persisted when leaving and returning to the listing page? Nothing server-side holds them; that is client state.

  • No tap-into-item path yet — presumably listing → item detail. Now captured in the purchase flow.

  • tags-catalog returns a keyed object of tag buckets unless unified_res=true flattens it to one intersected list. Which shape the listing page wants decides whether the screen is one list or several rails.

Batch platform, Shopify app and API documentation