Developer guide
VEXPay siteAPI reference
Browse documentation

Verify a Pago Móvil transfer

Show customers the account to pay into, then match their transfer reference against bank records.

Pago Móvil in the hosted checkout

Hosted checkouts, payment links and checkout sessions can offer Pago Móvil next to card and Débito Inmediato (the bank debit with an OTP, c2p). The buyer sends the Pago Móvil from their own bank app and VEXPay confirms it automatically — you do not call verify yourself.

  1. The buyer enters their details

    Cédula or RIF and the phone they will pay from.

  2. VEXPay shows where to pay

    The bank, phone and RIF to send to, and the exact bolívar amount, each with a copy button. The amount is priced at your Bolívar rate (BCV or market) when the buyer starts.

  3. The buyer pays from their bank app

    From the same phone they entered. VEXPay matches the incoming transfer on phone, amount and time, completes the payment and fires payment.completed — usually within seconds.

  4. Fallback: bank and reference

    If the buyer paid from another phone and nothing is confirmed after 5 minutes, they pick the bank they paid from and type the bank reference to confirm it.

Only Pago Móvilbash
curl --request POST "${API_URL}/v1/checkout/sessions" \
  --header "content-type: application/json" \
  --header "x-api-key: ${VEXPAY_API_KEY}" \
  --data '{ "amountUsd": 10.00, "methods": ["pago_movil"] }'

Show the customer where to pay

Before the customer opens their banking app, show them the account to send the Pago Móvil to. The bank, phone and identification come from GET /v1/payments/pago-movil/receiving-account — never hard-code them.

curlbash
curl "${API_URL}/v1/payments/pago-movil/receiving-account" \
  --header "x-api-key: ${VEXPAY_API_KEY}"
Nodejavascript
const account = await vexpay.payments.pagoMovil.receivingAccount();
if (account.configured) {
  // Show: account.bankName (account.bankCode), account.phone, account.identification
}
Pythonpython
account = vexpay.payments.pago_movil.receiving_account()
if account.configured:
    # Show: account.bankName (account.bankCode), account.phone, account.identification
    ...
Response shapejson
{
  "provider": "…",
  "bankCode": "0000",
  "bankName": "Banco receptor",
  "phone": "04125555555",
  "identification": "13536734",
  "configured": true,
  "missing": [],
  "livemode": true
}

The account follows your Pago Móvil routing: the same provider POST /v1/payments/pago-movil/verify uses for your enabled and default providers, skipping any provider not allowed Pago Móvil on your account. There is no override, so what you show is always the account verify checks. Fetch it at checkout time or cache it briefly; it changes only when your provider routing does.

Verify the reference

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": 8.75,
    "reference": "12345678",
    "dateMovement": "2026-07-20",
    "externalRef": "order_demo_1044"
  }'

reference must contain 4–32 digits. dateMovement is optional and uses YYYY-MM-DD.

Send the reference exactly as the customer’s bank receipt shows it, or at least its last 6 digits: banks number the same transfer differently, so when the transfer is confirmed from the bank’s notification, VEXPay matches on the last 6 digits. If the customer sent more bolívars than requested, the payment completes for the amount actually received — read vesAmount and usdAmount from the receipt, not from your request. Sending less still fails with an amount mismatch.