Skip to content

Quickstart

This page takes you through the entire payment loop in the sandbox: create a transaction, settle it on the fake BCA with simulate-pay, and verify the signed callback. Nothing here touches real money.

You need three things from your merchant account (ask your Incognito Payments administrator, or read them from your merchant dashboard):

Credential Example Used for
Merchant code M0001 Identifies you; part of the request signature.
Sandbox API key DEV-xxxxxxxx… Authorization: Bearer header. Starts with DEV-.
Sandbox private key devsk-xxxxxxxx… Signs requests and verifies callbacks. Secret.
Section titled “1. Install an SDK (optional but recommended)”
Terminal window
# Private install from GitHub Packages — see the Node.js SDK page for the .npmrc
npm install @incognitoasia/payments

Send your order reference and the amount you want to charge. We add a unique 3-digit code to the amount so the transfer can be matched automatically, and return the exact pay_amount the customer must transfer.

import { IncognitoPayments } from "@incognitoasia/payments";
const payments = new IncognitoPayments({
apiKey: process.env.INCOGNITO_PAYMENTS_API_KEY!, // DEV-… sandbox key
privateKey: process.env.INCOGNITO_PAYMENTS_PRIVATE_KEY!,
merchantCode: "M0001",
// baseUrl defaults to https://payment.incognito.asia
});
const tx = await payments.createTransaction({
merchantRef: "ORDER-1001",
amount: 150000, // what you want to receive, in IDR
customerName: "Budi Santoso",
customerEmail: "budi@example.com",
callbackUrl: "https://yourapp.com/webhooks/incognito",
});
console.log(tx.reference); // e.g. DEV-T... (sandbox references are DEV-prefixed)
console.log(tx.pay_amount); // 150076 ← customer transfers EXACTLY this
console.log(tx.pay_code); // "076"
console.log(tx.checkout_url); // hosted payment page you can redirect to

The response is the standard envelope; data holds the transaction:

{
"success": true,
"message": "",
"data": {
"reference": "DEV-T8K2P9ABC123",
"merchant_ref": "ORDER-1001",
"payment_method": "BCA",
"amount": 150000,
"pay_amount": 150076,
"amount_total": 150076,
"total_amount": 150076,
"pay_code": "076",
"unique_code": 76,
"bank": { "name": "BCA", "account_number": "6485415487", "account_name": "…" },
"checkout_url": "https://payment.incognito.asia/pay/…",
"status": "UNPAID",
"expired_time": 1731600000
}
}

3. Settle it on the fake BCA (sandbox only)

Section titled “3. Settle it on the fake BCA (sandbox only)”

Instead of actually transferring money, tell the sandbox to pretend the customer paid. This runs the same match engine the real robot uses and fires your callback.

const settled = await payments.simulatePayment(tx.reference);
console.log(settled.status); // "PAID"
console.log(settled.paid); // true

Moments later, we POST a signed JSON body to your callback_url. Verify the X-Callback-Signature header against the raw request body using your private key, then reply {"success": true}.

import express from "express";
const app = express();
// Capture the RAW body — signature is computed over exact bytes.
app.post(
"/webhooks/incognito",
express.raw({ type: "application/json" }),
(req, res) => {
const raw = req.body.toString("utf8");
const ok = payments.verifyCallback(raw, req.header("X-Callback-Signature") ?? "");
if (!ok) return res.status(403).json({ success: false });
const event = JSON.parse(raw);
if (event.status === "PAID") {
// ✅ mark event.merchant_ref as paid
}
return res.json({ success: true });
},
);

That's the whole loop

Create → settle → signed callback → fulfil. Swap your DEV- key for the PROD- key and point customers at real transfers, and the same code runs in production.