Developer guide
VEXPay siteAPI reference
Browse documentation

Disbursements: pay your end users from your sales

Credit each of your end users (staff, contractors, affiliates) in dollars at the BCV rate out of the money you collect, let them withdraw to their own Pago Móvil, and download a monthly statement per person.

What you will do

Your sales land in your VEXPay balance. Each pay period you credit every end user an amount in dollars; VEXPay converts it at the official BCV rate and keeps it in that person's balance. Each person then withdraws to their own Pago Móvil when they want, through your own system. You pay the withdrawal fee, not them. Each end user is a merchant in the API.

  • Disbursements turned on for your account. Ask VEXPay; it works in Test mode right away and in Live after go-live approval.
  • Your server holds your API key. Your end users never sign in to VEXPay: your admin system calls the API for them.
  • Each end user registered with a verified Pago Móvil (see Onboard a seller).

Steps

  1. Collect

    Sell with payment links, checkout sessions or charges as usual. Each bolívar sale is available in your balance once the bank confirms it (unconfirmedVes until then).

  2. Register your end users

    POST /v1/merchants once per person, then add and verify their Pago Móvil payout method. Keep the returned merchantId in your system next to the person.

  3. Credit each person in dollars

    POST /v1/merchants/:id/transfers with amountUsd and a transferKey that is unique per person and pay period (for example 2026-11-q1-emp-104). The response shows amountVes, the rate and rateAsOf. Sending the same transferKey again returns the first result, never a second credit at a new rate.

  4. The person withdraws

    When the person asks for a withdrawal in your system, call POST /v1/payouts with their merchantId, the bolívar monto, concepto, a unique externalRef and fromMerchantBalance: true. They receive the full monto; the withdrawal fee is charged to your balance.

  5. Download the month

    GET /v1/merchants/:id/statement?month=2026-11 (add &format=csv for a file), or Portal → Merchants → Monthly statement for one person or everyone in one CSV.

Credit $100 at BCVbash
curl --request POST "${API_URL}/v1/merchants/MERCHANT_ID/transfers" \
  --header "content-type: application/json" \
  --header "x-api-key: ${VEXPAY_API_KEY}" \
  --data '{
    "amountUsd": "100.00",
    "transferKey": "2026-11-q1-emp-104"
  }'
# → { "pendingVes": "...", "availableVes": "...",
#     "transfer": { "amountVes": "21540.00", "amountUsd": "100.00", "rate": "215.4000", "rateSource": "bcv", ... } }
Withdrawalbash
curl --request POST "${API_URL}/v1/payouts" \
  --header "content-type: application/json" \
  --header "x-api-key: ${VEXPAY_API_KEY}" \
  --data '{
    "merchantId": "MERCHANT_ID",
    "monto": "20000.00",
    "concepto": "Retiro",
    "externalRef": "wd-emp-104-0001",
    "fromMerchantBalance": true
  }'
Monthly statement (CSV)bash
curl "${API_URL}/v1/merchants/MERCHANT_ID/statement?month=2026-11&format=csv" \
  --header "x-api-key: ${VEXPAY_API_KEY}" --output emp-104-2026-11.csv

When the money can be withdrawn

A credit paid with money that is already available in your balance can be withdrawn at once. A credit paid with sales the bank has not confirmed yet sits in the person's pendingVes and moves to availableVes when they are confirmed. Crediting after the sales are confirmed avoids the wait.

The withdrawal fee

Each withdrawal costs a percentage of monto with a minimum in dollars, plus a fixed part in dollars; the dollar parts convert at the BCV rate of that moment. VEXPay agrees the price with you before you go live.

Example: 1% (min $0.25) + $0.25, BCV 215.40Fee
Withdrawal of Bs 20,000.00Bs 200.00 + Bs 53.85 = Bs 253.85
Withdrawal of Bs 2,000.00Bs 53.85 (minimum) + Bs 53.85 = Bs 107.70
  • The payout shows feeVes and feePayer: "tenant"; the person was debited only monto.
  • Your balance shows a disbursement_payout_fee movement. If the bank rejects the withdrawal, monto goes back to the person and the fee back to you (disbursement_payout_fee_reversal).
  • Keep a small reserve in your balance: if it cannot cover the fee, the withdrawal is refused with 422 insufficient_balance and reason: "tenant_fee_unfunded".

