Developer guide
VEXPay siteAPI reference
Browse documentation

Pay in bolívars, send USDT to a wallet

Add an onward payout to a Pago Móvil or C2P pay-in: when it completes, VEXPay converts its net VES to USDT and sends it to the wallet you gave — no further API calls.

How it works

Send onwardPayout with POST /v1/payments/pago-movil/verify, POST /v1/payments/c2p/request or POST /v1/payments/c2p. When the payment completes, VEXPay chains two things you could also do yourself: a VES → USDT conversion of the payment's net VES (see Convert VES or COP to USDT), then a USDT payout of that USDT minus the network fee to the address (see USDT & USDC).

  1. Collect with an instruction

    Add "onwardPayout": { "network": "BEP20", "address": "0x…" } to the pay-in request. VEXPay checks it before calling the bank: USDT and conversions must be enabled for your account, the network's payouts must be on, and the address must match the network's format. A bad instruction is answered with 400 and no money moves.

  2. Payment completes

    Exactly as without the instruction: payment.completed, your VES balance credited, fees as usual.

  3. Convert

    VEXPay converts the payment's netVes (amount minus VEXPay and application fees) at your usual conversion price: the market rate when the payment completes plus your spread. The rate is not shown in advance; the conversion object carries it.

  4. Send

    When the conversion completes, VEXPay sends its USDT minus the network's payout fee to the address, as a normal USDT payout (payout.completed with txHash).

Statuses and the webhook

The payment (GET /v1/payments/:id and every payment.* webhook) carries onwardPayout: status, network, address, conversionId, payoutId, amountUsdt, feeUsdt, txHash, reason and updatedAt. Every status change also sends onward_payout.updated with paymentId, customerRef and the same object — subscribe to it under "Onward payout".

statusMeaningYour money
pendingThe payment has not completed yetNothing moved
convertingThe conversion exists and is not completedVES debited, USDT not yet credited
waiting_releaseConverted; the USDT is under the 24h balance hold until sendAfterUSDT in your balance, held
sendingThe USDT payout exists and is not finalUSDT reserved for the payout
completedThe payout completed (txHash set)Sent to the address
heldStopped before a step it could not take (reason)Stays in your VES or USDT balance
failedThe payout failed (reason: payout_failed)USDT and fee back in your USDT balance
canceledPayment failed or reversed, or the conversion was canceled (reason)VES back in (or never left) your VES balance

completed, held, failed and canceled are final: VEXPay never continues after them. Funds left in your balance are yours to convert or pay out as usual.

Minimums and holds

reasonWhenWhere the money is
below_conversion_minimumThe net VES is worth less than your conversion minimumVES balance
below_payout_minimumThe USDT minus the network fee is below the network's payout minimumUSDT balance
daily_limit_exceededYour daily conversion cap is reachedVES balance
insufficient_balanceYour available balance no longer covers the stepVES or USDT balance
onward_payout_unavailableUSDT or conversions were turned off for your accountVES balance

Minimums and fees are the same as for any conversion and USDT payout: see GET /v1/conversions/settings and GET /v1/crypto/networks.

Reversals

A C2P payment can be reversed while its onward payout is still pending (the instruction is canceled). Once its conversion exists, POST /v1/payments/:id/reverse answers 409 onward_payout_in_progress.

Example

cURLbash
curl --request POST "${API_URL}/v1/payments/pago-movil/verify" \
  --header "content-type: application/json" \
  --header "x-api-key: ${VEXPAY_API_KEY}" \
  --data '{
    "usdAmount": 20,
    "reference": "40010003",
    "externalRef": "topup-user-42",
    "onwardPayout": { "network": "BEP20", "address": "0x2f5c0000000000000000000000000000000000aa" }
  }'
Webhook (onward_payout.updated)json
{
  "event": "onward_payout.updated",
  "data": {
    "paymentId": "6f1c…",
    "externalRef": "topup-user-42",
    "onwardPayout": {
      "status": "completed",
      "network": "BEP20",
      "address": "0x2f5c0000000000000000000000000000000000aa",
      "conversionId": "c1a2…",
      "payoutId": "9b7e…",
      "amountUsdt": "18.94",
      "feeUsdt": "0.75",
      "txHash": "0x8e1d…",
      "updatedAt": "2026-10-15T14:03:11.000Z"
    }
  }
}

Testing

With a test key the whole chain runs on the sandbox: the conversion and the payout complete at once and nothing is sent on-chain, so you receive converting, sending and completed within seconds of the payment.