Appearance
Product Examples
Each example below shows the complete integration flow for a product type:
- Catalog — product fields from
GET /v2/catalog - Options — items from
GET /v2/options(for select fields) - Payment — resulting
POST /v2/topuprequest via fulfillment mapping
Digi Prepaid — Fixed Amounts
Flow: Phone → Select amount → Pay
Catalog Entry
json
{
"code": "D",
"name": "Digi Prepaid",
"processing_time": "instant",
"denomination_currency": "MYR",
"denomination_unit_price": 1.0,
"fields": [
{
"id": "phone",
"type": "text",
"input_mode": "tel",
"label": "Phone Number",
"placeholder": "e.g. 0123456789",
"required": true,
"role": "account",
"validation": {
"pattern": "^01[0-9]{8,9}$",
"message": "Enter valid Malaysian phone number"
}
},
{
"id": "amount",
"type": "select",
"label": "Select Amount",
"required": true,
"role": "pricing",
"data_source": {
"type": "reference",
"endpoint": "/options",
"params": {
"product_code": { "static": "D" },
"field_id": { "static": "amount" }
}
}
}
],
"fulfillment": {
"account": { "from_field": "phone" },
"amount": { "from_field": "amount", "path": "price.amount" }
},
"pricing": {
"unit_price": "0.9850",
"currency": "MYR",
"discount": { "type": "percentage", "value": "1.5%" },
"price_adjustment": null,
"has_loss_risk": false
}
}Options Response
GET /v2/options?product_code=D&field_id=amount
json
{
"items": [
{
"code": "5",
"label": "RM 5",
"price": { "amount": "5.00", "currency": "MYR" },
"cost": { "amount": "4.8750", "currency": "MYR" }
},
{
"code": "10",
"label": "RM 10",
"price": { "amount": "10.00", "currency": "MYR" },
"cost": { "amount": "9.7500", "currency": "MYR" }
},
{
"code": "30",
"label": "RM 30",
"price": { "amount": "30.00", "currency": "MYR" },
"cost": { "amount": "29.2500", "currency": "MYR" }
},
{
"code": "50",
"label": "RM 50",
"price": { "amount": "50.00", "currency": "MYR" },
"cost": { "amount": "48.7500", "currency": "MYR" }
},
{
"code": "100",
"label": "RM 100",
"price": { "amount": "100.00", "currency": "MYR" },
"cost": { "amount": "97.5000", "currency": "MYR" }
}
]
}data_source.type is reference — these are static denominations. Cache locally.
Payment Request
User enters phone 0123456789 and selects RM 30. Fulfillment maps: account ← phone, amount ← amount.price.amount.
json
{
"refid": "your-unique-refid",
"product": "D",
"account": "0123456789",
"amount": "30.00"
}Pricing: RM 30 × 0.9850 = cost RM 29.55 → margin RM 0.45
Hotlink Internet — Dynamic Plans
Flow: Phone → Fetch plans for that number → Select plan → Pay
Catalog Entry
json
{
"code": "HI",
"name": "Hotlink Internet",
"processing_time": "instant",
"denomination_currency": "MYR",
"denomination_unit_price": 1.0,
"fields": [
{
"id": "phone",
"type": "text",
"input_mode": "tel",
"label": "Phone Number",
"placeholder": "e.g. 0123456789",
"required": true,
"role": "account",
"validation": {
"pattern": "^01[0-9]{8,9}$",
"message": "Enter valid Malaysian phone number"
}
},
{
"id": "plan",
"type": "select",
"label": "Select Plan",
"required": true,
"role": "pricing",
"data_source": {
"type": "dynamic",
"depends_on": ["phone"],
"endpoint": "/options",
"params": {
"product_code": { "static": "HI" },
"field_id": { "static": "plan" },
"account_number": { "from_field": "phone" }
}
}
}
],
"fulfillment": {
"account": { "from_field": "phone" },
"amount": { "from_field": "plan", "path": "price.amount" },
"extras": {
"subproduct_code": { "from_field": "plan", "path": "code" }
}
},
"pricing": {
"unit_price": "0.9800",
"currency": "MYR",
"discount": { "type": "percentage", "value": "2%" },
"price_adjustment": { "type": "fixed", "value": 1.0, "currency": "MYR" },
"has_loss_risk": false
}
}Options Response
GET /v2/options?product_code=HI&field_id=plan&account_number=0178855286
Plans are dynamic — they vary per phone number based on eligibility. Only fetch after the user enters their number (depends_on: ["phone"]).
json
{
"items": [
{
"code": "Everything Unlimited with Unlimited Weekly Pass RM12",
"label": "Unlimited Weekly Pass",
"validity": "7 days",
"description": "Everything Unlimited with Unlimited Weekly Pass RM12",
"price": { "amount": "12.00", "currency": "MYR" },
"cost": { "amount": "11.7600", "currency": "MYR" }
},
{
"code": "Unlimited data with hotspot and calls 30-days (3Mbps) H",
"label": "Unlimited data with hotspot and calls (3Mbps) H",
"validity": "30 days",
"price": { "amount": "40.00", "currency": "MYR" },
"cost": { "amount": "39.2000", "currency": "MYR" }
},
{
"code": "Unlimited data with hotspot and calls 30-days (6Mbps) H",
"label": "Unlimited data with hotspot and calls (6Mbps) H",
"validity": "30 days",
"price": { "amount": "50.00", "currency": "MYR" },
"cost": { "amount": "49.0000", "currency": "MYR" }
}
]
}Payment Request
User selects "Unlimited data with hotspot and calls (3Mbps) H". Fulfillment maps: account ← phone, amount ← plan.price.amount, extras.subproduct_code ← plan.code.
json
{
"refid": "your-unique-refid",
"product": "HI",
"account": "0178855286",
"amount": "40.00",
"extras": {
"subproduct_code": "Unlimited data with hotspot and calls 30-days (3Mbps) H"
}
}Pricing: RM 40 × 0.9800 = cost RM 39.20 → base margin RM 0.80. With +RM 1.00 fixed adjustment, user pays RM 41.00 → margin RM 1.80.
PTPTN — Account Lookup + Flexible Amount
Flow: NRIC → Fetch loan accounts → Select account → Enter amount → Pay
Catalog Entry
json
{
"code": "PTPTN",
"name": "PTPTN",
"processing_time": "24_hours",
"fields": [
{
"id": "nric",
"type": "text",
"input_mode": "numeric",
"label": "NRIC Number",
"placeholder": "Enter 12-digit NRIC",
"required": true,
"validation": {
"pattern": "^[0-9]{12}$",
"message": "Enter valid 12-digit NRIC"
}
},
{
"id": "loan_account",
"type": "select",
"label": "Select Account",
"required": true,
"data_source": {
"type": "dynamic",
"depends_on": ["nric"],
"endpoint": "/options",
"params": {
"product_code": { "static": "PTPTN" },
"field_id": { "static": "loan_account" },
"account_number": { "from_field": "nric" }
}
}
},
{
"id": "amount",
"type": "money",
"input_mode": "decimal",
"label": "Payment Amount",
"placeholder": "Enter amount",
"required": true,
"role": "pricing",
"currency": "MYR",
"validation": { "min": 10, "max": 60000 }
}
],
"fulfillment": {
"account": { "from_field": "loan_account", "path": "account_number" },
"amount": { "from_field": "amount" },
"extras": {
"ic_number": { "from_field": "nric" },
"subproduct_code": { "from_field": "loan_account", "path": "code" }
}
},
"pricing": {
"unit_price": "-0.5000",
"currency": "MYR",
"discount": { "type": "fixed", "value": "50 cent" },
"price_adjustment": { "type": "percentage", "value": 1.01 },
"has_loss_risk": false
}
}Options Response
GET /v2/options?product_code=PTPTN&field_id=loan_account&account_number=941123045001
json
{
"items": [
{
"code": "S",
"label": "KELVIN LEE WEI SERN",
"description": "SSPN Prime",
"account_number": "009411230450014"
}
]
}Note: items include account_number which fulfillment maps to the payment account field (not the NRIC).
Payment Request
User enters NRIC 941123045001, selects the SSPN account, enters RM 500. Fulfillment maps: account ← loan_account.account_number, amount ← amount (direct money input), extras.ic_number ← nric, extras.subproduct_code ← loan_account.code.
json
{
"refid": "your-unique-refid",
"product": "PTPTN",
"account": "009411230450014",
"amount": "500.00",
"extras": {
"ic_number": "941123045001",
"subproduct_code": "S"
}
}Pricing: RM 500 - 0.50 = cost RM 499.50 → base margin RM 0.50. With ×1.01 percentage adjustment, user pays RM 505.00 → margin RM 5.50.
JomPAY — Biller Selection
Flow: Select biller → Enter references → Enter NRIC → Enter amount → Pay
Catalog Entry
json
{
"code": "JOMPAY",
"name": "JomPAY",
"processing_time": "instant",
"fields": [
{
"id": "biller",
"type": "select",
"label": "Select Biller",
"required": true,
"data_source": {
"type": "reference",
"endpoint": "/options",
"params": {
"product_code": { "static": "JOMPAY" },
"field_id": { "static": "biller" }
}
}
},
{
"id": "ref1",
"type": "text",
"label": "Reference 1",
"placeholder": "Account/Reference number",
"required": true,
"role": "account"
},
{
"id": "ref2",
"type": "text",
"label": "Reference 2",
"placeholder": "Optional reference",
"required": false
},
{
"id": "nric",
"type": "text",
"input_mode": "numeric",
"label": "NRIC Number",
"placeholder": "Enter 12-digit NRIC",
"required": true,
"validation": {
"pattern": "^[0-9]{12}$",
"message": "Enter valid 12-digit NRIC"
}
},
{
"id": "amount",
"type": "money",
"input_mode": "decimal",
"label": "Payment Amount",
"required": true,
"role": "pricing",
"currency": "MYR",
"validation": { "min": 1, "max": 30000 }
}
],
"fulfillment": {
"account": { "from_field": "ref1" },
"amount": { "from_field": "amount" },
"extras": {
"biller_code": { "from_field": "biller", "path": "code" },
"ic_number": { "from_field": "nric" },
"ref2": { "from_field": "ref2", "omit_if_empty": true }
}
},
"pricing": {
"unit_price": "-0.3000",
"currency": "MYR",
"discount": { "type": "fixed", "value": "30 cent" },
"price_adjustment": { "type": "fixed", "value": 0.5, "currency": "MYR" },
"has_loss_risk": false
}
}Options Response
GET /v2/options?product_code=JOMPAY&field_id=biller&limit=3
21,000+ billers — use pagination (limit + page) and cache locally.
json
{
"items": [
{
"code": "818625",
"label": "TADIKA DIDIKAN SOLEH PLT.",
"min_amount": { "amount": "1.00", "currency": "MYR" },
"max_amount": { "amount": "30000.00", "currency": "MYR" }
},
{
"code": "779264",
"label": "RIM PRO AUTOMOTIVE.",
"min_amount": { "amount": "1.00", "currency": "MYR" },
"max_amount": { "amount": "30000.00", "currency": "MYR" }
}
],
"meta": {
"current_page": 1,
"last_page": 7096,
"per_page": 3,
"total": 21287
}
}Dynamic Amount Limits
Each biller has its own min_amount/max_amount. Use these to validate the payment amount field — they override the static validation.min/max from the catalog, which are fallbacks before a biller is selected.
You can also filter by biller code: GET /v2/options?product_code=JOMPAY&field_id=biller&biller_code=818625
Payment Request
User selects biller 818625, enters ref1 ABC123, ref2 is empty (omitted), NRIC 941123045001, amount RM 150.
json
{
"refid": "your-unique-refid",
"product": "JOMPAY",
"account": "ABC123",
"amount": "150.00",
"extras": {
"biller_code": "818625",
"ic_number": "941123045001"
}
}Note: ref2 is omitted because omit_if_empty: true and the value is empty.
Pricing: RM 150 - 0.30 = cost RM 149.70. With +RM 0.50 fixed adjustment, user pays RM 150.50 → margin RM 0.80.
PUBG Mobile — Game Packages
Flow: Player ID → Select package → Pay
Catalog Entry
json
{
"code": "PUBG",
"name": "PUBG Mobile",
"processing_time": "instant",
"fields": [
{
"id": "player_id",
"type": "text",
"input_mode": "numeric",
"label": "Player ID",
"placeholder": "Enter your PUBG Player ID",
"required": true,
"role": "account",
"validation": {
"pattern": "^[0-9]{8,12}$",
"message": "Enter valid Player ID"
}
},
{
"id": "package",
"type": "select",
"label": "Select Package",
"required": true,
"role": "pricing",
"data_source": {
"type": "reference",
"endpoint": "/options",
"params": {
"product_code": { "static": "PUBG" },
"field_id": { "static": "package" }
}
}
}
],
"fulfillment": {
"account": { "from_field": "player_id" },
"amount": { "from_field": "package", "path": "price.amount" },
"extras": {
"subproduct_code": { "from_field": "package", "path": "code" }
}
},
"pricing": {
"unit_price": "0.9450",
"currency": "MYR",
"discount": { "type": "percentage", "value": "5.5%" },
"price_adjustment": null,
"has_loss_risk": false
}
}Options Response
GET /v2/options?product_code=PUBG&field_id=package
This product includes rrp (recommended retail price) in addition to price and cost:
json
{
"items": [
{
"code": "60",
"label": "60 UC",
"price": { "amount": "5.00", "currency": "MYR" },
"cost": { "amount": "4.5000", "currency": "MYR" },
"rrp": { "amount": "5.50", "currency": "MYR" }
},
{
"code": "325",
"label": "325 UC",
"price": { "amount": "23.00", "currency": "MYR" },
"cost": { "amount": "19.5000", "currency": "MYR" },
"rrp": { "amount": "25.00", "currency": "MYR" }
},
{
"code": "660",
"label": "660 UC",
"price": { "amount": "50.00", "currency": "MYR" },
"cost": { "amount": "42.0000", "currency": "MYR" },
"rrp": { "amount": "55.00", "currency": "MYR" }
}
]
}Payment Request
User enters player ID 5123456789 and selects "60 UC". Fulfillment maps: account ← player_id, amount ← package.price.amount, extras.subproduct_code ← package.code.
json
{
"refid": "your-unique-refid",
"product": "PUBG",
"account": "5123456789",
"amount": "5.00",
"extras": {
"subproduct_code": "60"
}
}Pricing: Per-item cost is RM 4.50 (from options), price is RM 5.00 → margin RM 0.50.
