Dokumentasi API

Instanpay menyediakan API pembayaran QRIS dan Crypto (USDT/USDC) untuk merchant Indonesia. Semua endpoint menggunakan format JSON.

Base URLhttps://instanpay.my.id
FormatJSON
Versiv2.0

Autentikasi

Semua permintaan ke endpoint /api/v1/* memerlukan API Key di header.

X-API-Key: sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
Simpan API Key di sisi server. Jangan expose ke browser atau kode client-side.

Rate Limit

Tidak ada batasan rate limit saat ini. Gunakan dengan wajar untuk menjaga stabilitas layanan.

1. Buat Pembayaran QRIS

POST /api/v1/payments

Request

{
  "amount": 10000,
  "customer_name": "Budi Santoso",    // opsional
  "webhook_url": "https://tokomu.com/webhook"  // opsional
}

Response (200)

{
  "success": true,
  "data": {
    "transactionId": "TXN-1751411106-652",
    "qrisString": "0002010102112657...",
    "qrCodeSvg": "<svg>...</svg>",
    "baseAmount": 10000,
    "uniqueCode": 652,
    "totalAmount": 10652,
    "baseFormatted": "Rp 10.000",
    "totalFormatted": "Rp 10.652",
    "expiredAt": "2026-07-14 10:30:00",
    "status": "PENDING"
  }
}
Customer harus membayar totalAmount, bukan baseAmount. Pembayaran tidak sesuai tidak akan terdeteksi.

2. Cek Status Pembayaran QRIS

GET /api/v1/status/:transactionId

GET /api/v1/status/TXN-1751411106-652

Response (200)

{
  "success": true,
  "data": {
    "transactionId": "TXN-1751411106-652",
    "baseAmount": 10000,
    "uniqueCode": 652,
    "totalAmount": 10652,
    "status": "PAID",
    "expiredAt": "2026-07-14 10:30:00",
    "paidAt": "2026-07-14 10:15:22"
  }
}
StatusKeterangan
PENDINGMenunggu pembayaran
PAIDPembayaran berhasil dikonfirmasi
EXPIREDKadaluarsa (2 jam)

Webhook QRIS

Ketika pembayaran QRIS berhasil, sistem mengirim POST ke webhook URL yang dikonfigurasi.

Payload Webhook QRIS

{
  "transactionId": "TXN-1751411106-652",
  "status": "PAID",
  "baseAmount": 10000,
  "uniqueCode": 652,
  "totalAmount": 10652,
  "paidAt": "2026-07-14 10:15:22"
}
Payload QRIS tidak memiliki field type. Gunakan ini untuk membedakan dengan webhook Crypto.

Server Anda harus merespons HTTP 200. Timeout: 10 detik.

Ketentuan QRIS

AturanNilai
Nominal minimumRp 100
Nominal maksimumRp 10.000.000
Format nominalBilangan bulat, tidak boleh desimal
Kode unik500 - 999 (otomatis ditambahkan)
Masa berlaku2 jam sejak dibuat
Saldo yang masukbaseAmount saja (kode unik tidak termasuk)
Contoh: Merchant minta Rp 10.000, sistem tambah kode unik 652, customer bayar Rp 10.652, saldo merchant bertambah Rp 10.000.

3. Buat Order Crypto

POST /api/v1/crypto-payments

ChainTokenJaringan
BSCUSDT, USDCBNB Smart Chain
BASEUSDT, USDCBase (Coinbase L2)
ETHUSDT, USDCEthereum Mainnet
POLYGONUSDT, USDCPolygon PoS
SOLUSDT, USDCSolana
Hanya stablecoin (USDT/USDC). Token native seperti BNB, ETH, SOL, MATIC tidak diterima.

Request

{
  "amount_usd": 5.00,
  "chain": "BSC",
  "token": "USDT",
  "customer_name": "Budi Santoso",   // opsional
  "customer_email": "budi@mail.com"  // opsional
}

Response (200)

{
  "success": true,
  "data": {
    "transactionId": "CRYPTO-1751500000-AB1CD",
    "gatewayOrderId": "ORD_MRKxxxx_XXXXXX",
    "amount_usd": 5.00,
    "chain": "BSC",
    "token": "USDT",
    "deposit_address": "0xAbCd...1234",
    "status": "PENDING",
    "expires_at": "2026-07-14T10:30:00.000Z",
    "payment_url": "https://instanpay.my.id/pay/crypto/ORD_MRKxxxx"
  }
}

Arahkan customer ke payment_url untuk tampilan QR code dan deep link wallet, atau tampilkan deposit_address secara langsung.

4. Cek Status Order Crypto

GET /api/v1/crypto-status/:id

Parameter id bisa berupa transactionId lokal (CRYPTO-xxx) atau gatewayOrderId (ORD_xxx).

GET /api/v1/crypto-status/CRYPTO-1751500000-AB1CD

Response (200)

{
  "success": true,
  "data": {
    "transactionId": "CRYPTO-1751500000-AB1CD",
    "gatewayOrderId": "ORD_MRKxxxx_XXXXXX",
    "amount_usd": 5.00,
    "chain": "BSC",
    "token": "USDT",
    "deposit_address": "0xAbCd...1234",
    "status": "PAID",
    "tx_hash": "0xabc123...def456",
    "amount_received": "5.00",
    "asset_received": "USDT",
    "created_at": "2026-07-14T10:00:00.000Z",
    "expires_at": "2026-07-14T10:30:00.000Z",
    "paid_at": "2026-07-14T10:15:30.000Z",
    "payment_url": "https://instanpay.my.id/pay/crypto/ORD_MRKxxxx"
  }
}
StatusKeterangan
PENDINGMenunggu transfer on-chain
PAIDPembayaran dikonfirmasi on-chain
EXPIREDKadaluarsa (30 menit)

Webhook Crypto

Webhook Crypto dikirim ke URL webhook yang sama dengan QRIS. Bedakan keduanya dengan field type.

Tipe TransaksiPenanda
QRISTidak ada field type
Crypto"type": "CRYPTO"

Payload Webhook Crypto

{
  "transactionId": "CRYPTO-1751500000-AB1CD",
  "status": "PAID",
  "paidAt": "2026-07-14T10:15:30.000Z",
  "type": "CRYPTO",
  "gatewayOrderId": "ORD_MRKxxxx_XXXXXX",
  "amount_usd": 5.00,
  "chain": "BSC",
  "token": "USDT",
  "tx_hash": "0xabc123...def456",
  "amount_received": "5.00",
  "asset_received": "USDT"
}

Contoh Handler (Node.js)

app.post('/webhook', (req, res) => {
  const payload = req.body;

  if (payload.type === 'CRYPTO') {
    // Transaksi crypto
    console.log('Crypto PAID:', payload.amount_usd, payload.token, 'on', payload.chain);
    console.log('TX Hash:', payload.tx_hash);
  } else {
    // Transaksi QRIS (tidak ada field type)
    console.log('QRIS PAID:', payload.totalAmount, '| ID:', payload.transactionId);
  }

  res.sendStatus(200);
});

Ketentuan Crypto

AturanNilai
Nominal minimum$0.01 USD
Token yang diterimaUSDT, USDC
Masa berlaku30 menit sejak dibuat
Toleransi pembayaran+/- 1% (misal order $5.00, bayar $4.95 = PAID)
Saldo yang masukamount_usd x 100 (contoh: $5.00 = +500 unit)

Kode Error

HTTPKeterangan
200Berhasil
400Parameter tidak valid
401API Key tidak valid atau tidak ada
404Transaksi tidak ditemukan
500Internal server error
503Server monitor atau crypto gateway offline

Contoh Kode

QRIS - Node.js

const axios = require('axios');
const apiKey = 'sk_live_xxxx';

// Buat pembayaran QRIS
const res = await axios.post('https://instanpay.my.id/api/v1/payments',
  { amount: 10000, customer_name: 'Budi' },
  { headers: { 'X-API-Key': apiKey } }
);
const { transactionId, qrCodeSvg, totalFormatted } = res.data.data;

// Cek status
const status = await axios.get(
  'https://instanpay.my.id/api/v1/status/' + transactionId,
  { headers: { 'X-API-Key': apiKey } }
);
console.log(status.data.data.status); // PENDING | PAID | EXPIRED

Crypto - Node.js

const axios = require('axios');
const apiKey = 'sk_live_xxxx';

// Buat order crypto
const res = await axios.post('https://instanpay.my.id/api/v1/crypto-payments',
  { amount_usd: 5.00, chain: 'BSC', token: 'USDT' },
  { headers: { 'X-API-Key': apiKey } }
);
const { transactionId, deposit_address, payment_url } = res.data.data;
console.log('Arahkan customer ke:', payment_url);

// Cek status
const status = await axios.get(
  'https://instanpay.my.id/api/v1/crypto-status/' + transactionId,
  { headers: { 'X-API-Key': apiKey } }
);
console.log(status.data.data.status); // PENDING | PAID | EXPIRED

QRIS - PHP

$ch = curl_init('https://instanpay.my.id/api/v1/payments');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode(['amount' => 10000]),
  CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-API-Key: sk_live_xxxx'],
  CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true)['data'];
echo "Total bayar: " . $data['totalFormatted'];

Crypto - PHP

$ch = curl_init('https://instanpay.my.id/api/v1/crypto-payments');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode(['amount_usd' => 5.00, 'chain' => 'BSC', 'token' => 'USDT']),
  CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-API-Key: sk_live_xxxx'],
  CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true)['data'];
echo "Deposit: " . $data['deposit_address'];
echo "URL: " . $data['payment_url'];

QRIS - Python

import requests
headers = {'X-API-Key': 'sk_live_xxxx'}
r = requests.post('https://instanpay.my.id/api/v1/payments',
    json={'amount': 10000}, headers=headers)
data = r.json()['data']
print(f"Bayar: {data['totalFormatted']}")

Crypto - Python

import requests
headers = {'X-API-Key': 'sk_live_xxxx'}
r = requests.post('https://instanpay.my.id/api/v1/crypto-payments',
    json={'amount_usd': 5.00, 'chain': 'BSC', 'token': 'USDT'},
    headers=headers)
data = r.json()['data']
print(f"Deposit: {data['deposit_address']}")
print(f"URL Bayar: {data['payment_url']}")
Unduh Dokumentasi (.txt)