Skip to content

API Integration Guide

A step-by-step walkthrough for API partners - from environment setup and authentication to placing orders, handling all response states, and going live on production.

Follow the parts in order for your first integration.

Part I - Environments

Hubble provides two separate environments. You will start on Staging, and move to Production after your integration is verified.

1.1 Staging & Production URLs

EnvironmentBase URLPurpose
Staginghttps://api.dev.myhubble.moneyTesting and development
Productionhttps://api.myhubble.moneyLive transactions with real money
Terminal window
# Example: Login on Staging
curl -X POST "https://api.dev.myhubble.money/v1/partners/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "YOUR_STAGING_CLIENT_ID",
"clientSecret": "YOUR_STAGING_CLIENT_SECRET"
}'

1.2 Staging Credentials

Use the integration portal to obtain your credentials:

  • clientId — Your unique partner identifier
  • clientSecret — Your secret key (store securely, never expose in client-side code)

Part II - Authentication

All API access begins with authentication. You exchange your credentials for a time-limited access token, which is then used for every subsequent request.

2.1 Login API

All API access begins with authentication. Exchange your credentials for a time-limited access token used for every subsequent request.

POST /v1/partners/auth/login

Auth Required: No — this is how you get the token.

Error Responses

StatusMeaningCommon Cause
401UnauthorizedWrong clientId/clientSecret, or staging keys on production
400Bad RequestMissing fields in request body
403ForbiddenRequest from a non-whitelisted IP
Terminal window
curl -X POST "https://api.dev.myhubble.money/v1/partners/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "YOUR_STAGING_CLIENT_ID",
"clientSecret": "YOUR_STAGING_CLIENT_SECRET"
}'

Response (200 OK):

{
"token": "eyJhbGciOiJIUzI1NiIs...",
"expiresInSecs": 3600
}

2.2 Token Management

The access token expires after expiresInSecs (typically 3600s / 1 hour). You must:

  • Cache the token and reuse it for all requests within the validity window. Do not call Login before every request.
  • Implement automatic token refresh before expiry. Recommended: refresh at 80% of expiry time (e.g., after 48 minutes for a 60-minute token).
  • Handle 401 responses mid-session by re-authenticating and retrying the failed request automatically.

2.3 Request Headers

Every API call after authentication must include these headers:

HeaderValueDescription
AuthorizationBearer <access_token>JWT token from the Login API
X-REQUEST-IDA unique UUID per requestCritical for troubleshooting with Hubble support
Content-Typeapplication/jsonRequired for all POST requests
Terminal window
# Example headers
Authorization: Bearer <access_token>
X-REQUEST-ID: 239774a8-f59c-496c-bb52-ceb683d60af3
Content-Type: application/json

2.4 Setup Checklist

  • Configure base URLs separately (not hardcoded) so switching from staging to production is a config change, not a code change.
  • Generate and log X-REQUEST-ID for every single API call.

Part III - Discovering Brands

Once authenticated, explore the brand catalog. Hubble offers 450+ gift card brands across categories like Food, Fashion, Electronics, Travel, and more.

3.1 Fetch Brand Catalog

Fetch the entire brand catalog using this API. Authentication is required. The access token is a token you get from the login API.

GET /v1/partners/products

Query Parameters (all optional)

ParameterTypeDescription
qstringText search on brand titles and descriptions
categorystringFilter by category, e.g. FOOD, FASHION, ELECTRONICS
pageNointegerPage number starting from 1. Omit to get all brands.
limitintegerPage size for pagination
Terminal window
# Fetch brand catalog
curl "https://api.dev.myhubble.money/v1/partners/products?category=FOOD&pageNo=1&limit=20" \
-H "Authorization: Bearer <access_token>" \
-H "X-REQUEST-ID: $(uuidgen)"

3.2 Get Single Brand

Returns the full brand object for a specific product. Use this to fetch up-to-date details before placing an order.

GET /v1/partners/products/:productId
Terminal window
# Get single brand
curl "https://api.dev.myhubble.money/v1/partners/products/01GMMNJECTDZAG2YS61K58HVG8" \
-H "Authorization: Bearer <token>" \
-H "X-REQUEST-ID: $(uuidgen)"

