Skip to content

Enterprise platform fee ​

Every enterprise deal pays one platform fee to RekberPay. This page explains how it is priced, how the two parties split it, and where it shows in the API. Auth, roles, the workspace header and the shared limits are explained in Enterprise overview.

How the fee is priced ​

platform_fee = max(floor(deal total x rate), minimum), at most deal total minus 1 per milestone
  • Rate: 2% of the deal total by default.
  • Minimum: Rp5.000 per deal by default. The minimum is in rupiah and applies to IDR deals only; a deal in another currency pays the rate with no minimum.
  • Cap: the fee never goes above the deal total minus 1 per milestone, so every milestone always pays out at least 1.
  • Volume pricing (optional): RekberPay can agree a lower rate once your workspace releases more volume. Each tier says "from this much released in the last 30 days, this rate". The highest tier your workspace reached applies when the deal is created. Rates never go up with volume. Only IDR deals count toward the volume, and sandbox volume only counts toward sandbox deals.

The pricing is the pricing of the workspace that creates the deal (the RekberPay customer). It is set by RekberPay for your workspace and cannot be changed through the API; talk to your account manager about volume pricing.

Who pays: buyer and seller ​

In an enterprise deal the buyer is your workspace: it funds the milestones. The seller is the deal counterparty: it receives the payouts. Responses name them payer: "workspace" and payee: "counterparty".

The two parties agree who pays the fee per deal:

fee_allocationfee_buyer_percentMeaning
buyer100Your workspace pays the whole fee
seller0The counterparty pays the whole fee
split0 to 100Your workspace pays this whole percent, the counterparty the rest (0 and 100 work the same as seller and buyer)

You can send fee_allocation, fee_buyer_percent, or both (they must agree). When a deal is created without either, it takes the workspace default, which the workspace owner sets in the dashboard (Settings, Platform fee).

When a split does not divide evenly, the counterparty share takes the odd rupiah, so buyer_fee + seller_fee is always exactly platform_fee.

What it does to the money ​

  • Your share is added to funding. Each milestone carries a pro rata part of your share (buyer_fee). The money to send for a milestone is funding_amount = amount + buyer_fee.
  • The counterparty share is withheld from payouts. Each milestone carries a pro rata part of it (seller_fee). The counterparty receives payout_amount = amount - seller_fee, and the release splits must add up to payout_amount (see Release a milestone).
  • Pro rata, exact to the rupiah. Each milestone gets floor(share x milestone amount / deal total) and the last milestone takes the remainder, so the parts always add up to the share.
  • Sandbox deals show the same fee figures, but no real money moves.

When it is fixed ​

Deal stageWhat can change
DraftThe split (PATCH /v1/enterprise/deals/:id). Milestone edits re-spread the fee using the rate and minimum taken when the deal was created
Activated or laterNothing. The fee is part of the terms the counterparty funds and gets paid against (fee.frozen: true)

Pricing changes on your workspace never reach deals that already exist. In rare cases RekberPay may change one deal's split at the request of both parties; that change never touches money already funded or withheld, is written to the deal history (deal.fee_allocation_overridden) with its reason, and recomputes only the shares still open.

In deal responses ​

GET /v1/enterprise/deals/:id and every deal write return deal.fee, and each milestone returns its shares:

json
{
  "deal": {
    "total_amount": 150000000,
    "fee": {
      "rate_bp": 200,
      "rate_percent": 2,
      "min_fee": 5000,
      "tier": null,
      "volume_basis": 0,
      "platform_fee": 3000000,
      "allocation": "split",
      "buyer_percent": 50,
      "seller_percent": 50,
      "buyer_fee": 1500000,
      "seller_fee": 1500000,
      "funding_total": 151500000,
      "payout_total": 148500000,
      "payer": "workspace",
      "payee": "counterparty",
      "frozen": true
    }
  },
  "milestones": [
    { "amount": 50000000, "buyer_fee": 500000, "seller_fee": 500000, "funding_amount": 50500000, "payout_amount": 49500000 },
    { "amount": 100000000, "buyer_fee": 1000000, "seller_fee": 1000000, "funding_amount": 101000000, "payout_amount": 99000000 }
  ]
}

deal.fee is null on a deal created before platform fees existed; such a deal carries no fee. GET /v1/enterprise/deals returns platform_fee per deal (null for those deals), and the deals export adds fee_rate_bp, platform_fee, fee_buyer_percent, buyer_fee and seller_fee columns.

Get the fee terms ​

GET/v1/enterprise/fees