Add money that is not a sale (top-ups)

When the money you pay out comes from outside your sales (for example advertising income), load it into your balance with a top-up: you send a Pago Móvil to VEXPay and it is credited to your balance. Top-ups are turned on by VEXPay, with a monthly limit agreed with you. A top-up is not a sale: it fires no payment.completed webhook and does not count as sales volume.

  1. Start the top-up

    POST /v1/balance/topups with amountVes, the payerPhone and payerCedula you will pay from, and a sourceNote saying where the money comes from (at least 10 characters). Or use Portal → Balance movements → Load balance.

  2. Send the Pago Móvil

    Send exactly amountVes from that phone to the receiver in the response (bank code, phone, ID) within 15 minutes. Pick the bank by its code in your bank app.

  3. It completes on its own

    GET /v1/balance/topups/:id moves to completed when the transfer arrives. You are credited creditedVes = amount − fee. It follows your account's balance hold, if any (none by default).

  4. Optional: make it available now

    If your account has a hold, POST /v1/balance/topups/:id/instant releases the held part at once for instantFeePercent of it (instantFeeVes). Calling it again charges nothing more.

Start a top-upbash
curl --request POST "${API_URL}/v1/balance/topups" \
  --header "content-type: application/json" \
  --header "x-api-key: ${VEXPAY_API_KEY}" \
  --data '{
    "amountVes": "100000.00",
    "payerPhone": "04121234567",
    "payerCedula": "V12345678",
    "sourceNote": "Advertising income, second half of November"
  }'
# → { "id": "...", "status": "pending", "amountVes": "100000.00", "expiresAt": "...",
#     "receiver": { "bankCode": "...", "phone": "...", "identification": "..." } }
Example: fee 3.5% + $0.25, instant 1.5%, BCV 200Bs
Top-up100,000.00
Fee (3,500.00 + 50.00)− 3,550.00
Credited (held if your account has a hold)96,450.00
Instant fee to release it now (1.5%)− 1,446.75
Available at once95,003.25
  • Each top-up counts against your monthly limit (Venezuela calendar month, in dollars at BCV, pending and completed). Over it: 422 topup_cap_exceeded with remainingUsd and remainingVes.
  • Banks limit each Pago Móvil and each day: load a large amount in several top-ups.
  • Your balance shows topup, topup_fee, topup_instant_release and topup_instant_fee movements.
  • A transfer that arrives after the 15 minutes is not credited on its own: contact VEXPay with the reference.

Check that it worked

  • GET /v1/merchants/:id/balance shows the credit in pendingVes or availableVes.
  • GET /v1/merchants/:id/transactions lists credits (with amountUsd and rate), releases and withdrawals, newest first.
  • In the statement, opening + the sum of amountVes = closing. A release row moves money from pending to available, so its amountVes is 0.00.

Leftovers and chargebacks

  • Money you credit belongs to the person until they withdraw it; VEXPay does not take it back on its own. Credit only what you owe.
  • Months are in Venezuela time (America/Caracas).
  • A refund or card chargeback on one of your sales is taken from your balance, even if you already credited that money to your end users. Recovering it from them is up to you.

If something goes wrong

SymptomLikely causeWhat to do
422 insufficient_balance on a creditYour balance cannot cover itCheck GET /v1/balance; wait for more sales.
503 rate_unavailable on a credit or withdrawalThe BCV rate could not be read just now; nothing was recordedRetry in a minute with the same transferKey or externalRef.
422 insufficient_merchant_balance on a withdrawalThe credit is still pending (sales in hold), or the person has less availableCheck GET /v1/merchants/:id/balance; wait for the release.
422 insufficient_balance with reason: "tenant_fee_unfunded"Your balance cannot pay the withdrawal feeKeep a reserve; retry with the same externalRef.
Withdrawal awaiting_approvalOver the first-30-days payout limitNo action; VEXPay reviews it.
403 topups_not_enabledTop-ups are not on for your accountAsk VEXPay to turn them on.
422 topup_cap_exceededOver this month's top-up limitLoad at most remainingVes, or ask VEXPay to review the limit.
Top-up expiredThe transfer did not arrive within 15 minutesStart a new one; if you already sent it, contact VEXPay with the reference.

Related: Recipe: pay your end users · Onboard a seller · Merchants & payouts · Read balance & holds