Receta: paga a tus usuarios finales con tus ventas (dispersión de pagos)
Cobra con VEXPay, acredita a cada uno de tus usuarios finales (personal, contratistas, afiliados) en dólares a tasa BCV en cada período de pago, deja que retiren a su propio Pago Móvil desde tu app y entrégale a cada uno un estado de cuenta mensual. La comisión de retiro la pagas tú.
Qué vas a construir
Tu negocio vende con links de pago, sesiones de checkout o cobros de VEXPay, y el dinero llega a tu saldo. En cada período de pago (semanal, quincenal, mensual) tu sistema administrativo acredita a cada usuario final un monto en dólares; VEXPay lo convierte a la tasa oficial BCV y lo guarda en el saldo propio de esa persona. Cuando la persona quiere su dinero, toca Retirar en tu app, tu servidor le pide el payout a VEXPay y los bolívares llegan a su Pago Móvil. Tus usuarios finales nunca entran a VEXPay.
| Dinero | Dónde está | Quién lo puede mover |
|---|---|---|
| Tus ventas | Tu saldo (retenido 24 h, luego disponible) | Tú: acreditas a usuarios finales o retiras a tu propio banco |
| Un crédito a un usuario final | El saldo de ese usuario (pendingVes, luego availableVes) | Tú, en nombre del usuario: retiro a su Pago Móvil verificado |
| La comisión de retiro | Se cobra de tu saldo en cada retiro | VEXPay |
Cómo encajan las piezas
| Tu sistema | API de VEXPay |
|---|---|
| Entra una persona (empleado, afiliado…) | POST /v1/merchants + agregar y verificar su Pago Móvil |
| Corrida del período: "pagar $100 a cada persona" | POST /v1/merchants/:id/transfers con amountUsd, uno por persona |
| Pantalla de saldo de la persona | GET /v1/merchants/:id/balance |
| La persona toca Retirar | POST /v1/payouts con fromMerchantBalance: true |
| Historial / estado de cuenta mensual | GET /v1/merchants/:id/transactions, GET /v1/merchants/:id/statement?month=AAAA-MM |
| Avisos de estado | Webhooks: merchant.balance.updated, payout.completed, payout.failed |
- Guarda tu API key solo en tu servidor, nunca en una app móvil ni en el navegador.
- Guarda el
merchantIdde VEXPay junto a cada persona en tu base de datos; usa tu propio id comoexternalRef. - En la API un usuario final es un
merchant: el mismo objeto que usan los marketplaces para sus vendedores.
Paso 01
Cobra tus ventas
Vende como ya lo haces: links de pago del portal, sesiones de checkout o cobros por API. Cada venta completada suma su neto (después de la comisión de procesamiento de VEXPay) a tu saldo. Las ventas en Live quedan retenidas 24 horas (heldVes) antes de estar disponibles; tu saldo y cada movimiento están en GET /v1/balance y GET /v1/balance/transactions.
Paso 02
Registra a cada usuario final y verifica su Pago Móvil
# 1. Crea el usuario final (externalRef = tu propio id de la persona)
curl --request POST "${API_URL}/v1/merchants" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "externalRef": "emp-104", "name": "Ana Rodriguez", "identification": "V12345678", "contactEmail": "ana@mail.com", "contactPhone": "04141234567" }'
# 2. Agrega su Pago Móvil
curl --request POST "${API_URL}/v1/merchants/MERCHANT_ID/payout-methods" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "bankCode": "0105", "phone": "04141234567" }'
# 3. Dos micro-depósitos y luego confirma los montos que recibió la persona
curl --request POST "${API_URL}/v1/merchants/MERCHANT_ID/payout-methods/METHOD_ID/verify/start" --header "x-api-key: ${VEXPAY_API_KEY}"
curl --request POST "${API_URL}/v1/merchants/MERCHANT_ID/payout-methods/METHOD_ID/verify" \
--header "content-type: application/json" --header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "amount1": "0.37", "amount2": "0.82" }'Pídele a la persona, dentro de tu app, los dos montos pequeños que recibió. El dinero solo sale hacia un método verificado. Detalle completo: Registrar un vendedor.
Paso 03
Corre el período: acredita a cada persona en dólares
Para cada persona, envía el monto en dólares y un transferKey único por persona y período. VEXPay convierte a la tasa BCV de ese momento, debita tu saldo y acredita a la persona. Si tu proceso se cae y vuelve a correr, el mismo transferKey devuelve el primer resultado: nadie cobra dos veces y nadie se recalcula a otra tasa.
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" }'
# 200 →
# { "pendingVes": "0.00", "availableVes": "21540.00", ...,
# "transfer": { "transferKey": "2026-11-q1-emp-104", "amountVes": "21540.00",
# "amountUsd": "100.00", "rate": "215.4000", "rateSource": "bcv",
# "rateAsOf": "2026-11-15T13:00:00.000Z" } }const period = '2026-11-q1';
for (const person of await db.people.activeWithVexpayId()) {
const res = await fetch(`${process.env.VEXPAY_API_URL}/v1/merchants/${person.vexpayMerchantId}/transfers`, {
method: 'POST',
headers: { 'content-type': 'application/json', 'x-api-key': process.env.VEXPAY_API_KEY },
body: JSON.stringify({ amountUsd: person.amountUsd, transferKey: `${period}-${person.id}` }),
});
if (res.status === 503) throw new Error('Tasa BCV no disponible, reintenta la corrida luego'); // es seguro repetirla
if (!res.ok) { await db.payRun.fail(person.id, await res.json()); continue; }
const { transfer } = await res.json();
await db.payRun.record(person.id, transfer); // guarda amountVes + rate para tu contabilidad
}- ¿Prefieres fijar los bolívares tú? Envía
amountVesen lugar deamountUsd(uno u otro). - Tu saldo debe cubrir la corrida: revisa
GET /v1/balanceantes. Un crédito que no alcanzas a cubrir responde 422insufficient_balancey no registra nada. - Los créditos pagados con ventas que siguen en su retención de 24 horas esperan en el
pendingVesde la persona hasta que esa retención termina. Correr el proceso al día siguiente de las ventas evita la espera.
Paso 04
Deja que cada persona retire desde tu app
Muéstrale a la persona su availableVes (de GET /v1/merchants/:id/balance). Cuando pida un retiro, tu servidor envía el payout. Recibe exactamente el monto; la comisión de retiro se cobra de tu saldo.
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-0007", "fromMerchantBalance": true }'
# GET /v1/payouts/:id →
# { "status": "completed", "monto": "20000.00", "feeVes": "253.85", "feePayer": "tenant", ... }| Comisión de ejemplo: 1% (mín. $0,25) + $0,25, BCV 215,40 | Pagas tú |
|---|---|
| Retiro de Bs 20.000,00 | Bs 200,00 + Bs 53,85 = Bs 253,85 |
| Retiro de Bs 2.000,00 | Bs 53,85 (mínimo) + Bs 53,85 = Bs 107,70 |
- Usa un
externalRefnuevo por cada solicitud de retiro y repítelo en los reintentos: un reintento nunca paga dos veces. - Mantén una pequeña reserva en tu propio saldo para las comisiones. Sin ella el retiro se rechaza con 422
insufficient_balanceyreason: "tenant_fee_unfunded". - Escucha
payout.completedypayout.failed. Si el banco rechaza un retiro, el dinero vuelve al saldo disponible de la persona y la comisión vuelve al tuyo. - Puedes dejar que cada persona elija cuánto retirar, o que retire todo su
availableVescon un toque.
Paso 05
Estados de cuenta mensuales y tu propia exportación
El estado de cuenta de cada persona muestra el saldo inicial, cada crédito (con el monto en dólares y la tasa BCV), liberación y retiro del mes, y el saldo final. Los meses van en hora de Venezuela. Saldo inicial más movimientos siempre es igual al saldo final.
# JSON, para tus propias pantallas
curl "${API_URL}/v1/merchants/MERCHANT_ID/statement?month=2026-11" --header "x-api-key: ${VEXPAY_API_KEY}"
# CSV, para enviarlo a la persona o a tu contador
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
# Historial completo, del más reciente al más antiguo, paginado
curl "${API_URL}/v1/merchants/MERCHANT_ID/transactions?limit=50" --header "x-api-key: ${VEXPAY_API_KEY}"Para el cierre del mes no hace falta código: Portal → Merchants → Monthly statement descarga una persona, o a todas en un solo CSV con su nombre y cédula en cada fila. Tu propio lado (ventas, créditos, comisiones) está en GET /v1/balance/transactions: los créditos aparecen como seller_transfer y las comisiones como disbursement_payout_fee.
Lista para salir a producción
- Corre todo el flujo con tu key de Test: una venta, un crédito en dólares, un retiro y un estado de cuenta (Prueba todo primero).
- Dile a VEXPay cuántas personas tienes y el monto usual por período, para ajustar a tu nómina el límite de pagos de cuentas nuevas (USD 300 en cualquier período de 24 horas durante los primeros 30 días). Por encima de él, los retiros esperan revisión en
awaiting_approval. - Acuerda con VEXPay el precio de tu comisión de retiro.
- Registra un endpoint de webhooks y maneja
payout.completed/payout.failed(Configurar webhooks). - Haz que tu proceso del período se pueda repetir sin riesgo (mismo
transferKey) y que tus retiros se puedan reintentar (mismoexternalRef).
Preguntas
| Pregunta | Respuesta |
|---|---|
| ¿Mis usuarios finales necesitan una cuenta de VEXPay? | No. Tu sistema llama a la API con tu key; ellos solo ven tu app y su Pago Móvil. |
| ¿Qué tasa se usa? | La tasa oficial BCV del momento del crédito, guardada con él. Las partes en dólares de la comisión de retiro usan la tasa BCV del momento del retiro. |
| ¿Puedo reversar un crédito? | No por la API. El dinero que acreditas es de la persona hasta que lo retire; acredita solo lo que debes. Escríbenos si hubo un error. |
| ¿Y si un cliente disputa una venta con tarjeta después de que pagué a mi gente? | El reembolso o contracargo se descuenta de tu saldo, no del de tus usuarios finales. Recuperarlo de ellos te corresponde a ti. |
| ¿Puedo pagar a una cuenta bancaria en lugar de Pago Móvil? | Los retiros van al Pago Móvil verificado de la persona. |
| ¿Pago comisión cuando acredito a alguien? | No. Pagas la comisión de procesamiento de tus ventas y la comisión de retiro cuando una persona retira. |
Relacionado: Paga a tus usuarios · Registrar un vendedor · Comerciantes y payouts · Leer saldo y retenciones