Custom Listing
Custom Listing lets you build your own catalog, category, and search experience while using Hubble's store APIs for the underlying brand data. This is useful when you want full control over the listing experience but still need Hubble to handle brand availability, discounts, ranking, suggestions, trending searches, and recent searches.
Use this approach when your app needs a native catalog screen, custom filters, personalized search entry points, or a storefront listing that should match your product experience more closely. Brand detail, payment, and purchase flows can still open in Hubble SDK screens.
How It Works
Your app calls Hubble's public store search APIs and renders the results in your own UI:
- Show discovery prompts with trending searches.
- Fetch autocomplete options from suggestions as the user types.
- Fetch brands from search using keyword, category, brand, tag, discount, or pagination filters.
- Show recent searches for authenticated users so they can quickly resume previous discovery journeys.
- Use the returned brand identifiers to open the brand detail or purchase flow in the SDK.
The search API only returns brands that are applicable for the current client and user context. Discount and reward fields are also resolved from the same store configuration used by the SDK.
Search Brands
/v3/store/products/searchReturns brand listing sections for catalog pages, keyword search, category pages, filtered lists, and paginated all-brand lists.
Query Parameters
All parameters are optional. Combine only the filters needed for your screen.
| Parameter | Type | Description |
|---|---|---|
q | string | Keyword search across brand titles, categories, tags, and search keywords |
category | string or string[] | Category filter. A single category returns one listing section; multiple categories return one section per category |
tags | string or string[] | Filters already-returned products by display/filter tags |
brandKey | string or string[] | Fetches specific brands by brand key, preserving the requested order where possible |
discountPercentage | number | Returns brands with the exact discount percentage |
discountPercentage_gt | number | Returns brands with a discount percentage greater than the value |
pageNo | integer | Page number for all-brand pagination. Starts from 0 |
limit | integer | Page size for all-brand pagination. Defaults to 10 when pageNo is supplied |
Request Headers
Search, suggestions, and trending searches are public store endpoints. They do not require bearer authentication, but they do require client context.
| Header | Required | Description |
|---|---|---|
X-CLIENT-ID | Yes | Your Hubble client ID. If omitted, store-service defaults to the hubble client. |
X-USER-ID | No | User identifier. Send this only when the request should use user-specific context. |
X-Request-Id | Recommended | Unique request identifier for tracing and support. |
Example Request
curl "https://api.dev.myhubble.money/v3/store/products/search?q=food" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-Request-Id: $(uuidgen)"
Example Response
{
"nextCursor": null,
"data": [
{
"sectionName": "MAIN_PRODUCTS",
"products": [
{
"id": "01GMAW822RPDJ5C50XK24QC2C4",
"type": "VOUCHER",
"brandKey": "zomato",
"displayTags": ["Food Delivery"],
"category": "FOOD",
"tags": ["Food", "Restaurants"],
"voucherProduct": {
"title": "Zomato",
"backgroundImageUrl": "https://assets.myhubble.money/...",
"logoUrl": "https://assets.myhubble.money/...",
"sqLogoUrl": "https://assets.myhubble.money/...",
"cardBackgroundColor": "#FFFFFF",
"discountPercentage": 5,
"rewardType": "PERCENTAGE",
"rewardDetails": [
{
"discountPercentage": 5,
"rewardType": "PERCENTAGE"
}
],
"isLandingPageAvailable": true,
"status": "ACTIVE"
}
}
]
},
{
"sectionName": "OTHER_RELATED_PRODUCTS",
"products": []
}
]
}
Pagination Example
Use pageNo and limit when you want an all-brand listing instead of a keyword or category result.
curl "https://api.dev.myhubble.money/v3/store/products/search?pageNo=0&limit=20" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-Request-Id: $(uuidgen)"
{
"nextCursor": {
"pageNo": 1,
"limit": 20
},
"data": [
{
"sectionName": "MAIN_PRODUCTS",
"products": []
}
]
}
Keyword searches can return both MAIN_PRODUCTS and OTHER_RELATED_PRODUCTS. Render the main section first, then show related brands as a secondary section if present.
When X-USER-ID is present, keyword searches and single-category searches are saved as recent searches when they return main products. You do not need to call a separate tracking endpoint.
Search Suggestions
/v3/store/products/suggestionsReturns autocomplete suggestions while the user types. Suggestions can include matching categories, brands, and search keywords.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search text entered by the user |
Example Request
curl "https://api.dev.myhubble.money/v3/store/products/suggestions?q=piz" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-Request-Id: $(uuidgen)"
Example Response
{
"categories": [
{
"id": "01H_CATEGORY_ID",
"name": "FOOD",
"title": "Food",
"logoUrl": "https://assets.myhubble.money/...",
"brandLogoUrls": [
"https://assets.myhubble.money/...",
"https://assets.myhubble.money/..."
],
"brandCount": 24
}
],
"brands": [
{
"id": "01GMAW822RPDJ5C50XK24QC2C4",
"name": "Pizza Hut",
"sqLogoUrl": "https://assets.myhubble.money/...",
"percentage": 5
}
],
"keywords": ["pizza", "pizza night"]
}
Suggestion responses are optimized for discovery UI. Use the selected category, brand key, or keyword to call /v3/store/products/search and render the final listing.
Trending Searches
/v3/store/products/trending-searchesReturns popular search prompts that you can show before the user starts typing.
Example Request
curl "https://api.dev.myhubble.money/v3/store/products/trending-searches" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-Request-Id: $(uuidgen)"
Example Response
{
"searches": ["food", "fashion", "travel", "electronics"]
}
Recent Searches
/v3/store/products/recent-searchesReturns the user's recent keyword and category searches, along with preview brands for each search. This endpoint requires user context.
Example Request
curl "https://api.dev.myhubble.money/v3/store/products/recent-searches" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-USER-ID: <user_id>" \
-H "X-Request-Id: $(uuidgen)"
Example Response
{
"searches": [
{
"type": "KEYWORD_SEARCH",
"searchKey": "pizza",
"displayText": "pizza",
"categoryId": null,
"brands": [
{
"id": "01GMAW822RPDJ5C50XK24QC2C4",
"brandKey": "pizza-hut",
"name": "Pizza Hut",
"sqLogoUrl": "https://assets.myhubble.money/...",
"discountPercentage": 5,
"rewardType": "PERCENTAGE"
}
]
},
{
"type": "CATEGORY_SEARCH",
"searchKey": "FOOD",
"displayText": "Food",
"categoryId": "01H_CATEGORY_ID",
"brands": []
}
]
}
Recent searches are user-specific. Call this endpoint only when you can send X-USER-ID for the current user.
Recommended UX
Search Landing State
Use trending searches and recent searches together:
- Show Recent Searches first when the user is logged in and results are available
- Show Trending Searches as fallback or secondary discovery chips
- Trigger
/v3/store/products/search?q={keyword}when the user selects a keyword - Trigger
/v3/store/products/search?category={category}when the user selects a category
Results Page
Render search results using the section structure returned by the API:
- Show
MAIN_PRODUCTSas the primary grid or list - Show
OTHER_RELATED_PRODUCTSbelow the primary results - Use
voucherProduct.rewardDetailsfor discount/reward display - Use
brandKeyfor brand-specific routing when your UI works with stable brand keys - Use
idwhen opening the SDK brand detail or purchase flow
Empty Results
If both returned sections are empty:
- Keep the search term visible so users can edit it
- Show trending searches as recovery suggestions
- Avoid showing inactive or locally cached brands that were not returned by Hubble
Brand availability, discounts, and provider status can change. Cache only briefly for UI responsiveness and refresh results before showing a purchase screen.
Next Steps
- Use Deep Links to open SDK brand detail or purchase flows from a custom listing.
- Use Theme Customization if part of the experience still uses pre-built SDK screens.
- Use User Cohorts when brand visibility or discount rules should vary by user segment.