Each brand returned by the API contains critical fields that govern how you can order vouchers. You must understand these fields thoroughly before placing any orders.

3.3 Brand Status Values

Every brand has a status field that determines whether vouchers can be generated for it.

StatusMeaningWhat You Should Do
ACTIVEVouchers can be generatedSafe to display to end users and accept orders
INACTIVEVouchers CANNOT be generatedRemove from user-facing catalog immediately. Do not attempt orders.

Brand Errors

CodeErrorWhat To Do
E100Brand temporarily disabledProvider failure. Wait and retry later.
E101Brand not enabled for youContact Hubble support to enable this brand.
E102Brand not activeBrand is INACTIVE. Do not display to users.

3.4 Denomination Types

The denominationType field tells you how the brand accepts order amounts.

TypeHow It WorksWhat to Validate
FIXEDOnly specific denominations in amountRestrictions.denominations are acceptedYour order denomination must exactly match one value in the array
FLEXIBLEAny amount between minVoucherAmount and maxVoucherAmountValue must fall within min/max range. No fixed list to match against.

When a brand is FIXED: You must read the amountRestrictions.denominations array and only allow users to select from those exact values. For example, if Flipkart has denominations [100, 250, 500, 1000, 2000, 5000], you cannot send 600 or 1500 - only the exact listed values.

When a brand is FLEXIBLE: You can allow users to enter any custom amount, but you must enforce the min/max boundaries. For example, if a brand allows Rs 100 to Rs 10,000, sending Rs 50 or Rs 15,000 will fail.

Additional Amount Restrictions

  • maxVouchersPerOrder — Max total vouchers in a single order
  • maxVouchersPerDenomination — Max vouchers of same denomination in one order
  • maxDenominationsPerOrder — Max distinct denomination values in one order
  • minOrderAmount / maxOrderAmount — Total order amount boundaries

3.5 Card Type

The cardType field on the brand object is essential for building your voucher display logic. It tells you exactly what credentials the end user needs to redeem the gift card.

Card TypeWhat Customer NeedsWhat to Display
CARD_NUMBER_SECUREDCard number onlyShow cardNumber. cardPin will be null.
PIN_NO_SECUREDPIN onlyShow cardPin. cardNumber will be null.
CARD_AND_PIN_NO_SECUREDBoth card number AND PINShow BOTH. If either is missing, customer cannot redeem.
  • Read cardType from the brand object before placing an order to know what your display UI needs to support.
  • Handle null values gracefully — for CARD_NUMBER_SECURED brands, cardPin will be null.
  • For CARD_AND_PIN_NO_SECURED brands, you MUST display both credentials.

3.6 Redemption Type

The redemptionType tells you where the voucher can be used.

TypeWhere Voucher Can Be UsedHow to Use This Information
ONLINEOnly on the brand’s website or appShow an “Online Only” tag.
OFFLINEOnly at physical retail storesShow an “In-Store Only” tag. The brand’s online checkout may not accept this voucher.
ONLINE_AND_OFFLINEBoth online and at physical storesThe most flexible type. Show “Online & In-Store” or similar messaging.

How to use redemptionType in practice:

  • Display the redemption channel clearly to end users so they know where they can use the voucher. A customer buying a voucher for in-store use will be frustrated if the brand only accepts it online.
  • Use retailModeName for display text (not the retailMode enum). The enum value ONLINE/OFFLINE is for your logic; the retailModeName gives a user-friendly label.
  • Include howToUseInstructions - these are brand-specific redemption steps provided by the brand. Display them alongside the voucher to help customers redeem successfully.

3.7 Deprecated Fields

The following fields will be removed in future API versions. Migrate as soon as possible.

Deprecated FieldUse InsteadNotes
iconImageUrlthumbnailUrlBrand image/logo URL
minAmount / maxAmountminOrderAmount / maxOrderAmountOrder amount limits
usageInstructionshowToUseInstructionsRedemption steps for end users

Brand Errors You May Encounter

CodeErrorWhat To Do
E100Brand temporarily disabledBrand disabled due to provider failures. Wait and retry later.
E101Brand not enabled for youContact Hubble support to enable this brand for your account.
E102Brand not activeThe brand is INACTIVE. Do not display to users. Check catalog for updated status.

Part IV - Placing Your First Order