Your workspace's pricing, the default split and the rate in force for your current released volume.

  • Auth: A workspace API key (Authorization: Bearer rpe_...), a personal API key or a dashboard session.
  • Role: Any workspace member (viewer and up).
  • Rate limit: 300 requests a minute per user, shared by every route.
  • Idempotency: Not needed. Reading has no side effects.

Example request ​

bash
curl https://api.rekberpay.com/v1/enterprise/fees \
  -H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY"
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/fees', {
    headers: {
        Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
    },
});
const data = await res.json();
python
import os

import requests

resp = requests.get(
    "https://api.rekberpay.com/v1/enterprise/fees",
    headers={
        "Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
    },
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/fees');
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);

Example response ​

200 OK

json
{
    "success": true,
    "data": {
        "rate_bp": 200,
        "rate_percent": 2,
        "min_fee": 5000,
        "tiers": [{ "min_volume": 1000000000, "rate_bp": 150, "rate_percent": 1.5 }],
        "default_allocation": "buyer",
        "default_buyer_percent": 100,
        "default_seller_percent": 0,
        "uses_platform_rate": true,
        "uses_platform_min": true,
        "volume_window_days": 30,
        "trailing_volume": 1200000000,
        "rate_in_force_bp": 150,
        "rate_in_force_percent": 1.5,
        "tier_in_force": { "min_volume": 1000000000 },
        "can_edit_default_allocation": false,
        "pricing_set_by": "rekberpay"
    }
}

Errors ​

StatusCodeCause
401UNAUTHORIZED, SESSION_EXPIRED, INVALID_TOKENNo session or key, the session expired, or the key is wrong or revoked
403NO_WORKSPACEThe caller has no active membership in the workspace

Preview a deal fee ​

POST/v1/enterprise/fees/preview

The fee a deal with these milestones would pay if you created it now, with the same calculation as Create a deal. Nothing is saved.

  • Auth: A workspace API key (Authorization: Bearer rpe_...), a personal API key or a dashboard session.
  • Role: Any workspace member (viewer and up).
  • Rate limit: 60 previews a minute per user, plus the shared 300 a minute.
  • Idempotency: Not needed. A preview has no side effects.

Body (JSON) ​

NameTypeRequiredDescription
milestonesarrayYes1 to 20 items of { "amount": integer }, whole rupiah 10,000 to 50,000,000,000
fee_allocationstringNobuyer, seller or split. Default: the workspace default split
fee_buyer_percentintegerNo0 to 100, your workspace's share. Required with split
currencystringNoThree letters, default IDR. The minimum applies to IDR only

Example request ​

bash
curl -X POST https://api.rekberpay.com/v1/enterprise/fees/preview \
  -H "Authorization: Bearer $REKBERPAY_WORKSPACE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "milestones": [{ "amount": 50000000 }, { "amount": 100000000 }],
    "fee_allocation": "split",
    "fee_buyer_percent": 50
  }'
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/fees/preview', {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.REKBERPAY_WORKSPACE_KEY}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        milestones: [{ amount: 50000000 }, { amount: 100000000 }],
        fee_allocation: 'split',
        fee_buyer_percent: 50,
    }),
});
const data = await res.json();
python
import os

import requests

resp = requests.post(
    "https://api.rekberpay.com/v1/enterprise/fees/preview",
    headers={
        "Authorization": f"Bearer {os.environ['REKBERPAY_WORKSPACE_KEY']}",
    },
    json={
        "milestones": [{"amount": 50000000}, {"amount": 100000000}],
        "fee_allocation": "split",
        "fee_buyer_percent": 50,
    },
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/fees/preview');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('REKBERPAY_WORKSPACE_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'milestones' => [['amount' => 50000000], ['amount' => 100000000]],
        'fee_allocation' => 'split',
        'fee_buyer_percent' => 50,
    ]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

Example response ​

200 OK

json
{
    "success": true,
    "data": {
        "total_amount": 150000000,
        "rate_bp": 200,
        "rate_percent": 2,
        "min_fee": 5000,
        "tier": null,
        "volume_basis": 0,
        "platform_fee": 3000000,
        "allocation": "split",
        "buyer_percent": 50,
        "seller_percent": 50,
        "buyer_fee": 1500000,
        "seller_fee": 1500000,
        "funding_total": 151500000,
        "payout_total": 148500000,
        "payer": "workspace",
        "payee": "counterparty",
        "milestones": [
            { "amount": 50000000, "buyer_fee": 500000, "seller_fee": 500000, "funding_amount": 50500000, "payout_amount": 49500000 },
            { "amount": 100000000, "buyer_fee": 1000000, "seller_fee": 1000000, "funding_amount": 101000000, "payout_amount": 99000000 }
        ],
        "is_test": false
    }
}

