Custom Brand Page
Custom Brand Page lets you build your own brand detail screen — the page where a user sees a specific gift card brand, its artwork, discount, and redemption instructions before purchasing. Hubble provides all the underlying brand data through a single voucher product API, and you render it in your own UI.
Use this approach together with Custom Listing: the listing gives you brand identifiers, and this API gives you everything needed to render the brand's detail page. Payment and purchase flows can still open in Hubble SDK screens.
How It Works
- Get a
brandKeyor product ID from Custom Listing search results, or from your own routing. - Call the voucher product details API to fetch brand metadata, imagery, discount details, purchasable amounts, and how-to-redeem content.
- Render your own brand page — card artwork, brand colors, card worth, discounted price, and a "How to redeem" section.
- Open the purchase flow using the returned
externalId.
Only ACTIVE products are returned. Reward and pricing data are resolved per client (X-CLIENT-ID).
Get Brand Details
/v1/store/products/voucher-product/{voucherProductIdOrBrandKey}Returns the complete detail page payload for a single voucher product (gift card brand): brand metadata and imagery, reward (discount) details, purchasable amounts, purchase restrictions, how-to-redeem content, and variant SKUs for multi-SKU brands.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
voucherProductIdOrBrandKey | string | Yes | Voucher product ID or brand key (e.g. ikea, zomato). The identifier is resolved first as a product ID, then as a brand key, so both work in the same path segment. |
Request Headers
This is a public store endpoint. It does not require bearer authentication, but it does require client context.
| Header | Required | Description |
|---|---|---|
X-CLIENT-ID | Yes | Your Hubble client ID. If omitted, store-service defaults to the hubble client. |
X-Request-Id | Recommended | Unique request identifier for tracing and support. Echoed back in error responses. |
Example Request
curl "https://api.dev.myhubble.money/v1/store/products/voucher-product/ikea" \
-H "X-CLIENT-ID: <client_id>" \
-H "X-Request-Id: $(uuidgen)"
Example Response
{
"externalId": "01HSBD494BMXNNP9HA9CTXAQ16",
"brandKey": "ikea",
"name": "IKEA",
"status": "ACTIVE",
"voucherProductMetadata": {
"title": "IKEA",
"conditions": [
"The Gift Card cannot be used to purchase other gift cards.",
"Gift Vouchers can only be used in-store and on website for purchases, redemption of gift card on application is not allowed"
],
"cardImageUrl": "",
"cardBackgroundColor": "#015BB2",
"howToUseSteps": [
{
"retailMode": "ONLINE",
"retailModeName": "Offline",
"howToUseHints": {
"hints": [
"Visit the outlet near you.",
"At the billing counter inform cashier that you want to use Gift Card.",
"Show your Gift Card details & pay any balance amount by cash or card."
]
},
"howToUseInDetail": {
"steps": [
{
"description": "Visit the outlet near you.",
"imageUrl": null,
"imageSize": null
},
{
"description": "At the billing counter inform cashier that you want to use Gift Card.",
"imageUrl": null,
"imageSize": null
},
{
"description": "Show your Gift Card details & pay any balance amount by cash or card.",
"imageUrl": null,
"imageSize": null
}
]
}
},
{
"retailMode": "OFFLINE",
"retailModeName": "Online",
"howToUseHints": {
"hints": [
"On www.ikea.com add products to you cart",
"Before purchasing GC, please ensure that IKEA delivers to your location",
"To check, please follow these steps: https://coda.io/@sharad/does-ikea-deliver-to-my-location",
"Alternatively, you can check your PIN code against this list: https://coda.io/@sharad/ikea-servicable-pin-codes",
"Proceed to checkout, in the payment section, select Redeem an IKEA gift card",
"Enter the gift card details, complete checkout."
]
},
"howToUseInDetail": {
"steps": [
{
"description": "On www.ikea.com add products to you cart",
"imageUrl": null,
"imageSize": null
},
{
"description": "Before purchasing GC, please ensure that IKEA delivers to your location",
"imageUrl": null,
"imageSize": null
},
{
"description": "To check, please follow these steps: https://coda.io/@sharad/does-ikea-deliver-to-my-location",
"imageUrl": null,
"imageSize": null
},
{
"description": "Alternatively, you can check your PIN code against this list: https://coda.io/@sharad/ikea-servicable-pin-codes",
"imageUrl": null,
"imageSize": null
},
{
"description": "Proceed to checkout, in the payment section, select Redeem an IKEA gift card",
"imageUrl": null,
"imageSize": null
},
{
"description": "Enter the gift card details, complete checkout.",
"imageUrl": null,
"imageSize": null
}
]
}
}
],
"logoUrl": "https://assets.myhubble.money/brand-assets/logo-images-wp/ikea-logo.webp",
"plainLogoUrl": "https://assets.myhubble.money/brand-assets/wdmark-images-wp/ikea-wdmark.webp",
"plainFillLogoUrl": "",
"promoImageUrl": "https://gullak-assets.s3.ap-south-1.amazonaws.com/brand-images/promos/OldAppBrandCard_IKEA.png",
"promoImageUrlV2": "https://gullak-assets.s3.ap-south-1.amazonaws.com/brand-images/promos-v2/NewAppBrandCard_IKEA.png",
"heroImageUrl": "https://assets.myhubble.money/brand-assets/hero-images/ikea-hero1.png",
"iconImageUrl": "https://assets.myhubble.money/brand-assets/icon-images/Ikea_icon_0406.png",
"shareImageUrl": "https://gullak-assets.s3.ap-south-1.amazonaws.com/share-wa-brand-images/WA_ikea.png",
"rdSqLogoUrl": "https://assets.myhubble.money/brand-assets/rdsq-logo-images-wp/ikea-rdsq-logo.webp",
"sqLogoUrl": "https://assets.myhubble.money/brand-assets/sq-logo-images-wp/235-ikea-cpvsy0.webp",
"addVoucherBrandPageUrl": null,
"addVoucherBrandPageImageUrl": null
},
"amountConditions": {
"minAmount": 1,
"maxAmount": 100000,
"defaultAmount": 1000,
"denominations": null,
"defaultDenominationDetails": null,
"stepAmount": 1,
"maxNoOfVouchersPerDenomination": null,
"maxNoOfDenominationsPerOrder": null
},
"restrictions": {
"maxWorthOfVouchersInAMonth": null,
"maxWorthOfVouchersForApiPartnerInAMonth": null,
"maxNumberOfVouchersPerOrder": 10,
"maxNumberOfVouchersInAMonth": null,
"maxNumberOfVouchersInLast365Days": null,
"rewardCap": {
"unit": "PERC",
"value": 5
},
"vouchersWorthLimitInDateRange": null,
"voucherPreConditions": null,
"isCoinConsumptionAllowed": false,
"paymentSource": "PG_AND_WALLET_AND_COINS",
"allowedBusinessModels": "BOTH",
"ccEnabled": null,
"maxOrdersInAMonth": null,
"maxConsecutiveMonthlyOrders": null
},
"voucherProductProviderMetadata": {
"onlySingleDenominationAllowed": false
},
"rewardType": "PREPAID",
"rewardDetails": [
{
"discountPercentage": 5,
"rewardType": "PREPAID"
}
],
"variantDetailedResponse": null
}
This is a real sample response for one brand. Asset URLs, amounts, limits, and rewards vary by brand and by client. Deprecated fields still present in live responses are omitted here — see Deprecated Fields.
Response Fields
Top Level
| Field | Type | Description |
|---|---|---|
externalId | string | Voucher product ID. Use this when opening the purchase flow. |
brandKey | string | Stable brand identifier (e.g. ikea). |
name | string | Brand display name. |
status | string | Always ACTIVE — inactive products return an error instead. |
voucherProductMetadata | object | Brand content and imagery — see below. |
amountConditions | object | Purchasable amounts — see below. |
restrictions | object | Purchase limits — see below. |
voucherProductProviderMetadata | object | { onlySingleDenominationAllowed } — true when the provider only supports a single denomination per voucher. |
rewardType | enum | PREPAID | POSTPAID. |
rewardDetails | array | One entry per applicable reward: discountPercentage (number), rewardType (PREPAID | POSTPAID). Use this to render the discount and the discounted price. |
variantDetailedResponse | array, nullable | Present only for multi-SKU (variant) brands — see below. |
voucherProductMetadata
| Field | Type | Description |
|---|---|---|
title | string | Brand title. |
conditions | string[] | Brand-specific purchase and usage conditions. Display these on the brand page (e.g. in the terms section). |
cardImageUrl | string | Card artwork. Can be empty — fall back to your own card layout with the brand logo. |
cardBackgroundColor | string | Hex color for the card background. |
howToUseSteps | array | How-to-redeem content, one entry per retail mode — see below. |
logoUrl, sqLogoUrl, rdSqLogoUrl, plainLogoUrl, plainFillLogoUrl, promoImageUrl, promoImageUrlV2, heroImageUrl, iconImageUrl, shareImageUrl | string, nullable | Brand imagery in various shapes and sizes for different placements. Individual URLs can be empty for some brands. |
addVoucherBrandPageUrl, addVoucherBrandPageImageUrl | string, nullable | Link and image for adding an externally purchased voucher of this brand. |
howToUseSteps
This is the content behind the How to redeem section on the brand page. Each entry covers one retail mode:
| Field | Type | Description |
|---|---|---|
retailMode | enum | ONLINE | OFFLINE. |
retailModeName | string | Display label for the mode. Use this as the tab/section label. |
howToUseHints | object | { hints: string[] } — short redemption hints for compact display. |
howToUseInDetail | object | { steps: [{ description, imageUrl?, imageSize? }] } where imageSize is FULL | PARTIAL — detailed step-by-step instructions with optional imagery. |
amountConditions
| Field | Type | Description |
|---|---|---|
minAmount | number | Minimum purchase amount per voucher. |
maxAmount | number | Maximum purchase amount per voucher. |
defaultAmount | number, nullable | Pre-selected amount to show on the page. |
denominations | number[], nullable | Fixed purchasable denominations. When null, any amount between minAmount and maxAmount in stepAmount increments is allowed. |
defaultDenominationDetails | array, nullable | Pre-selected cart: { denomination, quantity }. |
stepAmount | number | Increment for custom amounts. |
maxNoOfVouchersPerDenomination | integer, nullable | Cap on vouchers per denomination in one order. |
maxNoOfDenominationsPerOrder | integer, nullable | Cap on distinct denominations in one order. |
restrictions
| Field | Type | Description |
|---|---|---|
maxNumberOfVouchersPerOrder | integer | Maximum vouchers in a single order. |
maxWorthOfVouchersInAMonth | number, nullable | Monthly spend cap for this brand. |
maxWorthOfVouchersForApiPartnerInAMonth | number, nullable | Monthly spend cap specific to API partners. |
maxNumberOfVouchersInAMonth | integer, nullable | Monthly voucher count cap. |
maxNumberOfVouchersInLast365Days | integer, nullable | Rolling-year voucher count cap. |
rewardCap | object, nullable | Cap on the reward: { unit, value } (e.g. PERC / 5). |
vouchersWorthLimitInDateRange | object, nullable | Spend cap within a date range: { maxVoucherWorthInDateRange, fromDate, endDate }. |
voucherPreConditions | object, nullable | Eligibility gate: { excludeVoucherProductIds, minimumSuccessfulOrder }. |
isCoinConsumptionAllowed | boolean | Whether Hubble coins can be applied to this purchase. |
paymentSource | enum | Allowed payment sources for the client, e.g. PG_AND_WALLET_AND_COINS (default), COINS_ONLY. |
allowedBusinessModels | enum | B2B | B2C | BOTH. |
ccEnabled | boolean, nullable | Whether credit card payment is enabled for this brand. |
maxOrdersInAMonth | integer, nullable | Monthly order count cap. |
maxConsecutiveMonthlyOrders | integer, nullable | Cap on consecutive months with orders. |
variantDetailedResponse (multi-SKU brands only)
Present for brands sold as fixed variants (e.g. subscription tiers).
| Field | Type | Description |
|---|---|---|
title, text, subtext | string, nullable | Display copy for the variant. |
rewardDetails | array | Per-variant { discountPercentage, rewardType }. |
Deprecated Fields
The response also contains the following fields. They are deprecated — they may still appear in live responses, but do not build on them:
voucherProductMetadata:tncUrl,tncResId,howItWorksVideoUrl,howItWorksCtaUrl,howItWorksSteps,howItWorksStepsAvailable,cardHighlights,canBalanceBeFetched,tips,showRetailModeHeader,howToUseDetailedStepsAvailable,preReviewPopupDetails,isVoucherAssured,brandLandingPageDetails,showDetailedInstructionCta,storeLocatorUrl- Top level:
showRewardCapModal,isOneVoucherOneDenominationOnly,isCoinConsumptionEnabled,taxDetails
Error Responses
404 — no active product matches the identifier:
{
"code": "PRODUCT_NOT_FOUND",
"message": "Product not found",
"requestId": "01M1126M1VJ0MGYDXH36RFAG4N",
"subErrors": [{ "message": "Product not found" }]
}
400 — the product exists but is not ACTIVE:
{
"code": "OPERATION_NOT_ALLOWED",
"message": "IKEA is temporarily disabled owing to failures",
"requestId": "01M1126M1VJ0MGYDXH36RFAG4N",
"subErrors": [{ "message": "IKEA is temporarily disabled owing to failures" }]
}
Recommended UX
Brand Card
- Use
cardImageUrlandcardBackgroundColorfor the card artwork and background; whencardImageUrlis empty, render your own card layout with a brand logo on the background color - Use
name(orvoucherProductMetadata.title) as the page heading - Use the logo variants (
logoUrl,sqLogoUrl,iconImageUrl, etc.) for the placement that fits your layout
Card Worth and Pricing
- Pre-select
amountConditions.defaultAmountas the card worth - When
denominationsis non-null, offer only those amounts; otherwise allow any amount betweenminAmountandmaxAmountinstepAmountincrements - Show the original amount struck through next to the discounted price
Purchase Limits
- Enforce
restrictions.maxNumberOfVouchersPerOrder(and denomination caps fromamountConditions) in your quantity selector
How to Redeem
- Render
howToUseStepsas the How to redeem section - Use
howToUseHints.hintsfor a compact bulleted summary per retail mode - Use
howToUseInDetail.stepswhen you want detailed, illustrated instructions - When multiple retail modes are returned, show a mode switcher using each entry's
retailModeName
Conditions and Warnings
- Display
voucherProductMetadata.conditionsin the terms/conditions section of the page - Options with
action: SHOW_WARNINGshould surface the warning copy;ALLOW_TRANSACTIONproceeds directly
Discounts, amounts, imagery, and brand availability can change, and inactive brands start returning errors. Refresh the brand details before showing a purchase screen.
Next Steps
- Use Custom Listing to build the catalog and search experience that leads to this page.
- Use Deep Links to open the SDK purchase flow from your custom brand page.
- Use User Cohorts when brand visibility or discount rules should vary by user segment.