This is the core of the integration, converting brand selections into actual gift card vouchers. This section covers the order request structure and the most common failure patterns.

4.1 Place Order

POST /v1/partners/orders

Request Body Fields

FieldTypeRequiredDescription
productIdstringRequiredBrand/product ID from the catalog
referenceIdstringRequiredYour idempotency key (max 40 chars, globally unique)
amountnumberRequiredTotal order amount (must = sum of denomination × qty)
denominationDetails[]arrayRequiredList of {denomination, quantity} pairs
customerDetailsobjectConditionalRequired for B2C, nullable for B2B
deliveryDetailsobjectOptionalOnly if Hubble handles voucher delivery for you
Terminal window
curl -X POST "https://api.dev.myhubble.money/v1/partners/orders" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-H "X-REQUEST-ID: 239774a8-f59c-496c-bb52-ceb683d60af3" \
-d '{
"productId": "01GMAW822RPDJ5C50XK24QC2C4",
"referenceId": "ORD-2026-001",
"amount": 1000,
"denominationDetails": [
{ "denomination": 500, "quantity": 2 }
],
"customerDetails": {
"name": "John Doe",
"phoneNumber": "9876543212",
"email": "john@example.com"
}
}'

Response Body

Returns the Order Object

4.2 Customer Details


Part V - Order Handling

Not all orders complete instantly. Orders can return in one of three primary states: SUCCESS, FAILED, or PROCESSING. This section walks through each state with real examples so you know exactly what to expect and how to handle it.

5.1 Response States

StatusMeaningYour Action
SUCCESSVouchers generated — data in vouchers[]Display vouchers to user
PROCESSINGGeneration in progress — vouchers[] is emptyPoll or listen for webhook
FAILEDGeneration failed — see failureReasonShow error, retry with new referenceId
CANCELLEDCancelled by client requestConfirm cancellation to user
REVERSEDReversed by client requestProcess refund if applicable

5.2 Handling SUCCESS

When an order completes successfully, the response includes a vouchers[] array with the generated gift card details. Here is a complete example using Flipkart as the brand.

Example: Placing a Flipkart Order (Staging)

Brand: Flipkart | Product ID: 01GMMNJECTDZAG2YS61K58HVG8 | Amount: Rs 500

curl -X POST "https://api.dev.myhubble.money/v1/partners/orders" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-H "X-REQUEST-ID: 239774a8-f59c-496c-bb52-ceb683d60af3" \
-d '{
"productId": "01GMMNJECTDZAG2YS61K58HVG8",
"referenceId": "ref_1772006406973_tfrkrtu",
"amount": 500,
"denominationDetails": [
{ "denomination": 500, "quantity": 1 }
],
"customerDetails": {
"name": "Test User",
"phoneNumber": "9876543212",
"email": "test@example.com"
}
}'

SUCCESS Response (HTTP 200)

{
"id": "01KJA7HBZAPKDN0VVXTVN6R41H",
"referenceId": "ref_1772006406973_tfrkrtu",
"status": "SUCCESS",
"vouchers": [
{
"cardType": "CARD_AND_PIN_NO_SECURED",
"cardPin": "215744",
"cardNumber": "8090920011768104",
"validTill": "2027-02-25",
"amount": 500
}
],
"failureReason": null
}

What to Do on SUCCESS

  • Extract the vouchers[] array - each object contains the gift card credentials.
  • Check the cardType field to determine what to display to the end user. In this Flipkart example, CARD_AND_PIN_NO_SECURED means the customer needs both the card number and PIN to redeem.
  • Display credentials: Show the cardNumber and cardPin to the customer.
  • Show the expiry date: The validTill field tells the customer when the voucher expires.
  • Store the order: Save the Hubble id and your referenceId for reconciliation.

5.3 Handling FAILED Orders

When an order fails, the response includes an empty vouchers[] array and a failureReason explaining what went wrong. Here is an example using Jiomart as the brand. (Brands like Jiomart and Myntra are configured to fail in staging.)

Example: Placing a Jiomart Order (Staging)

Brand: Jiomart | Product ID: 01J1W4D2KRHMJZKPAQWXCEMF4M | Amount: Rs 500

Request

