Docs

Mulai

Terima pembayaran VA, QRIS, dan GoPay dari website atau aplikasi Anda lewat REST API Skyve.

  1. Daftar dan buat API key di Portal → API.
  2. Isi Callback URL di Portal → Profil.
  3. Buat tagihan dari server Anda, lalu tampilkan nomor VA atau QR ke pembeli.
  4. Tandai pesanan lunas saat callback masuk dan statusnya sudah terverifikasi.
Belum ada mode sandbox. Setiap tagihan adalah transaksi sungguhan, jadi uji coba dengan nominal kecil.
Base URL
https://skyve.id

Autentikasi

Kirim API key di header X-API-Key atau Authorization: Bearer pada setiap request.

Panggil API hanya dari server. Jangan taruh API key di JavaScript browser atau aplikasi mobile.

Key lengkap hanya muncul sekali saat dibuat. Kalau hilang atau bocor, buat key baru di portal. Key lama langsung tidak berlaku.

Header
X-API-Key: sk_3f9a1c...

# atau
Authorization: Bearer sk_3f9a1c...

Checkout (link bayar)

Cara paling mudah menghubungkan aplikasi Anda. Kirim daftar barang dan nominal, Skyve membalas dengan checkout_url. Arahkan pembeli ke link itu: pembeli memilih metode, membayar, lalu diarahkan kembali ke return_url Anda. Anda tidak perlu membuat halaman bayar sendiri.

POST/api/v1/checkouts

Body

order_idstring · wajibID pesanan dari sistem Anda, unik per merchant. Maksimal 24 karakter: huruf, angka, . _ -.
items[]array · wajib1–50 barang, masing-masing name, quantity, dan price (rupiah, bilangan bulat). Total dihitung otomatis, minimal Rp1.000.
customerobjectname, phone, email. Field yang diisi tampil terkunci dan tidak bisa diubah pembeli. Yang dikosongkan diisi pembeli sendiri. Format phone sama dengan customer_details.phone (nomor luar negeri pakai awalan +).
return_urlstringTujuan tombol "Kembali" setelah bayar. Skyve menambahkan ?order_id=…&status=paid|pending|failed.
expires_in_hoursnumberMasa berlaku link. Default 24, maksimal 720.

Biaya admin

Biaya admin metode pembayaran dibayar oleh pembeli dan ditambahkan di halaman checkout. Di callback, gross_amount adalah total yang dibayar pembeli termasuk fee_amount. Nominal pesanan Anda = gross_amount − fee_amount, sama dengan amount checkout.

Setelah pembeli bayar

Skyve mengirim callback satu kali saat checkout lunas, dengan order_id milik Anda dan checkout_id. Kalau pembeli sempat ganti metode, attempt_order_id bisa berbeda (misalnya TOKO-1001-2).

Verifikasi dengan GET /api/v1/checkouts/{checkout_id} dan pastikan status bernilai paid sebelum menandai pesanan lunas. Status lain: open (belum dibayar) dan expired.

Jangan mengandalkan status di query return_url saja, karena pembeli bisa mengubahnya. Selalu verifikasi dari server.
curl -X POST https://skyve.id/api/v1/checkouts \
  -H "X-API-Key: $SKYVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "TOKO-1001",
    "items": [
      { "name": "Kopi Susu", "quantity": 2, "price": 18000 },
      { "name": "Croissant", "quantity": 1, "price": 25000 }
    ],
    "customer": { "name": "Budi", "phone": "081234567890" },
    "return_url": "https://tokokamu.com/pesanan/TOKO-1001"
  }'
Response · 201
{
  "success": true,
  "data": {
    "id": "chk_Qm3x9LwZp2Ka",
    "checkout_url": "https://skyve.id/c/chk_Qm3x9LwZp2Ka",
    "order_id": "TOKO-1001",
    "status": "open",
    "amount": 61000,
    "items": [
      { "name": "Kopi Susu", "quantity": 2, "price": 18000 },
      { "name": "Croissant", "quantity": 1, "price": 25000 }
    ],
    "customer": { "name": "Budi", "phone": "081234567890", "email": null },
    "return_url": "https://tokokamu.com/pesanan/TOKO-1001",
    "paid_order_id": null,
    "paid_at": null,
    "expires_at": "2026-10-01T09:00:00.000Z"
  }
}
Callback saat lunas
{
  "tenant_id": "tnt_8c1f2a9d4e7b3c60",
  "order_id": "TOKO-1001",
  "checkout_id": "chk_Qm3x9LwZp2Ka",
  "attempt_order_id": "TOKO-1001",
  "transaction_status": "settlement",
  "payment_type": "qris",
  "gross_amount": "61431.00",
  "fee_amount": "431.00",
  "transaction_id": "9f1c2e7a-3b0d-4c55-9a1e-7d2f0c6b8e41"
}

Buat tagihan

POST/api/v1/charges

Body

