Releasing funds with split payouts
When a milestone is approved, finance releases it to one to five payout instructions. Each instruction is a bank destination that RekberPay has verified and signed, so money cannot be sent to an account someone typed in at the last moment. In this run Rp30.000.000 is split between the supplier's main account and its freight account.
1. See the verified instructions
curl "https://api.rekberpay.com/v1/enterprise/payout-instructions?counterparty_id=eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee" \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY"const res = await fetch('https://api.rekberpay.com/v1/enterprise/payout-instructions?counterparty_id=eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee', {
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
},
});
const data = await res.json();import os
import requests
resp = requests.get(
"https://api.rekberpay.com/v1/enterprise/payout-instructions?counterparty_id=eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/payout-instructions?counterparty_id=eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);200 OK
{
"success": true,
"data": [
{
"id": "fffffff3-ffff-4fff-8fff-ffffffffffff",
"label": "Harbourline IDR collection account",
"counterparty": {
"id": "eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
"name": "Harbourline Components Pte Ltd"
},
"currency": "IDR",
"bank_name": "DBS Bank Indonesia",
"account_number_masked": "3320****43",
"account_holder": "Harbourline Components Pte Ltd",
"country_code": "ID",
"status": "verified",
"signed": true,
"verified_at": "2026-09-30T07:33:06.162Z",
"created_at": "2026-09-30T03:33:06.162Z",
"updated_at": "2026-10-13T14:33:06.231Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"total_pages": 1
}
}Only verified instructions can receive money. Account numbers are always masked.
2. Add a new instruction
curl -X POST https://api.rekberpay.com/v1/enterprise/payout-instructions \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY" \
-H "Idempotency-Key: 11111114-1111-4111-8111-111111111111" \
-H "Content-Type: application/json" \
-d '{
"label": "Harbourline freight account",
"counterparty_id": "eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
"currency": "IDR",
"bank_name": "Bank Central Asia",
"account_number": "8730 0412 55",
"account_holder": "PT Harbourline Indonesia",
"country_code": "ID"
}'const res = await fetch('https://api.rekberpay.com/v1/enterprise/payout-instructions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '11111114-1111-4111-8111-111111111111',
},
body: JSON.stringify({
label: "Harbourline freight account",
counterparty_id: "eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
currency: "IDR",
bank_name: "Bank Central Asia",
account_number: "8730 0412 55",
account_holder: "PT Harbourline Indonesia",
country_code: "ID"
}),
});
const data = await res.json();import os
import requests
resp = requests.post(
"https://api.rekberpay.com/v1/enterprise/payout-instructions",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
"Idempotency-Key": "11111114-1111-4111-8111-111111111111",
},
json={
"label": "Harbourline freight account",
"counterparty_id": "eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
"currency": "IDR",
"bank_name": "Bank Central Asia",
"account_number": "8730 0412 55",
"account_holder": "PT Harbourline Indonesia",
"country_code": "ID",
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/payout-instructions');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
'Content-Type: application/json',
'Idempotency-Key: 11111114-1111-4111-8111-111111111111',
],
CURLOPT_POSTFIELDS => json_encode([
'label' => 'Harbourline freight account',
'counterparty_id' => 'eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee',
'currency' => 'IDR',
'bank_name' => 'Bank Central Asia',
'account_number' => '8730 0412 55',
'account_holder' => 'PT Harbourline Indonesia',
'country_code' => 'ID',
]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);201 Created
{
"success": true,
"data": {
"id": "22222224-2222-4222-8222-222222222222",
"label": "Harbourline freight account",
"counterparty": {
"id": "eeeeeee3-eeee-4eee-8eee-eeeeeeeeeeee",
"name": "Harbourline Components Pte Ltd"
},
"currency": "IDR",
"bank_name": "Bank Central Asia",
"account_number_masked": "8730****55",
"account_holder": "PT Harbourline Indonesia",
"country_code": "ID",
"status": "pending_review",
"signed": true,
"verified_at": null,
"created_at": "2026-10-13T14:33:16.301Z",
"updated_at": "2026-10-13T14:33:16.301Z"
}
}It starts as pending_review. Editing the label keeps it in review; editing a bank field signs it again and sends it back to review:
curl -X PATCH https://api.rekberpay.com/v1/enterprise/payout-instructions/22222224-2222-4222-8222-222222222222 \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY" \
-H "Idempotency-Key: 33333334-3333-4333-8333-333333333333" \
-H "Content-Type: application/json" \
-d '{
"label": "Harbourline freight and duties"
}'const res = await fetch('https://api.rekberpay.com/v1/enterprise/payout-instructions/22222224-2222-4222-8222-222222222222', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '33333334-3333-4333-8333-333333333333',
},
body: JSON.stringify({
label: "Harbourline freight and duties"
}),
});
const data = await res.json();import os
import requests
resp = requests.patch(
"https://api.rekberpay.com/v1/enterprise/payout-instructions/22222224-2222-4222-8222-222222222222",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
"Idempotency-Key": "33333334-3333-4333-8333-333333333333",
},
json={
"label": "Harbourline freight and duties",
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/payout-instructions/22222224-2222-4222-8222-222222222222');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
'Content-Type: application/json',
'Idempotency-Key: 33333334-3333-4333-8333-333333333333',
],
CURLOPT_POSTFIELDS => json_encode([
'label' => 'Harbourline freight and duties',
]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);RekberPay checks the account and verifies it. You see payout_instruction.verified in the event feed when that happens.
3. Release in splits
The split amounts must add up to the milestone amount exactly:
400 Bad Request
{
"success": false,
"error": {
"code": "SPLITS_MISMATCH",
"message": "Splits must add up to the milestone amount."
}
}With matching amounts, the release goes through and each split becomes a queued payout:
curl -X POST https://api.rekberpay.com/v1/enterprise/deals/eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee/milestones/fffffff4-ffff-4fff-8fff-ffffffffffff/release \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY" \
-H "Idempotency-Key: 33333336-3333-4333-8333-333333333333" \
-H "Content-Type: application/json" \
-d '{
"splits": [
{
"payout_instruction_id": "fffffff3-ffff-4fff-8fff-ffffffffffff",
"amount": 25000000
},
{
"payout_instruction_id": "22222224-2222-4222-8222-222222222222",
"amount": 5000000
}
]
}'const res = await fetch('https://api.rekberpay.com/v1/enterprise/deals/eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee/milestones/fffffff4-ffff-4fff-8fff-ffffffffffff/release', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '33333336-3333-4333-8333-333333333333',
},
body: JSON.stringify({
splits: [
{
payout_instruction_id: "fffffff3-ffff-4fff-8fff-ffffffffffff",
amount: 25000000
},
{
payout_instruction_id: "22222224-2222-4222-8222-222222222222",
amount: 5000000
}
]
}),
});
const data = await res.json();import os
import requests
resp = requests.post(
"https://api.rekberpay.com/v1/enterprise/deals/eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee/milestones/fffffff4-ffff-4fff-8fff-ffffffffffff/release",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
"Idempotency-Key": "33333336-3333-4333-8333-333333333333",
},
json={
"splits": [
{
"payout_instruction_id": "fffffff3-ffff-4fff-8fff-ffffffffffff",
"amount": 25000000,
},
{
"payout_instruction_id": "22222224-2222-4222-8222-222222222222",
"amount": 5000000,
},
],
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/deals/eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee/milestones/fffffff4-ffff-4fff-8fff-ffffffffffff/release');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
'Content-Type: application/json',
'Idempotency-Key: 33333336-3333-4333-8333-333333333333',
],
CURLOPT_POSTFIELDS => json_encode([
'splits' => [
[
'payout_instruction_id' => 'fffffff3-ffff-4fff-8fff-ffffffffffff',
'amount' => 25000000,
],
[
'payout_instruction_id' => '22222224-2222-4222-8222-222222222222',
'amount' => 5000000,
],
],
]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);200 OK
{
"success": true,
"data": {
"milestone_id": "fffffff4-ffff-4fff-8fff-ffffffffffff",
"status": "released",
"deal_status": "in_progress",
"disbursements": [
{
"id": "44444446-4444-4444-8444-444444444444",
"payout_instruction_id": "fffffff3-ffff-4fff-8fff-ffffffffffff",
"amount": 25000000,
"currency": "IDR",
"status": "queued"
},
{
"id": "55555556-5555-4555-8555-555555555555",
"payout_instruction_id": "22222224-2222-4222-8222-222222222222",
"amount": 5000000,
"currency": "IDR",
"status": "queued"
}
]
}
}Every instruction must be verified, in the deal currency, and belong to the deal's counterparty or to the whole workspace, otherwise the call answers 400 INSTRUCTION_NOT_ELIGIBLE. Release is final.
4. Follow the payouts
curl "https://api.rekberpay.com/v1/enterprise/payouts?limit=2" \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY"const res = await fetch('https://api.rekberpay.com/v1/enterprise/payouts?limit=2', {
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
},
});
const data = await res.json();import os
import requests
resp = requests.get(
"https://api.rekberpay.com/v1/enterprise/payouts?limit=2",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/payouts?limit=2');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);200 OK
{
"success": true,
"data": {
"items": [
{
"id": "44444446-4444-4444-8444-444444444444",
"deal_id": "eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee",
"deal_reference": "DEAL-2026-0009",
"milestone_id": "fffffff4-ffff-4fff-8fff-ffffffffffff",
"milestone_title": "Tooling and proof approval",
"payout_instruction_id": "fffffff3-ffff-4fff-8fff-ffffffffffff",
"instruction_label": "Harbourline IDR collection account",
"bank_name": "DBS Bank Indonesia",
"account_number_masked": "3320****43",
"amount": 25000000,
"currency": "IDR",
"status": "queued",
"failure_reason": null,
"settled_at": null,
"created_at": "2026-10-13T14:33:16.480Z",
"updated_at": "2026-10-13T14:33:16.480Z"
},
{
"id": "55555556-5555-4555-8555-555555555555",
"deal_id": "eeeeeee4-eeee-4eee-8eee-eeeeeeeeeeee",
"deal_reference": "DEAL-2026-0009",
"milestone_id": "fffffff4-ffff-4fff-8fff-ffffffffffff",
"milestone_title": "Tooling and proof approval",
"payout_instruction_id": "22222224-2222-4222-8222-222222222222",
"instruction_label": "Harbourline freight and duties",
"bank_name": "Bank Central Asia",
"account_number_masked": "8730****55",
"amount": 5000000,
"currency": "IDR",
"status": "queued",
"failure_reason": null,
"settled_at": null,
"created_at": "2026-10-13T14:33:16.480Z",
"updated_at": "2026-10-13T14:33:16.480Z"
}
],
"summary": {
"today_count": 4,
"today_amount": 133000000,
"avg_settlement_minutes": 32,
"queued_amount": 58000000
}
},
"pagination": {
"page": 1,
"limit": 2,
"total": 8,
"total_pages": 4
}
}A payout moves from queued to processing to settled. One that fails at the bank stays failed with a failure_reason until RekberPay queues it again; the milestone stays released. The events disbursement.processing, disbursement.settled and disbursement.failed tell you when.
Removing an instruction
An instruction that never received money can be deleted:
curl -X DELETE https://api.rekberpay.com/v1/enterprise/payout-instructions/44444444-4444-4444-8444-444444444444 \
-H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY" \
-H "Idempotency-Key: 55555554-5555-4555-8555-555555555555"const res = await fetch('https://api.rekberpay.com/v1/enterprise/payout-instructions/44444444-4444-4444-8444-444444444444', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
'Idempotency-Key': '55555554-5555-4555-8555-555555555555',
},
});
const data = await res.json();import os
import requests
resp = requests.delete(
"https://api.rekberpay.com/v1/enterprise/payout-instructions/44444444-4444-4444-8444-444444444444",
headers={
"Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
"Idempotency-Key": "55555554-5555-4555-8555-555555555555",
},
timeout=30,
)
print(resp.status_code, resp.json())<?php
$ch = curl_init('https://api.rekberpay.com/v1/enterprise/payout-instructions/44444444-4444-4444-8444-444444444444');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
'Idempotency-Key: 55555554-5555-4555-8555-555555555555',
],
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);200 OK
{
"success": true,
"data": {
"id": "44444444-4444-4444-8444-444444444444",
"deleted": true
}
}