Terminal window
curl -X POST "https://api.dev.myhubble.money/v1/partners/orders" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-H "X-REQUEST-ID: 239774a8-f59c-496c-bb52-ceb683d60af3" \
-d '{
"productId": "01J1W4D2KRHMJZKPAQWXCEMF4M",
"referenceId": "ref_1772017611584_94lcjp8",
"amount": 500,
"denominationDetails": [
{ "denomination": 500, "quantity": 1 }
],
"customerDetails": {
"name": "Test User",
"phoneNumber": "9876543212",
"email": "test@example.com"
}
}'

FAILED Response (HTTP 200)

{
"id": "01KJA7NYJHHRPQ47VMN4ZN3JFT",
"referenceId": "ref_1772017611584_94lcjp8",
"status": "FAILED",
"vouchers": [],
"failureReason": "Brand not available"
}

What to Do on FAILED

  • Read the failureReason — in this case, “Brand not available” means Jiomart is not currently active or has no available providers.
  • Do NOT reuse the referenceId — even though the order failed, the referenceId ref_1772017611584_94lcjp8 is now consumed. You must generate a new one for any retry.
  • Check the brand status — call GET /v1/partners/products/:productId to verify if the brand is ACTIVE before retrying.
  • Inform the user — show a meaningful error message. Do not expose raw error strings to end users.
  • Log everything — save the Hubble id, your referenceId, and the failureReason for debugging.

Common Failure Reasons

ReasonResolution
”Brand not available”The brand is INACTIVE or has no active providers. Try a different brand or wait.
”Voucher generation failed”Provider-side failure (E200). Retry after 1–2 minutes.
”Insufficient balance”Wallet balance too low (E300). Top up before retrying.
”Denomination not available”The denomination is not in the brand’s allowed list (E150). Refresh your catalog.

5.4 Handling PROCESSING Orders

Some orders do not resolve immediately. When voucher generation takes time (e.g., for large orders or certain providers), the API returns a PROCESSING status. The vouchers[] array will be empty, and you need to wait for the final state.

If an order is returned with the status PROCESSING, follow this protocol:

  1. Begin polling the Get Order endpoint — start polling 1 minute after order placement.
  2. Limit polling to a maximum of 5 attempts at reasonable intervals.
  3. Optionally, set up the Order Reached Terminal State webhook (recommended). You may configure your system to listen for the webhook to receive the final order status automatically instead of relying only on polling.
  4. Timeout handling — if the order remains in PROCESSING status after 15 minutes, mark it as FAILED on your side and contact Hubble support for further assistance.

Example: PROCESSING Response

Brand: Amazon | Amount: Rs 5,000 (10 x Rs 500)

{
"id": "01KJB2EXAMPLE0PROCESSING01",
"referenceId": "ref_your_unique_id_here",
"status": "PROCESSING",
"vouchers": [],
"failureReason": null
}

Key observations: The status is PROCESSING, vouchers[] is empty (no gift cards yet), and failureReason is null (it has not failed — it is still in progress).

What to Do Next: Wait for Resolution

You have two options to know when the order resolves:

Option A: Polling

If webhooks are not set up, poll the Get Order endpoint:

  • Wait at least 1 minute after order placement before the first poll.
  • Poll GET /v1/partners/orders/:orderId at reasonable intervals (e.g., every 2 minutes).
  • Limit polling to a maximum of 5 attempts.
  • If the order remains PROCESSING after 15 minutes, mark it as FAILED on your side and contact Hubble support.

Resolved Response (After Polling or Webhook)

Once the order resolves, the Get Order API returns the full details:

{
"id": "01KJB2EXAMPLE0PROCESSING01",
"referenceId": "ref_your_unique_id_here",
"status": "SUCCESS",
"vouchers": [
{
"id": "01KJB2VOUCHER001",
"cardType": "CARD_AND_PIN_NO_SECURED",
"cardPin": "834291",
"cardNumber": "5012340098761234",
"validTill": "2027-02-25",
"amount": 500
},
{
"id": "01KJB2VOUCHER002",
"cardType": "CARD_AND_PIN_NO_SECURED",
"cardPin": "729103",
"cardNumber": "5012340098765678",
"validTill": "2027-02-25",
"amount": 500
}
],
"failureReason": null
}

