Skip to content

Product Examples

Each example below shows the complete integration flow for a product type:

  1. Catalog — product fields from GET /v2/catalog
  2. Options — items from GET /v2/options (for select fields)
  3. Payment — resulting POST /v2/topup request 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: accountphone, amountamount.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

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: accountphone, amountplan.price.amount, extras.subproduct_codeplan.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: accountloan_account.account_number, amountamount (direct money input), extras.ic_numbernric, extras.subproduct_codeloan_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: accountplayer_id, amountpackage.price.amount, extras.subproduct_codepackage.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.

IIMMPACT API Documentation