QRIS Payment Gateway API
Satu API untuk bikin invoice, cek status, dan cairkan saldo. Cocok untuk bot Telegram dan toko online.
Reset tiap Senin 00:00 WIB · sisa -
Reset tiap Senin 00:00 WIB · sisa -
Pilih nominal atau ketik sendiri. Fee acak Rp 50–80 ditambahkan ke total bayar.
Bayar sesuai Total Bayar. Saldo masuk otomatis setelah pembayaran terdeteksi.
Minimal Rp 10.000. Fee dipotong dari nominal. Saldo langsung dipotong, pencairan diproses admin.
Kamu belum punya API key.
https://nercay.biz.idx-api-key dan Content-Type: application/json./api/deposit/create, tampilkan QR ke pembeli.total_payment (nominal + fee)./api/deposit/status tiap ±5 detik sampai success. Saldo masuk otomatis.Saldo yang masuk = amount. Fee acak Rp 50–80 ditambahkan ke total_payment.
Kirim API key di header x-api-key. Key dibuat di tab Profil lewat tombol Create APIkey. Satu akun satu key.
expired.Buat invoice QRIS baru. Berlaku 10 menit.
amount integer, nominal deposit (Rp), minimal 7.000
// Request
{ "amount": 7000 }
// Response 200
{
"success": true,
"deposit": {
"id": "WZ-ab12cd34",
"amount": 7000,
"fee": 80,
"total_payment": 7080,
"qr_string": "00020101021226...",
"expired_at": "2026-10-05T10:10:00.000Z"
}
}
Cek status pembayaran invoice.
deposit_id query string. Status: pending, success, expired, canceled
// GET /api/deposit/status?deposit_id=WZ-ab12cd34
// Response 200
{
"success": true,
"deposit_id": "WZ-ab12cd34",
"status": "pending"
}
Batalkan invoice yang masih pending.
deposit_id string, ID invoice
// Request
{ "deposit_id": "WZ-ab12cd34" }
// Response 200
{
"success": true,
"message": "Transaksi dibatalkan",
"status": "canceled"
}
Cek saldo dan data akun pemilik API key.
// Response 200
{
"success": true,
"user": {
"username": "nerc",
"email": "kamu@email.com",
"balance": 50000,
"totalDeposit": 50000,
"totalWithdraw": 0
},
"stats": { "totalUsers": 42 }
}
Kami kirim POST JSON ke URL webhook kamu saat pembayaran sukses. Balas HTTP 200 kalau sudah diterima.
{
"event": "deposit.success",
"deposit_id": "WZ-ab12cd34",
"amount": 7000,
"fee": 80,
"total_payment": 7080,
"paid_at": "2026-10-05T10:03:21.000Z"
}
Statistik publik, tanpa API key. Dihitung langsung dari database.
// Response 200
{
"success": true,
"totalUsers": 42,
"totalDeposit": 2350000,
"totalWithdraw": 1200000
}
Perintah /deposit 10000: bot membuat invoice, mengirim gambar QR, lalu mengecek status tiap 5 detik sampai lunas. qr_string adalah teks QRIS mentah, jadi bot yang mengubahnya menjadi gambar.
// npm i node-telegram-bot-api qrcode (Node 18+)
const TelegramBot = require("node-telegram-bot-api");
const QRCode = require("qrcode");
const BASE = "https://nercpay.biz.id";
const API_KEY = process.env.NERCPAY_KEY; // jangan ditulis di kode
const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });
const wz = (path, body) => fetch(BASE + path, {
method: body ? "POST" : "GET",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined,
}).then((r) => r.json());
const idr = (n) => "Rp " + n.toLocaleString("id-ID");
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// Pemakaian: /deposit 10000
bot.onText(/^\/deposit (\d+)$/, async (msg, m) => {
const chat = msg.chat.id;
const r = await wz("/api/deposit/create", { amount: Number(m[1]) });
if (!r.success) return bot.sendMessage(chat, "Gagal: " + r.message);
const d = r.deposit;
const png = await QRCode.toBuffer(d.qr_string, { width: 400 });
await bot.sendPhoto(chat, png, {
caption: "Bayar " + idr(d.total_payment) + " (sudah termasuk fee). Berlaku 10 menit.",
});
const until = Date.parse(d.expired_at) + 60000;
while (Date.now() < until) {
await sleep(5000);
const s = await wz("/api/deposit/status?deposit_id=" + d.id);
if (s.status === "success") return bot.sendMessage(chat, "Lunas! Saldo +" + idr(d.amount));
if (s.status === "expired" || s.status === "canceled") break;
}
bot.sendMessage(chat, "Invoice berakhir. Ketik /deposit lagi.");
});# pip install python-telegram-bot httpx "qrcode[pil]"
import os, io, asyncio, httpx, qrcode
from telegram.ext import Application, CommandHandler
BASE = "https://nercpay.biz.id"
HEADERS = {"x-api-key": os.environ["NERCPAY_KEY"]} # jangan ditulis di kode
idr = lambda n: "Rp {:,}".format(n).replace(",", ".")
# Pemakaian: /deposit 10000
async def deposit(update, ctx):
try:
amount = int(ctx.args[0])
except (IndexError, ValueError):
return await update.message.reply_text("Format: /deposit 10000")
async with httpx.AsyncClient(base_url=BASE, headers=HEADERS, timeout=20) as c:
r = (await c.post("/api/deposit/create", json={"amount": amount})).json()
if not r.get("success"):
return await update.message.reply_text("Gagal: " + r.get("message", "?"))
d = r["deposit"]
buf = io.BytesIO()
qrcode.make(d["qr_string"]).save(buf, format="PNG")
buf.seek(0)
await update.message.reply_photo(
buf, caption=f"Bayar {idr(d['total_payment'])} (sudah termasuk fee). Berlaku 10 menit.")
for _ in range(125): # ±10 menit, cek tiap 5 detik
await asyncio.sleep(5)
s = (await c.get("/api/deposit/status", params={"deposit_id": d["id"]})).json()
if s.get("status") == "success":
return await update.message.reply_text("Lunas! Saldo +" + idr(d["amount"]))
if s.get("status") in ("expired", "canceled"):
break
await update.message.reply_text("Invoice berakhir. Ketik /deposit lagi.")
app = Application.builder().token(os.environ["BOT_TOKEN"]).concurrent_updates(True).build()
app.add_handler(CommandHandler("deposit", deposit))
app.run_polling()Format error: {"success":false,"message":"..."}. Endpoint bertanda Segera masih disiapkan, spesifikasi bisa berubah sebelum rilis.