order_idstring · wajibID pesanan dari sistem Anda. Harus unik per merchant.
gross_amountnumber · wajibNominal dalam rupiah, tanpa desimal.
payment_methodstring · wajibSalah satu dari metode pembayaran.
customer_details.first_namestring · wajibMinimal 2 karakter.
customer_details.last_namestring—
customer_details.emailstring · wajib—
customer_details.phonestring · wajibNomor Indonesia: 08… atau 628…. Nomor luar negeri wajib diawali + dan kode negara, mis. +6591234567.

Response

Tampilkan instruksi bayar ke pembeli sesuai metode. Field yang dipakai ada di tabel metode pembayaran. Status awal selalu pending.

curl -X POST https://skyve.id/api/v1/charges \
  -H "X-API-Key: $SKYVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "INV-1001",
    "gross_amount": 150000,
    "payment_method": "bni",
    "customer_details": {
      "first_name": "Budi",
      "email": "budi@mail.com",
      "phone": "081234567890"
    }
  }'
Response · 201
{
  "success": true,
  "data": {
    "order_id": "INV-1001",
    "transaction_id": "9f1c2e7a-3b0d-4c55-9a1e-7d2f0c6b8e41",
    "payment_method": "bni",
    "payment_type": "bank_transfer",
    "gross_amount": "150000.00",
    "transaction_status": "pending",
    "va_number": "9881234567890123",
    "bank": "bni",
    "expiry_time": "2026-10-01 16:51:00"
  }
}

Cek status

GET/api/v1/charges/{order_id}/status

Mengambil status terbaru langsung dari bank. Pakai untuk memverifikasi callback atau sebagai cadangan kalau callback tidak sampai.

curl https://skyve.id/api/v1/charges/INV-1001/status \
  -H "X-API-Key: $SKYVE_API_KEY"
Response · 200
{
  "success": true,
  "data": {
    "order_id": "INV-1001",
    "transaction_status": "settlement",
    "payment_type": "bank_transfer",
    "gross_amount": "150000.00",
    "fraud_status": "accept"
  }
}

Callback

Setiap kali status transaksi berubah, Skyve mengirim POST JSON ke Callback URL Anda.

Callback belum ditandatangani. Sebelum menandai pesanan lunas, selalu panggil cek status dan pastikan hasilnya settlement atau capture.
  • Balas dengan HTTP 200 dalam 10 detik.
  • Skyve tidak mengirim ulang callback yang gagal.
  • Callback yang sama bisa datang lebih dari sekali. Abaikan kalau pesanan sudah lunas.
Payload
POST https://tokokamu.com/skyve/callback
Content-Type: application/json

{
  "tenant_id": "tnt_8c1f2a9d4e7b3c60",
  "order_id": "INV-1001",
  "transaction_status": "settlement",
  "payment_type": "bank_transfer",
  "gross_amount": "150000.00",
  "fee_amount": "0.00",
  "fraud_status": "accept",
  "transaction_id": "9f1c2e7a-3b0d-4c55-9a1e-7d2f0c6b8e41"
}
app.post('/skyve/callback', express.json(), async (req, res) => {
  res.sendStatus(200);

  const orderId = req.body.order_id;
  const check = await fetch(
    `https://skyve.id/api/v1/charges/${encodeURIComponent(orderId)}/status`,
    { headers: { 'X-API-Key': process.env.SKYVE_API_KEY } }
  );
  const { data } = await check.json();

  if (['settlement', 'capture'].includes(data.transaction_status)) {
    await markOrderPaid(orderId);
  }
});

Metode pembayaran

payment_methodMetodeTampilkan ke pembeli
bniBNI Virtual Accountva_number
briBRI Virtual Accountva_number
permataPermata Virtual Accountva_number
cimbCIMB Niaga Virtual Accountva_number
mandiriMandiri Bill Paymentbiller_code + bill_key
qrisQRISqr_url (gambar) atau qr_string
gopayGoPaydeeplink_url atau qr_url
manualTransfer manualmanual_account

Batas bayar ada di expiry_time.

Transfer manual

Ambil daftar rekening dari GET /api/v1/manual-transfer-accounts, lalu kirim manual_account_id bersama payment_method: "manual". Kalau hanya ada satu rekening, manual_account_id boleh dikosongkan.

Pembeli transfer ke rekening di manual_account, lalu upload bukti ke POST /api/public/{tenant_id}/manual/{order_id}/proof dengan body { "image": "data:image/jpeg;base64,...", "sender_name": "..." }. Status berubah jadi settlement setelah admin Skyve menyetujui bukti.

Status transaksi

transaction_statusArti
pendingMenunggu pembayaran
settlementLunas
captureLunas
expireLewat batas bayar
cancelDibatalkan
denyDitolak bank

Error

Error selalu berformat { success: false, message }.

HTTPPenyebab
400Body tidak valid atau metode sedang nonaktif
401API key tidak dikirim
403API key salah
404order_id tidak ditemukan
409order_id sudah pernah dipakai
502Bank atau Midtrans sedang bermasalah, coba lagi
Response · 409
{
  "success": false,
  "message": "order_id already exists for this merchant"
}