Back-End Integration
Complete server-side integration guide: query order limits, generate payment orders, lock crypto rates, create on-chain QR codes, and query transaction reconciliation states.
Authentication & credential mapping
Every server-to-server call against Hashpay transaction endpoints requires your Secret Key sent in the api-key header. Never expose your Secret Key in client-side code, mobile bundles, or public repositories:
| Parameter | HTTP Header / Field | Description & Source |
|---|---|---|
| Secret Key | api-key: <YOUR_SECRET_KEY> | Your confidential merchant secret key. Located in Dashboard → Settings → API Keys. |
| Merchant ID | merchant_id: "10001" | Your public merchant identifier. Located in Dashboard → Settings → API Keys. |
| Order Number | order_no / transactionID | Your system's unique alphanumeric reference (e.g., INV-2026-0001). Reused consistently across calls. |
| Billing Amount | amount: "150000" | The fiat charge in IDR as an integer numeric string (without decimal points). |
| Token Contract | tokenAddress | Smart contract / mint address of the stablecoin, retrieved via GET /listToken. |
| Blockchain Network | network | Target blockchain network: ETHEREUM, BNB Chain, TRON, or SOLANA. |
Step 0 — Check dynamic order limits (Pre-flight)
/orderLimits?merchant_id={merchant_id}Before presenting payment options or creating an order, query your store's configured order limits. Hashpay calculates minimum order thresholds dynamically to ensure transaction amounts cover MDR fees and network gas costs:
curl -X GET "https://api.hashpay.id/v2/mainnet/orderLimits?merchant_id=10001" \
-H "api-key: sec_live_9f83b27a8e..."{
"status_code": 200,
"message": "success",
"data": {
"merchant_id": "10001",
"currency": "IDR",
"min_order_amount": "10000.00",
"max_order_amount": "500000000.00",
"mdr_fee_percent": "0.50"
}
}Step 1 — Create an order (Both paths)
/merchant/fiat/orderThe primary entry point for both Path A (Hosted Page) and Path B (Direct API). Creates an active order record in the Hashpay system and issues an order-scoped checkout credential:
curl -X POST "https://api.hashpay.id/v2/mainnet/merchant/fiat/order" \
-H "api-key: sec_live_9f83b27a8e..." \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "10001",
"order_no": "INV-2026-0001",
"amount": "150000",
"name": "Budi Santoso",
"email": "budi@example.com",
"phone": "081234567890",
"products": [
{ "name": "Specialty Coffee Beans 250g", "price": 150000, "quantity": 1 }
]
}'import axios from "axios";
interface CreateOrderResponse {
status_code: number;
message: string;
data: {
request: {
order_no: string;
merchant_id: string;
amount: string;
currency: string;
status: string;
};
url: string;
key: string;
expired_at: number;
};
}
async function createHashpayOrder(orderNo: string, amountIdr: number, customerEmail: string) {
const response = await axios.post<CreateOrderResponse>(
"https://api.hashpay.id/v2/mainnet/merchant/fiat/order",
{
merchant_id: process.env.HASHPAY_MERCHANT_ID,
order_no: orderNo,
amount: amountIdr.toString(),
email: customerEmail,
},
{
headers: {
"api-key": process.env.HASHPAY_SECRET_KEY,
"Content-Type": "application/json",
},
}
);
return response.data.data;
}use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'api-key' => config('services.hashpay.secret_key'),
'Content-Type' => 'application/json',
])->post('https://api.hashpay.id/v2/mainnet/merchant/fiat/order', [
'merchant_id' => config('services.hashpay.merchant_id'),
'order_no' => 'INV-2026-0001',
'amount' => '150000',
'name' => 'Budi Santoso',
'email' => 'budi@example.com',
]);
if ($response->successful()) {
$data = $response->json('data');
// For Path A: redirect customer to $data['url']
return redirect($data['url']);
}{
"status_code": 201,
"message": "success",
"data": {
"request": {
"order_no": "INV-2026-0001",
"merchant_id": "10001",
"amount": "150000",
"currency": "IDR",
"status": "Created"
},
"url": "https://webview.hashpay.id/sandbox?key=pl_eyJhbGciOi...",
"key": "pl_eyJhbGciOi...",
"expired_at": 1821387856
}
}Path B — Direct API (Build your own checkout UI)
If your application renders custom payment UI components instead of opening Hashpay's hosted webview, execute steps 2, 3, and 4 on your server:
Step 2 — Retrieve supported tokens & wallets
/listToken?merchant_id={merchant_id}Returns all active stablecoins (USDT, USDC), blockchain networks (Ethereum, BNB Chain, Tron, Solana), contract addresses, decimals, and supported wallet options configured for your merchant account:
curl -X GET "https://api.hashpay.id/v2/mainnet/listToken?merchant_id=10001" \
-H "api-key: sec_live_9f83b27a8e..."{
"status_code": 200,
"message": "success",
"data": [
{
"walletType": "METAMASK",
"walletIcon": "https://assets.hashpay.id/wallets/metamask.png",
"tokenDetails": [
{
"name": "USDT",
"network": "BNB Chain",
"tokenAddress": "0x55d398326f99059fF775485246999027B3197955",
"icon": "https://assets.hashpay.id/tokens/usdt.png",
"decimals": 18,
"chainId": 56
},
{
"name": "USDT",
"network": "TRON",
"tokenAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"icon": "https://assets.hashpay.id/tokens/usdt.png",
"decimals": 6,
"chainId": 728126428
}
]
}
]
}Step 3 — Lock exchange rate & compute fees
/merchant/fiat/checkOrderRateLocks the real-time cryptocurrency exchange rate for 15 minutes and calculates the exact crypto amount required. Use the tokenAddress and network obtained from Step 2, and supply your order_no as transactionID:
curl -X POST "https://api.hashpay.id/v2/mainnet/merchant/fiat/checkOrderRate" \
-H "api-key: sec_live_9f83b27a8e..." \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "10001",
"transactionID": "INV-2026-0001",
"tokenAddress": "0x55d398326f99059fF775485246999027B3197955",
"network": "BNB Chain"
}'{
"status_code": 200,
"message": "success",
"data": {
"order_no": "INV-2026-0001",
"merchant_id": "10001",
"status": "Created",
"currency": "IDR",
"amount": "150000",
"amount_crypto": "9.200000",
"crypto_rate": "16304.34",
"is_direct_deposit": false,
"merchant_fees": [
{
"name": "MDR Platform Fee",
"fee_type": "PERCENT",
"fee_value": "0.50",
"fee_amount": "750.00",
"fee_amount_crypto": "0.046000",
"is_included": true
}
],
"total_fee_amount_merchant": "750.00",
"total_fee_amount_crypto_merchant": "0.046000",
"merchant_received_amount": "149250.00",
"merchant_received_amount_crypto": "9.154000",
"fees": [],
"total_fee_amount": "0.00",
"total_fee_amount_crypto": "0.000000",
"total_amount": "150000.00",
"total_amount_crypto": "9.200000"
}
}Step 4 — Generate on-chain QR & destination address
/pgqr/fiat/createGenerates the dynamic, payment-ready QR code data. Returns an EIP-681 standard wallet URI (qrValue) and the exact destination blockchain deposit address:
curl -X POST "https://api.hashpay.id/v2/mainnet/pgqr/fiat/create" \
-H "api-key: sec_live_9f83b27a8e..." \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "10001",
"transactionID": "INV-2026-0001",
"tokenAddress": "0x55d398326f99059fF775485246999027B3197955",
"network": "BNB Chain",
"walletType": "METAMASK"
}'{
"status_code": 200,
"message": "success",
"data": {
"qrValue": "ethereum:0x55d398326f99059fF775485246999027B3197955@56/transfer?address=0x2AC2223419f32a6Aab57D9d4cb3210C97Bc62d51&uint256=9200000000000000000",
"request": {
"order_no": "INV-2026-0001",
"merchantID": "10001",
"tokenName": "USDT",
"network": "BNB Chain",
"walletType": "METAMASK",
"destinationAddress": "0x2AC2223419f32a6Aab57D9d4cb3210C97Bc62d51",
"amount": "9.200000",
"totalAmount": "9.200000",
"totalAmountFiat": "150000.00",
"uniqueCode": "0",
"expiredAt": 1821388756,
"is_direct_deposit": false
}
}
}Step 5 — Query order status & reconciliation (Fallback)
/merchant/fiat/getOrderWhile webhooks are the primary delivery channel for payment events, use getOrder as an on-demand reconciliation fallback (for example, if your webhook endpoint experienced downtime or when verifying an invoice status during customer support inquiries):
curl -X POST "https://api.hashpay.id/v2/mainnet/merchant/fiat/getOrder" \
-H "api-key: sec_live_9f83b27a8e..." \
-H "Content-Type: application/json" \
-d '{
"merchant_id": "10001",
"order_no": "INV-2026-0001"
}'{
"status_code": 200,
"message": "success",
"data": {
"order_no": "INV-2026-0001",
"merchant_id": "10001",
"merchant_name": "Toko Sejahtera Bersama",
"currency": "IDR",
"amount": "150000",
"status": "Success",
"paid_amount": "9.200000",
"total_amount": "9.200000",
"total_amount_fiat": "150000.00",
"tx_hash": "0x3a7e28b14c995f088127394c8b66da982341209b0a1d48293c834017834bcdef",
"link_explorer": "https://bscscan.com/tx/0x3a7e28b14c995f088127394c8b66da982341209b0a1d48293c834017834bcdef",
"expired_at": 1821388756,
"createdAt": "2026-10-23T10:15:00Z",
"updatedAt": "2026-10-23T10:16:42Z"
}
}