BayarBayar.in

BayarBayar.in Payment API · v2.0

Terima pembayaran QRIS dari aplikasi Anda

Diperbarui 30 Juli 2026 · Base URL: https://boosbayar.com

Satu panduan lengkap untuk membuat tagihan, mengarahkan pelanggan ke halaman pembayaran, menerima pemberitahuan pembayaran, dan memastikan pesanan aman diproses.

Mulai cepat

BayarBayar.in dipanggil dari backend website atau aplikasi Anda. API key tidak boleh ditempatkan di HTML, JavaScript browser, aplikasi pelanggan, URL pembayaran, atau repository publik.

  1. 1Buat transaksiBackend mengirim order dan nominal.
  2. 2Buka payment URLPelanggan melihat dan memindai QRIS.
  3. 3BayarBayar.in memeriksa mutasiBrowser pelanggan tidak mengakses GoPay.
  4. 4Webhook dikirimBackend menerima status bertanda tangan.
  5. 5Verifikasi & penuhiPastikan transaksi live benar-benar completed.

Endpoint yang tersedia

Contoh transaksi pertama

Jalankan dari backend atau terminal
curl -X POST 'https://boosbayar.com/api/transactioncreate/qris' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: gpk_test_GANTI_DENGAN_KEY_ANDA' \
  -H 'Idempotency-Key: checkout-INV-001' \
  -d '{
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "expiry_minutes": 60
  }'

Jika berhasil, buka nilai payment.payment_url dari response pada browser pelanggan. Jangan membuat sendiri URL pembayaran jika response sudah menyediakannya.

Kapan pesanan boleh diproses? Hanya setelah backend Anda menerima atau membaca status: "completed", memastikan environment: "live", dan mencocokkan project, order ID, serta nominal asli.

A. Persiapan

Daftar atau masuk ke Dashboard BayarBayar.in, lalu buat satu project untuk setiap website atau aplikasi yang akan menerima pembayaran.

A.1. Project

Project memisahkan transaksi, API key, callback URL, webhook secret, dan rate limit. Sumber pembayaran dipilih dari GoPay Merchant yang tersimpan pada akun Anda. Catat dua nilai berikut setelah project dibuat:

  • project slug — identitas project pada setiap request API.
  • API key — credential rahasia yang hanya ditampilkan saat dibuat.
Jangan kirim credential ke browser pelanggan API key dan webhook secret hanya boleh disimpan pada backend merchant atau secret manager.

A.2. QRIS dan akun GoPay Merchant

  1. Buka menu Pengaturan Channel, lalu hubungkan GoPay Merchant milik Anda melalui verifikasi OTP.
  2. Pada card GoPay Merchant tersebut, pilih Tambah QRIS dan masukkan QRIS statis milik merchant yang sama.
  3. Buat project. Setiap project baru otomatis menggunakan mode Sandbox; mode tidak dipilih saat pembuatan project.
  4. Buka menu Project, lalu tekan Pilih Chanel dan pilih GoPay Merchant yang akan digunakan.
  5. Ubah project ke Live hanya setelah payment channel dipilih dan tes integrasi Sandbox berhasil.

Satu GoPay Merchant hanya memiliki satu konfigurasi QRIS. Beberapa project dalam akun member yang sama boleh memilih GoPay Merchant yang sama, sehingga Merchant ID, QRIS, dan credential provider tetap disimpan satu kali dalam bentuk terenkripsi. Koneksi milik satu akun member tidak dapat dipilih oleh akun member lain.

A.3. Sandbox dan Live

ModeFungsiUang nyata
sandboxMenguji create, payment page, status, dan webhook melalui simulasi dashboard.Tidak
liveMembuat QRIS dinamis dan mencocokkan mutasi akun GoPay Merchant terkait.Ya

B. Halaman pembayaran

Cara yang disarankan adalah membuat transaksi melalui API, lalu mengarahkan pelanggan ke nilai payment.payment_url dari response. URL ini memakai token acak dan tidak mengekspos tuple invoice.

GEThttps://boosbayar.com/pay/t/{payment_token}

Endpoint kompatibilitas berikut juga tersedia untuk transaksi yang sudah dibuat. Gunakan total_payment, bukan nominal asli.

