Settle marketplace payments (fee + payout)
Collect from a buyer into the tenant commerce account, retain a platform fee in your app, then pay verified seller Pago Móvil destinations with simple or batch payouts.
What this workflow is
Use this pattern when a seller registers a VES Pago Móvil destination, a buyer pays with their own Pago Móvil (bid or order amount), and your tenant must keep a fee before paying the seller — optionally splitting the credit across more than one verified merchant.
End-to-end steps
- Register and verify the seller
POST /v1/merchants with the seller’s bankCode + phone (and your seller id as externalRef), then run micro-deposit verify on the payout method. Details: Merchants & payouts (/merchants-payouts).
- Resolve the merchant before payout
When settling, look up the seller under your tenant with GET /v1/merchants?externalRef={yourSellerId} — same auth as every other call (`x-api-key`). Prefer this over storing only the gateway merchantId. See /merchants-payouts#lookup-by-ref.
- Charge the buyer
Collect into the tenant commerce account with C2P (recommended: POST /v1/payments/c2p/request then POST /v1/payments/c2p) or débito inmediato (POST /v1/payments/debit/otp then POST /v1/payments/debit). Send a stable payment externalRef for your order/bid.
- Wait for payment.completed
Subscribe to payment.completed / payment.failed. On uncertain responses, recover with GET /v1/payments/by-ref/:externalRef before fulfilling or paying out.
- Compute fee and net VES
In your app: fee = collected × rate (or fixed), net = collected − fee. There is no platform-fee field on the API — you retain the fee by paying the seller less than you collected.
- Pay the seller (or split)
POST /v1/payouts with the seller merchantId, exact net monto, and paymentId from the completed collection — or POST /v1/payouts/batch with paymentId plus one item per destination. Each payout item needs its own idempotent externalRef. Multiple partial payouts are allowed until remaining net is 0.
Fee and split rules
| Rule | Detail |
|---|---|
| Fee ownership | Prefer applicationFeeVes / applicationFeePercent on the charge (platform retains fee; seller net goes to pending). Manual retain-by-paying-less still works without merchantId. |
| Seller ledger | GET /v1/merchants/:id/balance returns pendingVes + availableVes. POST /v1/merchants/:id/transfers moves tenant float → seller pending. fromMerchantBalance payouts debit seller available. |
| Platform balance | GET /v1/balance returns platformAvailableVes, sellerObligationsVes, sellerPendingVes, sellerAvailableVes. |
| Payout amounts | Exact two-decimal VES strings (e.g. "1523.40"). The gateway never FX-converts payouts. |
| paymentId link | Optional on POST /v1/payouts and POST /v1/payouts/batch. Links legs to the funding payment for ops and remaining-net enforcement. |
| Remaining net | remaining = vesAmount − feeVes − sum(PENDING|COMPLETED payouts for that paymentId). FAILED legs free remaining. Exceeding remaining → 422 payment_split_exceeded. |
| Multi-partial | Several payouts/batches may reference the same paymentId until remaining is 0. Same externalRef still idempotent-replays. |
| Batch split | POST /v1/payouts/batch pays many verified merchants in one request. Results are per item — not all-or-nothing. Batch paymentId applies to every item. |
| Commerce float | Classic payouts debit the tenant commerce account. Seller-balance payouts debit merchant available (tenant already reserved via SELLER_TRANSFER). |
| Idempotency | Payment externalRef is correlation only. Merchant and payout externalRef are required idempotency keys; paymentId is included in the payout request hash. |
Minimal examples
After the seller is verified and the buyer charge has completed, settle the net (or a multi-party split) with the payouts API.
curl --request POST "${API_URL}/v1/merchants" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"externalRef": "seller_laganga_7f3a",
"name": "Maria Perez",
"identification": "V12345678",
"contactEmail": "maria@mail.com",
"contactPhone": "04141234567",
"bankCode": "0134",
"phone": "04145555555"
}'curl --request POST "${API_URL}/v1/payments/c2p" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"intentId": "00000000-0000-4000-8000-000000000000",
"usdAmount": 12.50,
"debtorId": "V87654321",
"debtorCellPhone": "584121234567",
"debtorBankCode": 102,
"token": "123456",
"externalRef": "bid_1042"
}'curl --request POST "${API_URL}/v1/payouts" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"merchantId": "00000000-0000-4000-8000-000000000000",
"paymentId": "00000000-0000-4000-8000-000000000010",
"monto": "1371.06",
"concepto": "Bid 1042 net",
"externalRef": "po_bid_1042_seller"
}'curl --request POST "${API_URL}/v1/payouts/batch" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"externalRef": "settle_bid_1042",
"paymentId": "00000000-0000-4000-8000-000000000010",
"items": [
{
"merchantId": "00000000-0000-4000-8000-000000000000",
"monto": "1200.00",
"concepto": "Seller net",
"externalRef": "po_bid_1042_seller"
},
{
"merchantId": "00000000-0000-4000-8000-000000000002",
"monto": "171.06",
"concepto": "Partner share",
"externalRef": "po_bid_1042_partner"
}
]
}'Webhooks and recovery
- Use paymentId on payouts to link settlement to the collection; use payment externalRef for your order id and payout / batch item externalRef for safe retries.
- Subscribe to payment.completed / payment.failed before fulfilling the bid or order.
- Subscribe to payout.completed / payout.failed after you trigger settlement.
- Merchant verification and payout field rules: /merchants-payouts. Signature verification and delivery: /webhooks.