Buat disbursement — Partner Transactions API
Transfer dana ke rekening bank tujuan.
Setelah provider memproses request ini, transfer tidak bisa dibatalkan. Pastikan seluruh data rekening tujuan (nomor rekening, nama pemilik, kode bank) sudah benar sebelum submit.
Setelah dibuat, dana diteruskan ke payment provider yang dipilih berdasarkan groupId, termasuk
pengecekan liquidity dan reservasi saldo di awal. Status pada response ini bukan status final
transaksi; status akan diperbarui secara asinkron melalui webhook dari provider.
Autentikasi
Kirim header Authorization: Bearer <accessToken>, memakai accessToken yang didapat dari
Partner Auth API. Butuh permission transactions:create.
Idempotency
Wajib kirim header Idempotency-Key (string non-kosong apa pun -- rekomendasi kami: UUID v4) di
setiap request. Request kedua dengan key yang sama dan body yang sama persis mengembalikan
response yang identik tanpa memproses ulang. Body berbeda dengan key yang sama menghasilkan
409 Conflict -- ini penting khususnya di sini karena operasinya tidak bisa dibatalkan, jadi retry
yang aman itu WAJIB pakai key yang sama, bukan key baru. Lihat panduan lengkap di
Idempotency.
| Header | Wajib | Deskripsi |
|---|---|---|
Idempotency-Key | Ya | Unik per percobaan disbursement (gunakan key yang sama untuk retry dari transfer yang sama). Rekomendasi: UUID v4. |
Request body
| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
externalReference | string (maks 100) | Ya | ID unik transaksi dari sisi kamu, untuk rekonsiliasi. Harus unik per partner. |
amount | integer (Long) | Ya | Nominal dalam Rupiah (bilangan bulat, tidak ada sen). Minimum 10000 (= Rp 10.000). Contoh: 5000000 = Rp 5.000.000. |
description | string (maks 500) | Tidak | Keterangan untuk keperluan internal. |
groupId | UUID | Ya | Group tujuan. Provider WITHDRAW yang dipakai ditentukan oleh Routing Configuration yang di-setup untuk group ini (gateway Primary dengan weight, Backup dengan urutan priority buat failover, termasuk cek liquidity) -- request ini sendiri tidak punya parameter untuk memaksa provider tertentu, tapi kamu bisa atur pool provider & prioritasnya lewat Routing Configuration. |
destAccountNo | string | Ya | Nomor rekening bank tujuan, tanpa strip atau spasi. |
destAccountName | string (maks 100) | Ya | Nama pemilik rekening tujuan sesuai data bank. |
destBankCode | string (maks 10) | Ya | Kode bank tujuan format BI-FAST/SKNBI. Contoh: 014 = BCA, 008 = Mandiri, 009 = BNI -- lihat daftar lengkap di Guides. |
remark | string (maks 100) | Ya | Berita transfer -- muncul di mutasi bank rekening tujuan. |
Contoh request
- cURL
- Node.js
- Java
curl -X POST '{{BASE_URL}}/api/v1/transactions/disbursements' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"externalReference": "DISB-2026-000567",
"amount": 5000000,
"description": "Payout merchant periode Juli 2026",
"groupId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"destAccountNo": "1234567890",
"destAccountName": "Budi Santoso",
"destBankCode": "014",
"remark": "Payout Juli 2026"
}'
import { randomUUID } from "node:crypto";
const response = await fetch("{{BASE_URL}}/api/v1/transactions/disbursements", {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Idempotency-Key": randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
externalReference: "DISB-2026-000567",
amount: 5000000,
description: "Payout merchant periode Juli 2026",
groupId: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
destAccountNo: "1234567890",
destAccountName: "Budi Santoso",
destBankCode: "014",
remark: "Payout Juli 2026",
}),
});
const data = await response.json();
console.log(data);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
String requestBody =
"""
{
"externalReference": "DISB-2026-000567",
"amount": 5000000,
"description": "Payout merchant periode Juli 2026",
"groupId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"destAccountNo": "1234567890",
"destAccountName": "Budi Santoso",
"destBankCode": "014",
"remark": "Payout Juli 2026"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request =
HttpRequest.newBuilder()
.uri(URI.create("{{BASE_URL}}/api/v1/transactions/disbursements"))
.header("Authorization", "Bearer " + accessToken)
.header("Idempotency-Key", UUID.randomUUID().toString())
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Response sukses
201 Created
{
"code": "00",
"message": "Success",
"data": {
"transactionId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"partnerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"groupId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"externalReference": "DISB-2026-000567",
"platformReference": "TXN-20260707-B2C3D4",
"transactionType": "DISBURSEMENT",
"paymentMethod": "BANK_TRANSFER",
"status": "PENDING",
"amount": 5000000,
"currency": "IDR",
"providerCode": "OY",
"providerReference": null,
"qrString": null,
"expiredAt": null,
"description": "Payout merchant periode Juli 2026",
"createdAt": "2026-07-07T09:00:00Z",
"updatedAt": "2026-07-07T09:00:00Z"
},
"correlationId": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"requestId": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"timestamp": "2026-08-13T09:15:30.123Z"
}
providerCode di atas hanya contoh -- provider yang benar-benar dipakai ditentukan otomatis saat
runtime berdasarkan groupId kamu, bisa berbeda dari contoh ini.
Pantau data.status lewat polling Detail transaksi sampai berstatus SUCCESS atau FAILED.
Response error
| HTTP Status | code | Kapan terjadi |
|---|---|---|
| 400 | VALIDATION_ERROR | Field wajib kosong/format salah (mis. rekening tujuan kosong, amount di bawah minimum), ATAU header Idempotency-Key tidak dikirim sama sekali. |
| 400 | IDEMPOTENCY_KEY_REQUIRED | Header Idempotency-Key dikirim tapi isinya kosong/blank. |
| 401 | INVALID_TOKEN | Authorization header tidak ada, JWT tidak valid, atau kadaluarsa. |
| 403 | ACCESS_DENIED | Tidak punya permission transactions:create. |
| 403 | GROUP_NOT_OWNED | groupId tidak ditemukan atau bukan milik partner ini. |
| 403 | GROUP_INACTIVE | groupId valid tapi statusnya sudah tidak aktif. |
| 409 | DUPLICATE_TRANSACTION | externalReference sudah pernah dipakai partner ini sebelumnya. |
| 409 | IDEMPOTENCY_KEY_CONFLICT | Idempotency-Key sudah dipakai sebelumnya dengan body request yang berbeda. |
| 409 | IDEMPOTENCY_REQUEST_IN_PROGRESS | Request lain dengan Idempotency-Key yang sama masih diproses -- coba lagi sebentar. |
| 422 | NO_GATEWAY | Tidak ada gateway yang eligible untuk groupId ini saat ini. |
| 422 | NO_CREDENTIAL | Gateway ditemukan tapi belum ada credential yang terpasang untuk groupId ini. |
| 422 | INSUFFICIENT_LIQUIDITY | Tidak ada gateway dengan liquidity cukup untuk groupId ini saat ini -- coba lagi nanti. |
| 422 | INSUFFICIENT_BALANCE | Saldo partner tidak mencukupi untuk nominal disbursement ini. Dana tidak dikurangi, transfer tidak dikirim. |
| 500 | INTERNAL_ERROR | Gateway/provider tidak bisa dihubungi atau timeout -- aman di-retry dengan Idempotency-Key yang sama. |
{
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"data": {
"destAccountNo": "must not be blank",
"amount": "must be greater than or equal to 10000"
},
"correlationId": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"requestId": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"timestamp": "2026-08-13T09:15:30.123Z"
}
{
"code": "INSUFFICIENT_BALANCE",
"message": "Saldo tidak mencukupi untuk disbursement transactionId=b2c3d4e5-f6a7-8901-bcde-f23456789012",
"correlationId": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"requestId": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
"timestamp": "2026-08-13T09:15:30.123Z"
}