← Files GitBookARCHIVED FILE

references/example-site/guides/tutorials/marketplace/split-payments.md

7.7 KB · Oct 4, 2026 · 12:04 UTC

↓ Download file

---
icon: percent
description: Take your platform's cut on every payment — flat percentages, conditional rules, pass-through fees.
---

# Split each payment with application fees

By the end of this tutorial you'll have a payment split system that takes a flat application fee on every transaction, with hooks to layer conditional rules (per-seller tier, per-product category, per-volume) on top. The build takes about 60 minutes.

This is the platform-revenue side of Connect — your take rate is configured at session creation, the math is automatic, and reporting rolls up across all sellers.

{% hint style="info" %}
**Prerequisites.** [Onboard your first sellers](onboard-sellers.md) finished — you need at least one verified connected account to test against. Read [Connect → Splitting payments](https://app.gitbook.com/s/Xtfxb7OHGyrdfIsObmnu/platform-setup/splitting-payments) for the underlying model.
{% endhint %}

{% embed url="https://www.youtube.com/watch?v=55oOB-lsQKY" %}

## Build it

{% stepper %}
{% step %}

### Set the platform default

In **Connect → Settings → Default split**, set your platform-wide application fee as a percentage of gross. Most platforms start at 5% and adjust. You can also set a flat-fee component (e.g. 5% + $0.30 per transaction).

This is the default; per-payment overrides take precedence.

{% endstep %}

{% step %}

### Override per checkout session

When you create a Checkout session for a payment that should route to a connected account, pass `application_fee_amount`:

{% tabs %}
{% tab title="Node" %}
```js
const session = await evolve.connect.checkoutSessions.create({
  amount: 10000,                          // $100 gross
  currency: "usd",
  connected_account: seller.evolve_account_id,
  application_fee_amount: computeFee(seller, 10000),
  success_url: "...",
  cancel_url: "...",
});
```
{% endtab %}

{% tab title="Python" %}
```python
session = evolve.connect.CheckoutSession.create(
    amount=10000,
    currency="usd",
    connected_account=seller.evolve_account_id,
    application_fee_amount=compute_fee(seller, 10000),
    success_url="...",
    cancel_url="...",
)
```
{% endtab %}
{% endtabs %}

`compute_fee` is your function — see the next step.

{% endstep %}

{% step %}

### Implement your fee logic

Most platforms outgrow a flat percentage within months. Build the fee function as a single point of truth, then evolve it as your business model matures:

{% tabs %}
{% tab title="Node" %}
```js
function computeFee(seller, grossAmount) {
  // Base rate by seller tier
  let rate;
  switch (seller.tier) {
    case "premium": rate = 0.03; break;  // 3%
    case "standard": rate = 0.05; break; // 5%
    case "new": rate = 0.07; break;      // 7% for first 90 days
    default: rate = 0.05;
  }

  // Volume discount: 1.5% above $10k per transaction
  if (grossAmount > 10_00000) rate = Math.min(rate, 0.015);

  // Promotional 0% on Black Friday weekend
  const today = new Date();
  if (isBlackFridayWeekend(today)) rate = 0;

  return Math.round(grossAmount * rate);
}
```
{% endtab %}

{% tab title="Python" %}
```python
def compute_fee(seller, gross_amount):
    rates = {"premium": 0.03, "standard": 0.05, "new": 0.07}
    rate = rates.get(seller.tier, 0.05)

    if gross_amount > 10_00000:
        rate = min(rate, 0.015)

    if is_black_friday_weekend(date.today()):
        rate = 0

    return round(gross_amount * rate)
```
{% endtab %}
{% endtabs %}

{% endstep %}

{% step %}

### Decide who eats the processing fee

By default, the card processing fee comes off the platform's application fee — meaning your effective margin is `application_fee - processing_fee`.

To pass the processing fee through to the seller instead:

{% tabs %}
{% tab title="Node" %}
```js
const session = await evolve.connect.checkoutSessions.create({
  amount: 10000,
  currency: "usd",
  connected_account: seller.evolve_account_id,
  application_fee_amount: 500,
  application_fee_includes_processing: false,  // seller absorbs processing
  success_url: "...",
  cancel_url: "...",
});
```
{% endtab %}

{% tab title="Python" %}
```python
session = evolve.connect.CheckoutSession.create(
    amount=10000,
    currency="usd",
    connected_account=seller.evolve_account_id,
    application_fee_amount=500,
    application_fee_includes_processing=False,
    success_url="...",
    cancel_url="...",
)
```
{% endtab %}
{% endtabs %}

Marketplaces with thin take-rates almost always pass through. Marketplaces competing on seller experience absorb. Pick once at the platform level; keep it consistent.

{% endstep %}

{% step %}

### Watch the splits in the dashboard

In **Reports → Application fees**, you'll see daily/weekly/monthly aggregates of your platform revenue, broken down by seller and by date. Charts you'll watch:

* Total application fees per day.
* Take rate (application fees / gross volume).
* Top sellers by gross volume.
* Top sellers by application fees earned.

For deeper analysis (per-product-category, per-cohort) export the application-fees report and pivot in your data warehouse.

{% endstep %}

{% step %}

### Test with refunds

Refund a charge in test mode. By default, the application fee is refunded proportionally — full refund takes the full application fee, partial refund takes a proportional amount.

To override:

{% tabs %}
{% tab title="Node" %}
```js
const refund = await evolve.refunds.create({
  charge: "ch_3KsM12pL9qXa7",
  refund_application_fee: false,  // platform keeps the fee
});
```
{% endtab %}

{% tab title="Python" %}
```python
refund = evolve.Refund.create(
    charge="ch_3KsM12pL9qXa7",
    refund_application_fee=False,
)
```
{% endtab %}
{% endtabs %}

Useful when the seller is at fault for the refund — the platform keeps its cut.

{% endstep %}
{% endstepper %}

## Common pitfalls

<details>

<summary>"Sellers complain the dashboard doesn't show what fees they paid"</summary>

The platform's application fee shows up on each charge as a separate line item. From the seller's connected-account dashboard, they see the gross, the application fee deducted, and the net. If sellers complain, walk them to the per-charge detail page — the breakdown is right there.

</details>

<details>

<summary>"Math doesn't match between Evolve and our internal records"</summary>

Most-cited cause: rounding differences. Always work in integer cents, never in float dollars. `round(amount * rate)` in your code; double-check on Evolve's side that the same integer math applies. One sub-cent rounding error per transaction adds up over 10,000 transactions.

</details>

<details>

<summary>"How do I do tiered commissions (e.g. 5% on first $1k, 3% above)"</summary>

Compute it in your fee function. Evolve's API takes a single `application_fee_amount` per session — your platform decides what to put there. The dashboard's reports show the actual per-charge fee, which is enough for sellers to verify.

</details>

## What's next

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h3><i class="fa-money-bill-transfer" style="color:$primary;">:money-bill-transfer:</i></h3></td><td><strong>Per-seller payout schedules</strong></td><td>How seller balances become bank deposits.</td><td><a href="payout-schedules.md">payout-schedules.md</a></td></tr><tr><td><h3><i class="fa-gavel" style="color:$primary;">:gavel:</i></h3></td><td><strong>Disputes at scale</strong></td><td>Refund and dispute splits explained.</td><td><a href="disputes-at-scale.md">disputes-at-scale.md</a></td></tr><tr><td><h3><i class="fa-code" style="color:$primary;">:code:</i></h3></td><td><strong>Custom onboarding</strong></td><td>For platforms with their own brand.</td><td><a href="custom-onboarding.md">custom-onboarding.md</a></td></tr></tbody></table>

SHA-256: f2affb3ce3155e58313d4a9dfdc64bec066ca7b54e05d295148ade18c5684edf