Developer gateway untuk QRIS dinamis

Welcome to BabyGo Documentations

Integrasikan QRIS payment infrastructure BabyGo ke sistem kamu. Buat invoice QRIS dinamis, validasi pembayaran via reference, dan terima notifikasi real-time via webhook.

REST + JSONx-client-api-keyWebhook HMACReference Matching

Integration Snapshot

Siap dipakai developer

Base URL
api-v2.babygo.my.id
Auth
x-client-api-key
Format
REST + JSON
Webhook
HMAC-SHA256

Recommended Flow

1Buat invoice QRIS
2Validasi reference
3Terima webhook real-time

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

SUCCESS
// Sukses
{ "data": { ... } }
ERROR
// Gagal
{ "error": { "code": "invalid_amount", "message": "Nominal invoice harus bilangan bulat positif" } }

Authentication

Semua request ke Gateway API harus menyertakan header x-client-api-key. Dapatkan API Key dari Dashboard → Settings → Workspace API Key.

Header yang diperlukan

HEADER
x-client-api-key: pg_yfLDvlMPKpZewjyGtwxdm0VA

Contoh request dengan auth

BASH
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

Dari daftar sampai QRIS dinamis berjalan, kamu butuh kurang dari 10 menit.
01

Daftar & Hubungkan QRIS GoPay Merchant

Buat akun BabyGo, masuk ke halaman Merchant, dan hubungkan akun GoPay Merchant via OTP. Selesai dalam menit.

02

Copy API Key dari Settings

Buka Dashboard → Settings → Workspace Key. Copy API Key (format: pg_...) dan simpan di environment variable server kamu.

03

POST /api/gateway/checkout — Buat Invoice

Kirim merchantConnectionId dan amount. Simpan referenceLabel yang dibuat BabyGo dari response checkout.

04

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
POST/api/gateway/checkout x-client-api-key

Buat invoice QRIS dinamis untuk transaksi baru. Endpoint utama untuk memulai flow pembayaran.

Biarkan BabyGo generate referenceLabel otomatis. Simpan value dari response checkout untuk lookup berikutnya; gunakan externalReference kalau butuh mapping order internal.

Request Body

JSON
{
  "merchantConnectionId": "mconn_1b89cd0664c54293a1bdee9972b2bffb",
  "amount": 50000,
  "externalReference": "ORDER-001",
  "description": "Pembayaran Order #001",
  "expiresInMinutes": 30
}
BASH
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
  }'
GET/api/gateway/transactions/:referenceLabel x-client-api-key

Ambil detail invoice berdasarkan referenceLabel yang dikembalikan BabyGo saat checkout.

Gunakan endpoint ini untuk polling status sebelum webhook aktif, atau sebagai fallback.
BASH
curl --request GET \
  --url "https://api-v2.babygo.my.id/api/gateway/transactions/BBYG-231504S261404K0FFFF4A7B4c8BT" \
  --header "x-client-api-key: YOUR_API_KEY"
POST/api/gateway/transactions/:referenceLabel/check-status x-client-api-key

Trigger rekonsiliasi manual — cocokkan invoice dengan riwayat transaksi GoPay secara on-demand.

Gunakan jika webhook belum di-setup atau sebagai fallback. `matched: true` artinya pembayaran sudah tervalidasi.
BASH
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"
POST/api/gateway/transactions/:referenceLabel/cancel x-client-api-key

Batalkan invoice yang masih dalam status pending. Invoice yang sudah paid tidak bisa dibatalkan.

BASH
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)

Endpoint ini tidak butuh auth apapun. Cocok untuk embed langsung di halaman pembayaran customer. Response bukan JSON — melainkan image/svg+xml.
GET/api/public/invoices/:invoiceId/qrNo Auth

Render QRIS sebagai gambar SVG. invoiceId didapat dari response POST /checkout.

BASH
curl "https://api-v2.babygo.my.id/api/public/invoices/inv_6a9cfc67.../qr"
RESPONSE HEADERS
HTTP/1.1 200 OK
Content-Type: image/svg+xml; charset=utf-8
Cache-Control: public, max-age=300

Embed di HTML