Errors ​

StatusCodeCause
400INVALID_BODYNo milestones, more than 20, an amount out of range, or a percent outside 0 to 100
400INVALID_FEE_ALLOCATIONsplit without fee_buyer_percent, or buyer/seller with a percent that disagrees
401UNAUTHORIZED, SESSION_EXPIRED, INVALID_TOKENNo session or key, the session expired, or the key is wrong or revoked
429RATE_LIMITEDMore than 60 previews a minute

Set the default split ​

PUT/v1/enterprise/fees/default-allocation

Sets the split that prefills new deals in your workspace. Existing deals keep the split they were created with.

  • Auth: Dashboard session only. API keys, workspace or personal, get 403 KEY_NOT_ALLOWED.
  • Role: owner only.
  • Rate limit: 30 money writes a minute per user, plus the shared 300 a minute.
  • Idempotency: Send an Idempotency-Key header (UUID v4). A retry with the same key and body returns the first answer with Idempotent-Replay: true.

Body (JSON) ​

NameTypeRequiredDescription
fee_allocationstringOne of the twobuyer, seller or split
fee_buyer_percentintegerOne of the two0 to 100, your workspace's share. Required with split

Example request ​

bash
curl -X PUT https://api.rekberpay.com/v1/enterprise/fees/default-allocation \
  -b cookies.txt \
  -H "X-CSRF-Token: $CSRF_TOKEN" \
  -H "X-Enterprise-Account: $WORKSPACE_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "fee_allocation": "split", "fee_buyer_percent": 50 }'
js
const res = await fetch('https://api.rekberpay.com/v1/enterprise/fees/default-allocation', {
    method: 'PUT',
    headers: {
        Cookie: process.env.REKBERPAY_SESSION_COOKIE, // '__Host-rekber_session=...' from POST /v1/auth/login
        'X-CSRF-Token': process.env.REKBERPAY_CSRF_TOKEN,
        'X-Enterprise-Account': process.env.WORKSPACE_ID,
        'Idempotency-Key': crypto.randomUUID(),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ fee_allocation: 'split', fee_buyer_percent: 50 }),
});
const data = await res.json();
python
import os
import uuid

import requests

resp = requests.put(
    "https://api.rekberpay.com/v1/enterprise/fees/default-allocation",
    headers={
        "Cookie": os.environ["REKBERPAY_SESSION_COOKIE"],
        "X-CSRF-Token": os.environ["REKBERPAY_CSRF_TOKEN"],
        "X-Enterprise-Account": os.environ["WORKSPACE_ID"],
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"fee_allocation": "split", "fee_buyer_percent": 50},
    timeout=30,
)
print(resp.status_code, resp.json())
php
<?php

$ch = curl_init('https://api.rekberpay.com/v1/enterprise/fees/default-allocation');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => [
        'Cookie: ' . getenv('REKBERPAY_SESSION_COOKIE'),
        'X-CSRF-Token: ' . getenv('REKBERPAY_CSRF_TOKEN'),
        'X-Enterprise-Account: ' . getenv('WORKSPACE_ID'),
        'Idempotency-Key: ' . bin2hex(random_bytes(16)),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['fee_allocation' => 'split', 'fee_buyer_percent' => 50]),
]);
$response = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

Example response ​

200 OK: the workspace terms, as in Get the fee terms, without the volume fields.

json
{
    "success": true,
    "data": {
        "rate_bp": 200,
        "rate_percent": 2,
        "min_fee": 5000,
        "tiers": [],
        "default_allocation": "split",
        "default_buyer_percent": 50,
        "default_seller_percent": 50,
        "uses_platform_rate": true,
        "uses_platform_min": true,
        "volume_window_days": 30
    }
}

Errors ​

StatusCodeCause
400INVALID_BODYNeither field sent, or a percent outside 0 to 100
400INVALID_FEE_ALLOCATIONsplit without fee_buyer_percent, or buyer/seller with a percent that disagrees
403KEY_NOT_ALLOWEDThe request came with an API key
403FORBIDDENThe caller is not the workspace owner

Fee errors on other endpoints ​

StatusCodeWhere
400INVALID_FEE_ALLOCATIONCreate a deal, update a draft deal
400SPLITS_MISMATCHRelease: the splits do not add up to the milestone payout_amount
409NOT_DRAFTUpdate a deal: the split of an activated deal cannot change

Escrow, payment services and B2B deals for Indonesian businesses.