Overview
Gateway API
API utama untuk integrasi. Buat invoice, cek status, dan batalkan transaksi via REST.
Webhook Events
Notifikasi real-time saat invoice.paid / cancelled / expired atau transaction.received.
Public QR API
Embed gambar QRIS SVG langsung tanpa auth — cocok untuk halaman pembayaran customer.
Response Envelope
// Sukses
{ "data": { ... } }// Gagal
{ "error": { "code": "invalid_amount", "message": "Nominal invoice harus bilangan bulat positif" } }Authentication
x-client-api-key. Dapatkan API Key dari Dashboard → Settings → Workspace API Key.Header yang diperlukan
x-client-api-key: pg_yfLDvlMPKpZewjyGtwxdm0VAContoh request dengan auth
curl --request POST \
--url "https://api-v2.babygo.my.id/api/gateway/checkout" \
--header "x-client-api-key: pg_YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{ ... }'Quickstart — Integration in 4 Steps
Daftar & Hubungkan QRIS GoPay Merchant
Buat akun BabyGo, masuk ke halaman Merchant, dan hubungkan akun GoPay Merchant via OTP. Selesai dalam menit.
Copy API Key dari Settings
Buka Dashboard → Settings → Workspace Key. Copy API Key (format: pg_...) dan simpan di environment variable server kamu.
POST /api/gateway/checkout — Buat Invoice
Kirim merchantConnectionId dan amount. Simpan referenceLabel yang dibuat BabyGo dari response checkout.
Terima Webhook invoice.paid
Setup endpoint di Settings → Webhook. BabyGo kirim callback HMAC-signed ke endpoint kamu saat pembayaran berhasil.
Gateway Endpoints
Auth: x-client-api-key/api/gateway/checkout x-client-api-keyBuat invoice QRIS dinamis untuk transaksi baru. Endpoint utama untuk memulai flow pembayaran.
Request Body
{
"merchantConnectionId": "mconn_1b89cd0664c54293a1bdee9972b2bffb",
"amount": 50000,
"externalReference": "ORDER-001",
"description": "Pembayaran Order #001",
"expiresInMinutes": 30
}curl --request POST \
--url "https://api-v2.babygo.my.id/api/gateway/checkout" \
--header "x-client-api-key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"merchantConnectionId": "mconn_1b89cd...",
"amount": 50000,
"externalReference": "ORDER-001",
"description": "Pembayaran Order #001",
"expiresInMinutes": 30
}'/api/gateway/transactions/:referenceLabel x-client-api-keyAmbil detail invoice berdasarkan referenceLabel yang dikembalikan BabyGo saat checkout.
curl --request GET \
--url "https://api-v2.babygo.my.id/api/gateway/transactions/BBYG-231504S261404K0FFFF4A7B4c8BT" \
--header "x-client-api-key: YOUR_API_KEY"/api/gateway/transactions/:referenceLabel/check-status x-client-api-keyTrigger rekonsiliasi manual — cocokkan invoice dengan riwayat transaksi GoPay secara on-demand.
curl --request POST \
--url "https://api-v2.babygo.my.id/api/gateway/transactions/BBYG-231504S261404K0FFFF4A7B4c8BT/check-status" \
--header "x-client-api-key: YOUR_API_KEY"/api/gateway/transactions/:referenceLabel/cancel x-client-api-keyBatalkan invoice yang masih dalam status pending. Invoice yang sudah paid tidak bisa dibatalkan.
curl --request POST \
--url "https://api-v2.babygo.my.id/api/gateway/transactions/BBYG-231504S261404K0FFFF4A7B4c8BT/cancel" \
--header "x-client-api-key: YOUR_API_KEY"QRIS QR Image (Public)
image/svg+xml./api/public/invoices/:invoiceId/qrNo AuthRender QRIS sebagai gambar SVG. invoiceId didapat dari response POST /checkout.
curl "https://api-v2.babygo.my.id/api/public/invoices/inv_6a9cfc67.../qr"HTTP/1.1 200 OK
Content-Type: image/svg+xml; charset=utf-8
Cache-Control: public, max-age=300Embed di HTML
<img
src="https://api-v2.babygo.my.id/api/public/invoices/{invoiceId}/qr"
alt="Scan QRIS untuk membayar"
width="256"
height="256"
/>Webhooks
Daftar Events
invoice.paidInvoice berhasil dicocokkan dengan transaksi GoPay yang valid.
invoice.cancelledInvoice dibatalkan (via API atau expired dan sudah di-cancel manual).
invoice.expiredInvoice kadaluarsa sebelum ada pembayaran yang cocok.
transaction.receivedAda transaksi masuk dari GoPay — mungkin belum tentu cocok dengan invoice apapun.
Webhook Payload (Real Shape)
Headers yang dikirim BabyGo
X-Signature: v1=3d8f1d7f...
X-Callback-Timestamp: 2026-04-12T14:57:26.846Z
X-Callback-Id: cb_c7639f229b4a4876a6dd5cd58dc74d57
X-Callback-Event: invoice.paid
X-Client-Code: BG-FEV2DOCS-9B95BA
Content-Type: application/jsonHeader canonical runtime BabyGo adalah X-Signature, X-Callback-Timestamp, X-Callback-Id, dan X-Callback-Event. Nama x-babygo-signature dan x-babygo-timestamp bukan header runtime BabyGo saat ini. Saat secret sedang rotasi, BabyGo juga bisa mengirim X-Signature-Previous dan X-Signature-Previous-Expires-At sebagai compatibility-only grace window.
{
"callbackId": "cb_c7639f229b4a4876a6dd5cd58dc74d57",
"event": "invoice.paid",
"occurredAt": "2026-04-12T14:57:26.846Z",
"client": {
"id": "cli_aa5f...",
"code": "BG-FEV2DOCS-9B95BA",
"name": "FE V2 Workspace"
},
"invoice": {
"id": "inv_8097...",
"referenceLabel": "BBYG-231504S261404K0FFFF4A7B4c8BT",
"externalReference": "ORDER-001",
"amount": 50000,
"currency": "IDR",
"status": "paid",
"paidAt": "2026-04-12T14:57:26.169Z",
"merchantConnectionId": "mconn_1b89..."
},
"merchant": {
"connectionId": "mconn_1b89...",
"merchantId": "G269716353",
"merchantName": "Demo Merchant Store",
"userFullName": "Demo Merchant User",
"phoneNumber": "81234567890"
},
"transaction": {
"transactionReferenceNumber": "QRREF-DEMO-001",
"referenceLabel": "BBYG-231504S261404K0FFFF4A7B4c8BT",
"amount": 50000,
"currency": "IDR",
"status": "success",
"paymentType": "qris",
"procedure": "offline_dynamic",
"channelType": "DYNAMIC_QR",
"issuer": "gopay",
"transactionTime": "2026-04-12T10:12:00.000Z",
"settlementTime": "2026-04-12T10:12:20.000Z"
}
}Webhook Signature Verification
Cara kerja signature
BabyGo generates timestamp
ISO 8601 UTC string (contoh: 2026-04-13T08:15:30.123Z) saat webhook dikirim. Dikirim via header X-Callback-Timestamp.
BabyGo builds signing payload
payload = timestamp + "." + rawBodyString
BabyGo computes HMAC
v1=HMAC_SHA256_HEX(webhookSecret, timestamp + "." + rawBodyString) — dikirim via X-Signature.
Kamu verifikasi
Hitung ulang signature (termasuk prefix v1=). Bandingkan dengan header pakai timing-safe equal untuk mencegah timing attack. Gunakan RAW BODY asli.
Tolak jika timestamp expired
Cek selisih timestamp sekarang dengan X-Callback-Timestamp. Batas maksimum 5 menit untuk replay attack prevention.
import crypto from "node:crypto";
import express from "express";
const app = express();
const WEBHOOK_SECRET = process.env.BABYGO_WEBHOOK_SECRET;
function verifyBabyGoSignature({ rawBody, signature, timestamp, secret }) {
const expected = "v1=" + crypto
.createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex");
const left = Buffer.from(signature || "", "utf8");
const right = Buffer.from(expected, "utf8");
if (left.length !== right.length) return false;
return crypto.timingSafeEqual(left, right);
}
app.post(
"/webhooks/babygo",
express.raw({ type: "application/json" }),
async (req, res) => {
const rawBody = req.body.toString("utf8");
const signature = req.get("X-Signature");
const timestamp = req.get("X-Callback-Timestamp");
const callbackId = req.get("X-Callback-Id");
const eventHeader = req.get("X-Callback-Event");
if (!signature || !timestamp || !callbackId) {
return res.status(401).json({ error: "Missing required headers" });
}
const ok = verifyBabyGoSignature({ rawBody, signature, timestamp, secret: WEBHOOK_SECRET });
if (!ok) {
return res.status(401).json({ error: "Invalid signature" });
}
const ageMs = Math.abs(Date.now() - new Date(timestamp).getTime());
if (Number.isNaN(ageMs) || ageMs > 5 * 60 * 1000) {
return res.status(401).json({ error: "Timestamp expired" });
}
const payload = JSON.parse(rawBody);
const event = eventHeader || payload.event;
console.log("Verified event:", event);
return res.json({ ok: true });
}
);Error Reference
lowercase_snake_case pada error.code. Validasi schema request dapat berhenti lebih awal dengan response validator Hono/Zod, jadi jangan mengandalkan kode uppercase generik seperti INVALID_REQUEST, UNAUTHORIZED, atau FORBIDDEN.HTTP Status
Error Code
Keterangan
invalid_amountNominal invoice tidak valid; harus integer positif.invalid_webhook_urlWebhook URL kosong, tidak valid, atau tidak HTTPS.invalid_webhook_secretWebhook secret tidak memenuhi syarat minimal.missing_client_api_keyHeader x-client-api-key atau bearer API key tidak dikirim.invalid_client_api_keyAPI key client tidak valid.client_api_key_revokedAPI key sudah dinonaktifkan.client_api_key_expiredAPI key sudah kedaluwarsa.client_suspendedWorkspace client tidak aktif untuk akses gateway.workspace_suspendedWorkspace ditangguhkan dan tidak bisa dipakai untuk operasi baru.subscription_inactiveWorkspace belum punya langganan aktif atau sudah habis.subscription_plan_invalidPlan workspace belum valid untuk operasi gateway.insufficient_api_key_scopeAPI key tidak punya scope yang dibutuhkan endpoint.not_foundRoute API tidak ditemukan.invoice_not_foundInvoice atau referenceLabel tidak ditemukan di workspace ini.invoice_qr_not_availableQRIS string untuk invoice tidak tersedia.workspace_migratingWorkspace sedang dipindahkan antar shard; coba lagi nanti.missing_static_qris_payloadMerchant belum punya static QRIS yang bisa dikonversi.merchant_not_connectedMerchant connection belum aktif saat create atau process invoice.merchant_not_authenticatedToken upstream merchant belum tersedia atau perlu reconnect.merchant_missing_merchant_idMerchant belum punya merchant_id hasil sinkronisasi.invoice_already_paidInvoice yang sudah paid tidak bisa dibatalkan.missing_webhook_urlWebhook diaktifkan tanpa URL.missing_webhook_secretWebhook diaktifkan tanpa secret.rate_limitedRate limit terlampaui; ikuti retry-after dan header rate limit.internal_server_errorError internal tak terduga di sisi BabyGo.reference_label_generation_failedBackend gagal membuat referenceLabel otomatis yang unik.baby_api_errorUpstream Baby API mengembalikan error; details berisi body upstream.Siap Integrasi?
Daftar gratis, hubungkan QRIS GoPay Merchant, dan dapatkan API Key dalam hitungan menit.
