Skip to main content
Your customers buy from your marketplace, so the sale is yours: the charge lands in your balance, and each seller’s share moves down to it when the charge settles. In this guide you’ll create a seller, sell something, take the payment, and watch the seller’s share arrive. By the end you’ll have run a full destination charge without moving real money.

How it fits together

The sale is yours, so the money lands in your balance first. Bachs moves the seller’s share to the seller’s balance when the charge settles, and the seller withdraws from there.

What you’ll use

Before you start

Every request below goes to https://sandbox-api.bachs.io. Going live is the same calls against https://api.bachs.io with an sk_live_ key. See Take Connect live.

Steps

1

Create the seller

A marketplace seller receives money; it never takes payments of its own. So it only needs the recipient configuration, and its onboarding stays short. Naming no payment-accepting capability is what keeps it that way.
Copy the id. Every step below uses it as the seller’s account id.transfers is what lets the seller receive its share, and payouts is what lets it withdraw. In sandbox both are active immediately; in live they start pending_review until a reviewer enables them. See Capabilities and Testing Connect.
2

Create something to sell

The product is yours, not the seller’s: you are the merchant of record. Price it in NGN, which settles the same day.
Copy the product id for the next step.
3

Create the checkout, naming the seller

transfer_data.destination is what makes this a destination charge: the sale is yours, and the account you name is paid out of it. platform_fee is the part you keep; naming transfer_data.amount instead fixes what the seller receives, with your platform keeping the rest. See Destination charges for both.
Copy the checkout_id and checkout_url.Out of the 100000.00 the customer pays, 20000.00 is yours and the rest is the seller’s.
Name only an account you own. Any other id is refused, in sandbox and in live.
4

Send the customer to pay

In your integration you redirect the customer to checkout_url and they pay on the page we host. To finish this guide, open the link and complete the payment there.This account is in sandbox, so the payment is simulated, no funds move. See Test payment outcomes.
5

Confirm the payment landed

The simulated outcome finalizes a second or two later. Read the checkout back until status is completed:
In your integration you would not poll for this. Subscribe to checkout.completed instead and react when it arrives.
6

Read the split

The seller’s share moves as a transfer when the charge settles, never sooner. Filter by the seller’s account id:
status is paid once settlement has posted the movement. source_charge_id ties the share back to the sale that produced it, which is what you show a seller asking where an amount came from.The transfer carries the full 100000.00 the customer paid, not the 80000.00 the seller ends up with: because you named your own cut with platform_fee, that cut settles separately, readable at Platform fees. Naming transfer_data.amount instead would fix the seller’s share directly, and the transfer would carry only that. See Destination charges for both forms.
7

Read the seller's balance

The share is the seller’s own money now, in its own balance. Send X-Account-Id to read an account’s balance instead of yours:
Drop the header to read your own, which went up by 19850.00. That is the whole sale accounted for:Your 20000.00 fee is what you keep, and our fee comes out of it because the sale is yours. See Processing fees.
The seller held no NGN until this sale. An account holds a currency once money arrives in it.

What you built

A sale that belongs to your marketplace, split with the seller who fulfilled it, and a transfer you can point at to explain where the money went. The seller can withdraw its balance once it has given you a payout destination, which is one of the requirements it still owes. Read what is outstanding from requirements.currently_due on the account, and see Onboard through the API for collecting it, or Onboarding to hand the whole flow to us. Because the sale is yours, a refund or a lost dispute debits you, not the seller. See Refunds and disputes before you go live.

Webhooks to handle

Create your endpoint with event_source set to connect or all, or it receives nothing about your sellers’ accounts. On an event from a seller’s account, the top-level account field names the seller. See Monitor onboarding for reacting to onboarding without polling.

Edge cases

A seller can withdraw only once it has given you a payout destination and its payouts capability is active. In production, capabilities start restricted until a reviewer enables them, so wait for capability.updated rather than assuming. See Requirements.
The sale is yours, so a refund debits your balance, not the seller’s. Decide how you recover the seller’s share before you go live. See Refunds and disputes.
You are liable, as the owner of the charge. The disputed amount is set aside from your available balance while the dispute is open, and the dispute fee is charged when it opens. See Disputes on Connect.
The seller’s share moves when the charge settles, not when the customer pays. Show the seller its earnings from transfer.created, and don’t send a second, manual transfer for the same sale.
You receive payout.failed, and the amount returns to the seller’s balance. Ask the seller to check its destination. A destination is used only once it is usable. See Payouts on Connect.

Go-live checklist

  • Your platform has completed registered-business compliance and connect is active in production. See Take Connect live.
  • Your production keys have only the scopes you use, such as connected_accounts:write and payouts:write.
  • Your production webhook endpoint has event_source set to connect or all, and its signing secret is checked against a live delivery.
  • Your integration waits for capabilities to become active in production instead of assuming them.
  • Every transfer and withdrawal sends an Idempotency-Key, and a 5xx is checked before it is retried.
  • Your team knows that refunds and lost disputes debit your balance.

Build it with an AI assistant

Give this prompt to a coding assistant that can work with your app’s code. It builds the flow on this page into your own app. For prompts that need nothing from Connect, and the rules to give your assistant, see Build with AI. What you’ll build: your platform collects a payment, keeps its fee, and the seller’s share reaches the seller’s Bachs balance at settlement. The seller can then pay out to its own approved destination. Have ready: the Connect capability, seller records, your fee, and the collection currency. Start with one seller per order. If each business should own its sale, use Platform for businesses.
Prompt

Check the result

  • The correct seller account ID is saved against each seller.
  • The payment is accounted for across the seller’s share, platform fee, and processing fee.
  • Settlement creates one seller transfer; the app does not send another manually.
  • Blocked capabilities or an unusable destination prevent a payout.
  • The app tracks payout status through delivery or failure.
  • Your team understands the platform’s responsibility for refunds and disputes.
Before going live, read Connect payouts for withdrawals and refunds and disputes.

Next steps