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
In each pricing option, code is the stable plan or package identity, denomination is the face value or quantity sent as the topup amount, price.amount is the customer-facing selling price, and cost.amount is the reseller's wholesale cost.
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": "denomination" }
},
"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" },
"denomination": 5
},
{
"code": "10",
"label": "RM 10",
"price": { "amount": "10.00", "currency": "MYR" },
"cost": { "amount": "9.7500", "currency": "MYR" },
"denomination": 10
},
{
"code": "30",
"label": "RM 30",
"price": { "amount": "30.00", "currency": "MYR" },
"cost": { "amount": "29.2500", "currency": "MYR" },
"denomination": 30
},
{
"code": "50",
"label": "RM 50",
"price": { "amount": "50.00", "currency": "MYR" },
"cost": { "amount": "48.7500", "currency": "MYR" },
"denomination": 50
},
{
"code": "100",
"label": "RM 100",
"price": { "amount": "100.00", "currency": "MYR" },
"cost": { "amount": "97.5000", "currency": "MYR" },
"denomination": 100
}
]
}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.denomination.
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
Products that support plan extras include extras.subproduct_code in fulfillment, mapped from the selected option's code. A product without extras support does not gain this mapping.
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": "denomination" },
"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" },
"denomination": 12
},
{
"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" },
"denomination": 40
},
{
"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" },
"denomination": 50
}
]
}Payment Request
User selects "Unlimited data with hotspot and calls (3Mbps) H". Fulfillment maps: account ← phone, amount ← plan.denomination, 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"
}
}Always send extras.subproduct_code for mobile internet products. If it is omitted and more than one plan shares the selected denomination, the request is rejected with HTTP 400, statusCode 44 and remarks Multiple plans are available for this amount. Please provide a plan code.; no transaction is created. See Make Payment.
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": "denomination" },
"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" },
"denomination": 60
},
{
"code": "325",
"label": "325 UC",
"price": { "amount": "23.00", "currency": "MYR" },
"cost": { "amount": "19.5000", "currency": "MYR" },
"rrp": { "amount": "25.00", "currency": "MYR" },
"denomination": 325
},
{
"code": "660",
"label": "660 UC",
"price": { "amount": "50.00", "currency": "MYR" },
"cost": { "amount": "42.0000", "currency": "MYR" },
"rrp": { "amount": "55.00", "currency": "MYR" },
"denomination": 660
}
]
}Payment Request
User enters player ID 5123456789 and selects "60 UC". Fulfillment maps: account ← player_id, amount ← package.denomination, extras.subproduct_code ← package.code.
json
{
"refid": "your-unique-refid",
"product": "PUBG",
"account": "5123456789",
"amount": 60,
"extras": {
"subproduct_code": "60"
}
}Pricing: Per-item cost is RM 4.50 (from options), price is RM 5.00 → margin RM 0.50.