URL kompatibilitas
https://boosbayar.com/pay/toko-satu/10123?order_id=INV-001&qris_only=1
ParameterKeterangan
projectSlug project.
amounttotal_payment dari response create.
order_idNomor invoice pada sistem merchant.
redirectURL tujuan setelah lunas. Hostname wajib terdaftar pada redirect allowlist project.
qris_only=1Parameter kompatibilitas. Halaman saat ini memang hanya menampilkan QRIS, sehingga parameter ini tidak mengubah perilaku.
Perlakukan payment URL sebagai data terbatas URL boleh diberikan kepada pelanggan yang akan membayar, tetapi jangan menaruhnya pada halaman publik, log analytics, atau hasil pencarian. API key tidak pernah diperlukan pada halaman pembayaran.

Halaman pembayaran membaca status dari database BayarBayar.in. Setelah pembayaran terverifikasi, QR dan countdown hilang, lalu diganti tanda berhasil. Jika parameter redirect valid, pelanggan dapat kembali ke website merchant.

Endpoint status tanpa API key yang dipakai oleh halaman pembayaran adalah endpoint internal browser dan bukan kontrak integrasi merchant. Backend merchant harus memeriksa transaksi melalui GET /api/transactiondetail atau webhook.

C. Autentikasi API

Kirim API key melalui header X-API-Key. Header selalu diprioritaskan jika credential lama juga ada di body atau query.

HTTP header
X-API-Key: gpk_live_CONTOH_BUKAN_CREDENTIAL_ASLI
Kompatibilitas lama Parameter api_key pada body atau query masih diterima, tetapi deprecated. Integrasi baru wajib memakai header. Pemakaian credential lama menghasilkan header response Warning: 299.

API key memiliki environment dan scope. Key sandbox tidak dapat dipakai setelah project berpindah ke live; simpan key baru yang ditampilkan saat pergantian mode.

C.1. Header yang digunakan

HeaderWajibKeterangan
Content-TypePOSTGunakan application/json.
X-API-KeyYaAPI key project. Jangan kirim ke browser pelanggan.
Idempotency-KeyCreateSangat disarankan agar retry tidak membuat transaksi ganda.
X-Request-IDTidakUUID penelusuran milik Anda. Nilai non-UUID diganti dengan UUID baru; response selalu mengembalikan nilai yang dipakai.

C.2. Scope API key

ScopeDipakai untuk
transactions:writeMembuat dan membatalkan transaksi.
transactions:readMembaca detail transaksi dan metode pembayaran.

Gunakan key dengan scope minimum yang diperlukan. Jika key diduga bocor, buat key baru dari Dashboard dan cabut key lama.

C.3. Format waktu dan zona

Semua field date-time pada response API dan payload webhook BayarBayar.in menggunakan ISO 8601/RFC 3339 dalam UTC dengan akhiran Z. Nilai tersebut adalah waktu absolut, bukan waktu lokal server atau merchant.

UTC dan WIB menunjukkan waktu yang sama 2026-07-28T15:37:39Z sama dengan 2026-07-28T22:37:39+07:00 di Asia/Jakarta. Pertahankan instant dan informasi zona saat parsing. Simpan sebagai UTC atau tipe database yang memahami zona waktu; konversikan ke WIB hanya untuk tampilan.

Untuk request expired_at, zona waktu wajib dicantumkan. Gunakan akhiran UTC seperti 2026-07-28T15:37:39Z atau offset seperti 2026-07-28T22:37:39+07:00. Timestamp tanpa zona, misalnya 2026-07-28T15:37:39 atau 2026-07-28 15:37:39, ditolak dengan HTTP 422. BayarBayar.in menormalisasi nilai yang diterima menjadi UTC pada response.

D. API: Transaction Create

Membuat satu transaksi QRIS. Jika kode unik aktif, BayarBayar.in menambah kode tersebut ke nominal asli agar mutasi dapat dicocokkan dengan aman.

POST/api/transactioncreate/qris

D.1. Request

Member dapat menentukan expiry untuk setiap transaksi. Gunakan paling banyak satu field expiry. Rentang yang diterima adalah 5–300 menit (5 menit–5 jam). Jika tidak dikirim, BayarBayar.in menggunakan default 60 menit. Nilai di luar rentang selalu ditolak dengan HTTP 422 dan transaksi tidak dibuat.

