Skip to content

SDK Quickstart

Coming Soon

This feature is under active development and not yet available. The API endpoints, SDK packages, and behavior described here are subject to change before release.

This guide gets you from zero to a working bill selection flow as fast as possible.

Prerequisites

  1. B2B API credentials -- Existing X-Api-Key + HMAC secret (same credentials used for other B2B API key endpoints)
  2. A backend server -- Session creation is server-to-server only (secrets must never be in client code)
  3. A frontend app -- Web (any framework) or React Native

DANGER

Never put API keys or HMAC secrets in frontend bundles, mobile apps, or source control.

Step 1: Create a Session (Backend)

When a user wants to view bills, your backend creates a session with POST /v2/sdk/sessions using API Key + HMAC headers.

bash
API_KEY="your_api_key"
HMAC_SECRET_BASE64="your_hmac_secret_base64"
TIMESTAMP=$(date +%s)
NONCE=$(uuidgen | tr '[:upper:]' '[:lower:]')

BODY='{"ic_number":"901234567890","name":"John Tan","phone":"+60123456789"}'
BODY_HASH=$(printf "%s" "$BODY" | openssl dgst -sha256 -binary | base64)
CANONICAL="v1:${TIMESTAMP}:${NONCE}:POST::${BODY_HASH}"
SIGNATURE=$(printf "%s" "$CANONICAL" | openssl dgst -sha256 -mac HMAC \
  -macopt "hexkey:$(printf "%s" "$HMAC_SECRET_BASE64" | base64 -d | xxd -p -c 256)" \
  -binary | base64)

curl -X POST https://api.iimmpact.com/v2/sdk/sessions \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: ${API_KEY}" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "X-Nonce: ${NONCE}" \
  -H "X-Signature: v1=${SIGNATURE}" \
  -d "$BODY"

Response:

json
{
  "session_token": "bp_sess_7nF1oQ4n6vR2xZ9a",
  "expires_at": "2026-03-11T10:15:00Z"
}

Pass session_token to your frontend. See POST /v2/sdk/sessions for full request/response details.

INFO

session_token is the only SDK token. There is no bootstrap-token exchange step.

Step 2: Install the SDK (Frontend)

bash
npm install @iimmpact/billpresentment-sdk
bash
npm install @iimmpact/billpresentment-sdk-react-native react-native-webview

Step 3: Open the SDK

Use the session_token returned by your backend.

typescript
import { BillPresentmentSDK } from "@iimmpact/billpresentment-sdk";

const sdk = new BillPresentmentSDK({
  sessionToken: sessionTokenFromBackend,
  displayMode: "modal", // "modal" | "fullscreen" | "inline"
});

const result = await sdk.open();
tsx
import { BillPresentment } from "@iimmpact/billpresentment-sdk-react-native";

<BillPresentment
  sessionToken={sessionTokenFromBackend}
  visible={showBills}
  displayMode="fullscreen"
  onResult={(result) => handleResult(result)}
  onClose={() => setShowBills(false)}
/>

Internally, the SDK opens bills.iimmpact.com/#token=..., the hosted app reads and clears the fragment, then uses Authorization: Bearer {session_token} for API calls.

Step 4: Handle the Result

When the user confirms bill selection, the SDK returns a structured result object:

typescript
if (result.status === "success") {
  navigateToPayment({
    bills: result.selectedBills,
    total: result.totalAmount,
  });
}

if (result.status === "cancelled") {
  // The SDK resolves with: { status: "cancelled" }
}

if (result.status === "error") {
  console.error("SDK error:", result.error);
}

Result structure:

typescript
interface SelectedBill {
  accountNumber: string;
  billerCode: string;
  billerName: string;
  billerCategory: string;
  outstandingAmount: number;
  dueDate?: string;
  jompayBillerCode?: string;
  jompayRef2?: string;
}

type BillSelectionResult =
  | { status: "success"; selectedBills: SelectedBill[]; totalAmount: number }
  | { status: "cancelled" }
  | { status: "error"; error: string };

Complete Example (Web)

typescript
import { BillPresentmentSDK } from "@iimmpact/billpresentment-sdk";

async function showBills(sessionToken: string) {
  const sdk = new BillPresentmentSDK({
    sessionToken,
    displayMode: "modal",
  });

  const result = await sdk.open();

  if (result.status === "success") {
    sessionStorage.setItem("selectedBills", JSON.stringify(result.selectedBills ?? []));
    sessionStorage.setItem("totalAmount", String(result.totalAmount ?? 0));
    window.location.href = "/pay";
    return;
  }

  if (result.status === "cancelled") {
    return;
  }

  console.error("Failed to collect bill selection:", result.error);
}

showBills(sessionTokenFromBackend);

Backend Example (Node.js)

typescript
import { createHash, createHmac, randomUUID } from "node:crypto";

const API_BASE_URL = "https://api.iimmpact.com";

type CreateSessionInput = {
  ic_number: string;
  name?: string;
  email?: string;
  phone?: string;
  address?: string;
};

function sha256Base64(value: string): string {
  return createHash("sha256").update(value).digest("base64");
}

export async function createSdkSession(input: CreateSessionInput) {
  const apiKey = process.env.IIMMPACT_API_KEY;
  const hmacSecretBase64 = process.env.IIMMPACT_HMAC_SECRET_BASE64;

  if (!apiKey || !hmacSecretBase64) {
    throw new Error("Missing IIMMPACT API credentials");
  }

  const method = "POST";
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonce = randomUUID().toLowerCase();
  const query = "";
  const body = JSON.stringify(input);
  const bodyHash = sha256Base64(body);
  const canonical = `v1:${timestamp}:${nonce}:${method}:${query}:${bodyHash}`;
  const hmacKey = Buffer.from(hmacSecretBase64, "base64");
  const signature = createHmac("sha256", hmacKey).update(canonical).digest("base64");

  const response = await fetch(`${API_BASE_URL}/v2/sdk/sessions`, {
    method,
    headers: {
      "Content-Type": "application/json",
      "X-Api-Key": apiKey,
      "X-Timestamp": timestamp,
      "X-Nonce": nonce,
      "X-Signature": `v1=${signature}`,
    },
    body,
  });

  if (!response.ok) {
    throw new Error(`Session creation failed (${response.status})`);
  }

  return (await response.json()) as {
    session_token: string;
    expires_at: string;
  };
}

Next Steps

  • Authentication -- Full auth flow, token lifecycle, and bill set validation
  • Web SDK -- Full configuration options and display modes
  • React Native SDK -- Component props and platform-specific handling

IIMMPACT API Documentation