Option B: Webhook (Recommended)

If you have the Order Reached Terminal State webhook configured, Hubble will push a notification to your endpoint when the order resolves to SUCCESS or FAILED.

// Webhook payload you will receive:
{
"orderId": "01KJB2EXAMPLE0PROCESSING01",
"status": "SUCCESS"
}

On receiving this webhook, call GET /v1/partners/orders/01KJB2EXAMPLE0PROCESSING01 to fetch the full order details including the vouchers[] array.

5.5 Handling Timeouts

If your HTTP request to the Place Order API times out (no response received at all):

  1. Call GET /v1/partners/orders/by-reference/:referenceId to check if the order was created.
  2. A 404 response means the order was NOT created — you may safely retry with the same referenceId.
  3. Any other response means the order exists — process based on the returned status (SUCCESS, FAILED, or PROCESSING).
Terminal window
# Check if order exists by your referenceId
curl "https://api.dev.myhubble.money/v1/partners/orders/by-reference/ORD-2026-001" \
-H "Authorization: Bearer <token>"
# 404 = not created, retry with same referenceId
# 200 = exists, process based on status

Part VI - Go Live

Once your staging integration is working end-to-end (authenticate, fetch brands, place orders, handle all statuses), it is time to transition to production. Hubble will provide production credentials after verifying your staging integration.

6.1 Production Credentials

Hubble provides production credentials separately from staging. You will receive new clientId and clientSecret for production (different from staging)

6.2 IP Whitelisting

Hubble only allows API requests from pre-approved IP addresses. Use the integration portal to add your server’s static IPs. Production server IPs must be whitelisted separately from staging.

6.3 Wallet Balance

GET /v1/partners/wallet/balance

Wallet Top-Up: Wallet loading is an offline process. Contact your Hubble account manager to request a top-up.

Terminal window
curl "https://api.myhubble.money/v1/partners/wallet/balance" \
-H "Authorization: Bearer <prod_token>" \
-H "X-REQUEST-ID: $(uuidgen)"

Response:

{
"balance": 1000.50
}

6.4 Webhooks

Webhooks allow Hubble to push updates to your system in real time. Strongly recommended for a production-grade integration.

WebhookTriggers When…
Brand UpdatedA brand’s status, denomination, or amount restrictions change
Wallet Low BalanceWallet balance falls below your configured threshold
Order Reached Terminal StateA PROCESSING order transitions to SUCCESS or FAILED
Brand Discount UpdateSubvention/discount percentage changes for a brand

6.5 Catalog Sync

  • Refresh your full catalog at least once per week (daily recommended).
  • Subscribe to the Brand Updated webhook for real-time changes to status, denominations, and amount restrictions.
  • Categories are NOT communicated via webhooks. Rely on periodic sync for category and new brand additions.
  • Filter out INACTIVE brands from your user-facing catalog immediately when detected.
  • Cache brand data locally to minimize API calls — but always validate denominations against the latest catalog before placing orders.
  • If your sync is infrequent, orders will fail with E150 (denomination not available).

6.6 Rate Limiting

  • Limits are enforced at two levels: Partner-level (across your entire account) and Brand-level (per product). If either is breached, the order fails.
  • Two types: Amount (total monetary value) and Count (number of orders), across hourly, daily, and monthly windows.
  • Brand-level limits can be scoped globally or per user for granular risk control.
  • Rate limit failures are business logic failures, not HTTP 429 errors. Always check the response body for the failure reason.
  • Before going live, define realistic limits and coordinate with Hubble ahead of high-volume campaigns or seasonal spikes.

Appendix

All Endpoints (Quick Reference)

MethodEndpointPurpose
POST/v1/partners/auth/loginAuthenticate and get access token
GET/v1/partners/productsList all brands with filters
GET/v1/partners/products/:productIdGet single brand details
POST/v1/partners/ordersPlace a voucher order
GET/v1/partners/orders/:orderIdGet order by Hubble ID
GET/v1/partners/orders/by-reference/:referenceIdGet order by your reference ID
GET/v1/partners/orders/vouchers/:idGet individual voucher details
POST/v1/partners/orders/:orderId/resend-deliveryRetry voucher delivery
GET/v1/partners/wallet/balanceCheck wallet balance