FieldTipeKeterangan
project wajibstringSlug project, 3–63 karakter.
order_id wajibstringID invoice unik dalam project, maksimum 128 karakter.
amount wajibintegerNominal transaksi asli dalam rupiah, maksimum Rp100.000.000.
expired_atdate-timeWaktu kedaluwarsa RFC 3339 antara 5 menit dan 5 jam sejak request diproses. Zona wajib ada: gunakan Z atau offset seperti +07:00. Timestamp tanpa zona ditolak. Untuk batas tepat 5 menit, gunakan expiry_minutes: 5. Jangan kirim bersama field expiry lain.
expiry_minutesintegerDurasi dalam menit. Minimum 5, maksimum 300, default 60. Nilai desimal atau nilai di luar batas ditolak.
expiredintegerAlias lama untuk durasi menit. Gunakan expiry_minutes pada integrasi baru.
expired_minutesintegerAlias lama untuk durasi menit. Gunakan expiry_minutes pada integrasi baru.
api_key deprecatedstringGunakan header X-API-Key.
cURL
curl -X POST 'https://boosbayar.com/api/transactioncreate/qris' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: gpk_live_CONTOH' \
  -H 'Idempotency-Key: checkout-INV-001' \
  -d '{
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "expiry_minutes": 90
  }'
Aturan expiry
  • 5, 60, dan 300 diterima.
  • 4, 301, angka desimal, atau lebih dari satu field expiry ditolak dengan HTTP 422.
  • Gunakan expiry_minutes pada integrasi baru untuk menghindari kekeliruan UTC/WIB, perbedaan jam, atau latensi jaringan.
  • expired_at wajib memakai Z atau offset RFC 3339; nilai tanpa zona ditolak dengan HTTP 422.
  • Expiry tidak dapat diubah setelah QR dibuat. Buat transaksi baru jika membutuhkan waktu berbeda.

E_VALIDATION digunakan untuk bentuk request yang tidak valid, termasuk nilai di bawah batas schema, angka desimal, field tidak dikenal, atau beberapa field expiry sekaligus. Request body create dan cancel menolak field tambahan yang tidak tercantum di dokumentasi. E_INVALID_EXPIRY digunakan saat nilai yang formatnya valid tetap berada di luar kebijakan waktu, misalnya expiry_minutes: 301 atau expired_at di luar 5–300 menit.

HTTP 422 · expiry di luar batas
{
  "success": false,
  "message": "Waktu kedaluwarsa harus antara 5 menit dan 300 menit.",
  "code": "E_INVALID_EXPIRY",
  "errors": null,
  "request_id": "UUID"
}

D.2. Response sukses

HTTP 201 · application/json
{
  "success": true,
  "payment": {
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "fee": 0,
    "total_payment": 10123,
    "payment_method": "qris",
    "payment_number": "000201010212...",
    "expired_at": "2030-01-01T12:00:00.000Z",
    "environment": "live",
    "sandbox": false,
    "payment_url": "https://boosbayar.com/pay/t/OPAQUE_TOKEN"
  }
}
  • amount adalah nominal transaksi asli.
  • total_payment adalah nominal tepat yang harus dibayar pelanggan.
  • fee tetap 0; kode unik bukan fee.
  • payment_number berisi payload QRIS dinamis pada mode live.
  • payment_url adalah URL siap pakai yang harus dibuka pelanggan.

Create mengembalikan HTTP 201, termasuk saat request idempotent mengembalikan transaksi yang sudah ada. Simpan order_id dan response ini pada database merchant.

Data yang tidak pernah dikembalikan Response publik tidak berisi QRIS statis, session provider, cookie, OTP, access token, API key, atau webhook secret.

D.3. Response gagal