HTML
<img
  src="https://api-v2.babygo.my.id/api/public/invoices/{invoiceId}/qr"
  alt="Scan QRIS untuk membayar"
  width="256"
  height="256"
/>

Webhooks

Konfigurasi webhook URL di Dashboard → Settings → Webhook. BabyGo mengirim payload HMAC-signed ke endpoint kamu saat salah satu event terjadi.

Daftar Events

invoice.paid

Invoice berhasil dicocokkan dengan transaksi GoPay yang valid.

invoice.cancelled

Invoice dibatalkan (via API atau expired dan sudah di-cancel manual).

invoice.expired

Invoice kadaluarsa sebelum ada pembayaran yang cocok.

transaction.received

Ada transaksi masuk dari GoPay — mungkin belum tentu cocok dengan invoice apapun.

Webhook Payload (Real Shape)

Headers yang dikirim BabyGo

HEADERS
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/json

Header 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.

JSON PAYLOAD
{
  "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

Selalu verifikasi signature sebelum memproses webhook! Tanpa verifikasi, sistem kamu rentan terhadap spoofed request. BabyGo menggunakan HMAC-SHA256 dengan secret yang kamu set di Settings.

Cara kerja signature

1

BabyGo generates timestamp

ISO 8601 UTC string (contoh: 2026-04-13T08:15:30.123Z) saat webhook dikirim. Dikirim via header X-Callback-Timestamp.

2

BabyGo builds signing payload

payload = timestamp + "." + rawBodyString

3

BabyGo computes HMAC

v1=HMAC_SHA256_HEX(webhookSecret, timestamp + "." + rawBodyString) — dikirim via X-Signature.

4

Kamu verifikasi

Hitung ulang signature (termasuk prefix v1=). Bandingkan dengan header pakai timing-safe equal untuk mencegah timing attack. Gunakan RAW BODY asli.

5

Tolak jika timestamp expired

Cek selisih timestamp sekarang dengan X-Callback-Timestamp. Batas maksimum 5 menit untuk replay attack prevention.

Node.js (Express)
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

Runtime BabyGo memakai 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

400invalid_amountNominal invoice tidak valid; harus integer positif.
400invalid_webhook_urlWebhook URL kosong, tidak valid, atau tidak HTTPS.
400invalid_webhook_secretWebhook secret tidak memenuhi syarat minimal.
401missing_client_api_keyHeader x-client-api-key atau bearer API key tidak dikirim.
401invalid_client_api_keyAPI key client tidak valid.
401client_api_key_revokedAPI key sudah dinonaktifkan.
401client_api_key_expiredAPI key sudah kedaluwarsa.
403client_suspendedWorkspace client tidak aktif untuk akses gateway.
403workspace_suspendedWorkspace ditangguhkan dan tidak bisa dipakai untuk operasi baru.
403subscription_inactiveWorkspace belum punya langganan aktif atau sudah habis.
403subscription_plan_invalidPlan workspace belum valid untuk operasi gateway.
403insufficient_api_key_scopeAPI key tidak punya scope yang dibutuhkan endpoint.
404not_foundRoute API tidak ditemukan.
404invoice_not_foundInvoice atau referenceLabel tidak ditemukan di workspace ini.
404invoice_qr_not_availableQRIS string untuk invoice tidak tersedia.
409workspace_migratingWorkspace sedang dipindahkan antar shard; coba lagi nanti.
409missing_static_qris_payloadMerchant belum punya static QRIS yang bisa dikonversi.
409merchant_not_connectedMerchant connection belum aktif saat create atau process invoice.
409merchant_not_authenticatedToken upstream merchant belum tersedia atau perlu reconnect.
409merchant_missing_merchant_idMerchant belum punya merchant_id hasil sinkronisasi.
409invoice_already_paidInvoice yang sudah paid tidak bisa dibatalkan.
400missing_webhook_urlWebhook diaktifkan tanpa URL.
400missing_webhook_secretWebhook diaktifkan tanpa secret.
429rate_limitedRate limit terlampaui; ikuti retry-after dan header rate limit.
500internal_server_errorError internal tak terduga di sisi BabyGo.
500reference_label_generation_failedBackend gagal membuat referenceLabel otomatis yang unik.
4xx/5xxbaby_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.