application/json
{
  "success": false,
  "message": "Request tidak valid.",
  "code": "E_VALIDATION",
  "errors": {
    "formErrors": [],
    "fieldErrors": {
      "expiry_minutes": [
        "Nilai harus berupa bilangan bulat minimal 5."
      ]
    }
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Untuk error validasi, errors berisi rincian field. Pada error operasional atau autentikasi, nilainya dapat berupa null.

E. API: Transaction Detail

Gunakan endpoint ini sebagai sumber status transaksi. Untuk keputusan fulfillment, cocokkan selalu project, order_id, amount, environment, dan status.

GET/api/transactiondetail
QueryTipeKeterangan
project wajibstringSlug project pemilik transaksi.
order_id wajibstringID invoice yang dikirim saat create.
amount wajibintegerNominal asli, bukan total_payment.
api_key deprecatedstringGunakan header X-API-Key.
cURL
curl --get 'https://boosbayar.com/api/transactiondetail' \
  -H 'X-API-Key: gpk_live_CONTOH' \
  --data-urlencode 'project=toko-satu' \
  --data-urlencode 'order_id=INV-001' \
  --data-urlencode 'amount=10000'
HTTP 200 · response pending
{
  "transaction": {
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "total_payment": 10123,
    "refund_amount": 0,
    "status": "pending",
    "payment_method": "qris",
    "completed_at": null,
    "environment": "live",
    "sandbox": false
  }
}
HTTP 200 · response completed
{
  "transaction": {
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "total_payment": 10123,
    "refund_amount": 0,
    "status": "completed",
    "payment_method": "qris",
    "completed_at": "2030-01-01T11:55:00.000Z",
    "environment": "live",
    "sandbox": false
  }
}

Webhook adalah mekanisme utama untuk perubahan status. Endpoint detail cocok sebagai verifikasi tambahan atau rekonsiliasi—bukan untuk polling sangat cepat. Jika perlu polling, gunakan interval wajar dan exponential backoff.

F. API: Transaction Cancel

Membatalkan transaksi yang masih pending. QR dinonaktifkan secara lokal dan kode unik dilepas sesuai guard period. Transaksi completed tidak dapat dibatalkan.

POST/api/transactioncancel
cURL
curl -X POST 'https://boosbayar.com/api/transactioncancel' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: gpk_live_CONTOH' \
  -d '{
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000
  }'
HTTP 200 · response
{
  "success": true,
  "status": "cancelled",
  "transaction": {
    "project": "toko-satu",
    "order_id": "INV-001",
    "amount": 10000,
    "total_payment": 10123,
    "refund_amount": 0,
    "status": "cancelled",
    "payment_method": "qris",
    "completed_at": null,
    "environment": "live",
    "sandbox": false
  }
}
Pembayaran terlambat setelah cancel atau expiry Jangan otomatis memenuhi pesanan. Mutasi yang tiba setelah transaksi berakhir dapat dipindahkan ke manual_review agar diperiksa manusia.

G. API: Payment Methods

Membaca metode pembayaran yang aktif untuk project.

GET/api/v1/projects/{project}/payment-methods
cURL
curl 'https://boosbayar.com/api/v1/projects/toko-satu/payment-methods' \
  -H 'X-API-Key: gpk_live_CONTOH'
Response
{
  "success": true,
  "data": [
    {
      "code": "qris",
      "name": "QRIS",
      "status": "active"
    }
  ]
}

H. Contoh Integrasi

H.1. Node.js

JavaScript · backend
const response = await fetch(
  'https://boosbayar.com/api/transactioncreate/qris',
  {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
      'x-api-key': process.env.BAYARBAYAR_API_KEY,
      'idempotency-key': `checkout-${order.id}`
    },
    body: JSON.stringify({
      project: 'toko-satu',
      order_id: order.id,
      amount: order.amount,
      expiry_minutes: 60
    })
  }
);

const result = await response.json();
if (!response.ok) throw new Error(result.code);

// Arahkan browser pelanggan ke URL ini.
return result.payment.payment_url;

H.2. PHP

PHP · backend
<?php
$orderId = 'INV-001';
$payload = json_encode([
  'project' => 'toko-satu',
  'order_id' => $orderId,
  'amount' => 10000,
  'expiry_minutes' => 60,
]);

$curl = curl_init('https://boosbayar.com/api/transactioncreate/qris');
curl_setopt_array($curl, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'X-API-Key: ' . getenv('BAYARBAYAR_API_KEY'),
    'Idempotency-Key: checkout-' . $orderId,
  ],
  CURLOPT_POSTFIELDS => $payload,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$result = json_decode($response, true);
curl_close($curl);

if ($status < 200 || $status >= 300) {
  throw new RuntimeException($result['code'] ?? 'E_UNKNOWN');
}

header('Location: ' . $result['payment']['payment_url']);
exit;

I. Webhook Pembayaran

BayarBayar.in mengirim HTTP POST ke callback URL project untuk setiap perubahan status yang menghasilkan event. Event disimpan sebelum dikirim dan dicoba ulang dengan exponential backoff sampai menerima HTTP 2xx atau mencapai batas percobaan otomatis.

Konfigurasi default melakukan maksimal 10 percobaan otomatis. Setelah batas tercapai, event berstatus dead, tetap tersimpan, dan dapat dikirim ulang secara manual dari menu Webhook.

Semua field date-time dalam payload, termasuk event_timestamp dan completed_at, dikirim sebagai UTC dengan akhiran Z. Header X-Gateway-Timestamp tetap berupa UNIX timestamp dalam detik.

I.1. Header

HeaderIsi
X-Gateway-Event-IDUUID unik untuk deduplikasi event.
X-Gateway-TimestampUNIX timestamp saat request ditandatangani.
X-Gateway-SignatureHMAC SHA-256 dalam format hexadecimal.
Content-Typeapplication/json

I.2. Jenis event

EventKapan dikirimTindakan merchant
transaction.completedPembayaran live terverifikasi.Verifikasi payload, lalu penuhi pesanan satu kali.
transaction.sandbox_completedSimulasi sandbox berhasil.Uji integrasi saja; jangan memenuhi pesanan nyata.
transaction.expiredBatas pembayaran terlewati.Tutup invoice pada sistem merchant.
transaction.cancelledMerchant membatalkan transaksi.Tandai invoice dibatalkan.
transaction.manual_reviewPencocokan tidak aman atau ambigu.Jangan fulfillment otomatis; periksa dashboard.
transaction.partially_refundedPengembalian dana sebagian terdeteksi.Catat nilai refund_amount.
transaction.refundedPengembalian dana penuh terdeteksi.Tandai pembayaran telah dikembalikan.

I.3. Payload

transaction.completed
{
  "schema_version": "1.0",
  "event_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_type": "transaction.completed",
  "event_timestamp": "2030-01-01T11:55:01.000Z",
  "project": "toko-satu",
  "order_id": "INV-001",
  "amount": 10000,
  "total_payment": 10123,
  "status": "completed",
  "payment_method": "qris",
  "completed_at": "2030-01-01T11:55:00.000Z",
  "refund_amount": 0,
  "environment": "live",
  "sandbox": false
}

I.4. Verifikasi signature

Hitung signature dari raw request body persis seperti diterima:

Formula
hex(HMAC_SHA256(timestamp + "." + raw_request_body, webhook_secret))
Node.js · Express
import crypto from 'node:crypto';
import express from 'express';

const app = express();

app.post('/webhook/bayarbayar',
  express.raw({ type: 'application/json' }),
	  (req, res) => {
	    const timestamp = req.get('x-gateway-timestamp') || '';
	    const received = req.get('x-gateway-signature') || '';
	    const timestampSeconds = Number(timestamp);
	    const currentSeconds = Math.floor(Date.now() / 1000);
	    const timestampValid = Number.isSafeInteger(timestampSeconds)
	      && Math.abs(currentSeconds - timestampSeconds) <= 300;

	    if (!timestampValid) return res.sendStatus(401);

	    const expected = crypto
	      .createHmac('sha256', process.env.BAYARBAYAR_WEBHOOK_SECRET)
	      .update(`${timestamp}.${req.body.toString('utf8')}`)
	      .digest();

	    const receivedBuffer = /^[a-f0-9]{64}$/.test(received)
	      ? Buffer.from(received, 'hex')
	      : Buffer.alloc(0);
	    const valid = receivedBuffer.length === expected.length
	      && crypto.timingSafeEqual(receivedBuffer, expected);

    if (!valid) return res.sendStatus(401);

    const event = JSON.parse(req.body.toString('utf8'));
    // Deduplikasi event.event_id sebelum fulfillment.
    res.sendStatus(204);
  }
);
Webhook dapat dikirim berkali-kali Simpan event_id, verifikasi signature, tolak timestamp yang berselisih lebih dari 5 menit, lalu proses event secara idempotent. Hanya kembalikan HTTP 2xx setelah event berhasil disimpan.

I.5. Urutan aman menerima webhook

  1. Baca body sebagai raw bytes sebelum JSON parser mengubah formatnya.
  2. Tolak timestamp yang terlalu lama untuk membatasi replay.
  3. Hitung HMAC menggunakan webhook secret project dan bandingkan secara constant-time.
  4. Simpan X-Gateway-Event-ID pada kolom unik. Event yang sama cukup dibalas HTTP 2xx.
  5. Cocokkan project, order ID, amount, status, dan environment dengan data merchant.
  6. Simpan perubahan secara atomik, baru balas HTTP 2xx.

Callback URL wajib memakai HTTPS dan domain publik. Host lokal atau loopback, jaringan privat/reserved, serta URL yang memuat username atau password akan ditolak. Respons selain HTTP 2xx dianggap gagal dan akan dicoba ulang.

J. Idempotensi, retry, dan rate limit

Kirim header Idempotency-Key saat membuat transaksi. Gunakan nilai unik dan stabil untuk satu usaha pembuatan pembayaran, misalnya checkout-{order_id}.

  • Project, order ID, dan nominal yang sama mengembalikan transaksi yang sudah ada.
  • Order ID sama dengan nominal berbeda menghasilkan HTTP 409.
  • Idempotency key sama untuk payload berbeda menghasilkan HTTP 409.
  • Panjang maksimum idempotency key adalah 128 karakter.

Retry yang aman

  • Jika terjadi timeout jaringan, kirim ulang request create dengan body dan Idempotency-Key yang sama.
  • Jangan mengganti order_id hanya karena response pertama terlambat.
  • Retry otomatis hanya untuk kegagalan sementara seperti timeout, HTTP 429, 502, atau 503.
  • Gunakan exponential backoff dengan jitter dan batasi jumlah percobaan.
  • Jangan retry otomatis untuk 400, 401, 403, 404, 409, atau 422 sebelum penyebab request diperbaiki.

Rate limit

BayarBayar.in menerapkan batas global dan batas per project. Saat HTTP 429 diterima, hentikan request sementara dan ikuti header Retry-After. Header berikut dapat disertakan pada response:

HeaderArti
RateLimitInformasi limit global sesuai standar yang digunakan server.
RateLimit-PolicyKebijakan window dan batas rate limit global.
X-RateLimit-LimitBatas request project per menit.
X-RateLimit-RemainingSisa request pada window project saat ini.
Retry-AfterJumlah detik minimum sebelum mencoba kembali.

K. Status dan Error

pending

Menunggu pembayaran.

completed

Pembayaran berhasil terverifikasi.

expired

Melewati batas waktu pembayaran.

cancelled

Dibatalkan oleh merchant.

failed

Pemrosesan transaksi gagal.

manual_review

Mutasi ambigu atau perlu pemeriksaan manual.

partially_refunded

Dana dikembalikan sebagian.

refunded

Dana dikembalikan seluruhnya.

K.1. HTTP status

HTTPArtiContoh kode
400Format request tidak dapat diproses.E_BAD_REQUEST
401API key salah atau tidak tersedia.E_UNAUTHORIZED
403Project, scope, atau akun provider tidak diizinkan.E_INSUFFICIENT_SCOPE
404Endpoint atau transaksi tidak ditemukan.E_TRANSACTION_NOT_FOUND
409Konflik order, idempotensi, nominal, atau status.E_ORDER_AMOUNT_CONFLICT
413Body request melebihi batas 32 KB.E_BODY_TOO_LARGE
422Validasi request gagal.E_VALIDATION
429Rate limit atau kuota pending tercapai.E_RATE_LIMIT
500Error internal tanpa stack trace.E_INTERNAL
502Provider mengembalikan respons tidak valid.E_PROVIDER_UNAVAILABLE
503Sesi provider atau kode unik belum tersedia.E_PROVIDER_SESSION_NOT_READY

Simpan request_id dari response gagal untuk pencarian audit dan troubleshooting.

K.2. Kode error yang sering ditemui

KodePenyebabYang harus dilakukan
E_UNAUTHORIZEDSlug dan API key tidak cocok, key dicabut, kedaluwarsa, atau berbeda mode.Periksa project dan gunakan key aktif dari environment yang sama.
E_INSUFFICIENT_SCOPEAPI key tidak memiliki scope endpoint.Buat key dengan scope read atau write yang diperlukan.
E_PROJECT_INACTIVEProject dinonaktifkan.Aktifkan project dari Dashboard.
E_PROJECT_PAYMENT_CONFIG_REQUIREDProject belum memilih GoPay Merchant yang memiliki QRIS.Buka Pengaturan Channel untuk melengkapi QRIS Merchant, lalu gunakan Pilih Chanel pada halaman Project.
E_BAD_REQUESTJSON rusak atau request tidak dapat dibaca.Perbaiki sintaks JSON dan header Content-Type.
E_BODY_TOO_LARGEBody request melebihi 32 KB.Kirim hanya field API yang didukung.
E_VALIDATIONTipe, field, atau kombinasi parameter tidak sesuai schema.Periksa rincian pada object errors.
E_INVALID_EXPIRYExpiry yang berformat valid berada di luar 5–300 menit.Kirim satu expiry_minutes berupa integer 5–300.
E_ORDER_AMOUNT_CONFLICTOrder ID sudah ada dengan nominal lain.Gunakan nominal semula atau order ID baru.
E_IDEMPOTENCY_CONFLICTIdempotency key dipakai untuk payload berbeda.Gunakan payload semula atau key baru.
E_COMPLETED_CANNOT_CANCELTransaksi sudah lunas.Jangan cancel; jalankan proses refund terpisah bila tersedia.
E_PROVIDER_SESSION_NOT_READYSesi GoPay live belum dapat diverifikasi.Hubungkan ulang akun provider dari menu Pengaturan Channel.
E_RATE_LIMITTerlalu banyak request pada project.Ikuti Retry-After dan perlambat request.

L. Pengujian

  1. Pastikan project berada dalam mode Sandbox.
  2. Buka menu Tes QRIS dan buat transaksi uji.
  3. Gunakan tombol simulasi lunas di dashboard. QR sandbox tidak boleh dibayar dengan aplikasi bank.
  4. Pastikan backend menerima webhook dengan environment: "sandbox" dan event_type: "transaction.sandbox_completed".
  5. Periksa detail transaksi melalui API sebelum menguji mode Live.
Aturan fulfillment Hanya transaksi dengan status: "completed", environment: "live", dan identitas order yang cocok yang boleh memenuhi pesanan nyata.

M. Checklist sebelum menerima uang nyata

Selesaikan seluruh pemeriksaan ini sebelum mengubah project ke mode Live.

Status layanan

  • GET/healthMenandakan proses aplikasi hidup.
  • GET/readyHTTP 200 jika database siap; HTTP 503 jika belum siap.

Gunakan endpoint ini untuk load balancer atau monitoring. Jangan menggunakannya sebagai bukti bahwa akun provider suatu project siap menerima pembayaran; pemeriksaan provider tetap dilakukan saat transaksi live dibuat.

N. Pemecahan masalah

QR sandbox tidak dapat dibayar

Ini normal. QR sandbox hanya untuk simulasi melalui menu Tes QRIS. Ubah project ke Live hanya setelah seluruh integrasi selesai diuji.

Pembayaran live sudah dilakukan, tetapi status masih pending

Pastikan pelanggan membayar persis total_payment, project memilih GoPay Merchant dan QRIS yang benar, sesi GoPay terhubung, transaksi belum kedaluwarsa, dan worker berjalan. Jangan mengubah status secara manual. Jika pencocokan tidak tunggal atau pembayaran terlambat, transaksi dapat masuk manual_review.

Create mengembalikan 401 setelah mode project diubah

Perubahan Sandbox/Live menghasilkan credential environment yang sesuai. Gunakan API key baru yang ditampilkan setelah perubahan mode.

Webhook gagal atau berstatus dead

Pastikan callback dapat diakses melalui HTTPS publik, tidak melakukan redirect, selesai sebelum timeout, dan mengembalikan HTTP 2xx. Setelah 10 kegagalan otomatis pada konfigurasi default, event menjadi dead; periksa riwayat dan kirim ulang secara manual dari menu Webhook.

Payment URL menampilkan 404

Gunakan payment_url persis dari response create. Token yang salah, project nonaktif, atau URL yang dipotong akan ditolak.

Bagaimana meminta bantuan?

Catat waktu kejadian, project slug, order ID, HTTP status, error code, dan request_id. Jangan pernah mengirim API key, webhook secret, OTP, cookie, atau session provider.