Construye tu integración paso a paso
De tu primera llamada a la API a los pagos reales: nueve pasos, en orden, con las solicitudes exactas y lo que debes comprobar antes de seguir.
La ruta de un vistazo
Sigue los pasos en orden. Cada uno termina con un punto de control: cuando se cumple, pasa al siguiente. Todo hasta el paso 8 corre con tu clave Test, así que no se mueve dinero real hasta que salgas a producción.
| Paso | Qué haces | Listo cuando |
|---|---|---|
| 1. Claves | Guarda tu clave Test y la URL de la API en tu servidor | Tu servidor puede leer ambas desde su entorno |
| 2. Primera llamada | Llama a GET /v1/banks | Recibes un 200 con la lista de bancos |
| 3. Elige un flujo | Escoge el checkout alojado o un método directo | Sabes qué endpoint crea tus pagos |
| 4. Primer pago | Crea un pago de prueba y complétalo | El GET muestra el pago COMPLETED |
| 5. Webhooks | Registra un endpoint y verifica las firmas | payment.completed llega a tu servidor y pasa la verificación |
| 6. Reintentos seguros | Agrega idempotencia y recuperación por referencia | Una solicitud reintentada nunca crea un segundo pago |
| 7. Saldos | Lee tu saldo y la retención de 24 h | Puedes explicar disponible, retenido y reserva |
| 8. Payouts | Retira o paga desde los fondos disponibles | Un payout de prueba se completa y llega payout.completed |
| 9. Salir a producción | Solicita la revisión y luego cambia de clave | Tu primer pago real se completa |
Paso 01
Obtén tus claves y prepara tu entorno
Tu cuenta tiene una clave Live y una Test. Usa la clave Test para todo hasta el paso 9: funciona de inmediato, corre en sandboxes y nunca mueve dinero real. Cópiala desde Portal → Credentials.
API_URL=https://api.pay.vexwallet.co
VEXPAY_API_KEY=vk_test_replace_me
VEXPAY_WEBHOOK_SECRET=whsec_replace_mePunto de control: tu servidor lee API_URL y VEXPAY_API_KEY desde su entorno. Más detalle: Autenticación.
Paso 02
Haz tu primera llamada
Cada solicitud envía la clave en el encabezado x-api-key. La lista de bancos es una primera llamada segura: solo lee y no necesita configuración.
curl "${API_URL}/v1/banks" \
--header "x-api-key: ${VEXPAY_API_KEY}"import VexPay from '@vexpay/node';
const vexpay = new VexPay(process.env.VEXPAY_API_KEY);
const banks = await vexpay.banks.list();import os
from vexpay import VexPay
vexpay = VexPay(os.environ["VEXPAY_API_KEY"])
banks = vexpay.banks.list()Punto de control: una respuesta 200 con la lista de bancos. Un 401 significa que la clave falta o es incorrecta. Un SDK oficial (Node, Python, PHP, Laravel) te ahorra escribir tú mismo el HTTP, los reintentos y la verificación de webhooks.
Paso 03
Elige cómo pagan tus compradores
Empieza con el checkout alojado salvo que necesites tus propias pantallas de pago: una solicitud te da una página donde el comprador elige bolívares, stablecoins o pesos colombianos, y VEXPay ejecuta cada paso.
| Opción | Ideal cuando | Se crea con |
|---|---|---|
| Checkout alojado (recomendado) | Quieres todos los métodos sin construir una interfaz de pago | POST /v1/checkout/sessions |
| Enlaces de pago | Vendes sin código (WhatsApp, redes sociales) | Portal → Payment links |
| C2P | Tu propia pantalla; el comprador autoriza con un token bancario | POST /v1/payments/c2p/request y luego POST /v1/payments/c2p |
| Verificación de Pago Móvil | El comprador ya transfirió y te da la referencia | POST /v1/payments/pago-movil/verify |
| Tarjeta (VPOS) | Pagos con tarjeta en tu propio formulario (aplica alcance PCI) | POST /v1/payments/vpos |
| USDT / USDC | Depósitos en stablecoins por cliente | POST /v1/crypto/deposit-addresses |
| Pesos colombianos | Compradores en Colombia (Bre-B, Nequi, Daviplata) | POST /v1/cop/payments |
Punto de control: sabes qué endpoint crea tus pagos. GET /v1/payment-methods te dice qué métodos en bolívares puede ofrecer tu cuenta en este momento.
Paso 04
Crea y completa un pago de prueba
Crea una sesión de checkout para un pedido y envía al comprador a su url (o incrústala con @vexpay/js usando clientSecret). Guarda el id de la sesión con tu pedido.
curl --request POST "${API_URL}/v1/checkout/sessions" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"amountUsd": 25.00,
"description": "Pedido #1042",
"reference": "order-1042",
"successUrl": "https://shop.example/thanks",
"cancelUrl": "https://shop.example/cart"
}'const session = await vexpay.checkout.sessions.create({
amountUsd: 25,
description: 'Pedido #1042',
reference: 'order-1042',
successUrl: 'https://shop.example/thanks',
cancelUrl: 'https://shop.example/cart',
});
// Redirige al comprador a session.url{
"id": "cs_4f0c6f1e2b7d4c1a9e3f5a6b7c8d9e0f",
"object": "checkout.session",
"status": "open",
"url": "https://pay.vexwallet.co/pay/cs-9f2a4b7c1d3e",
"clientSecret": "cs-9f2a4b7c1d3e_secret_k8Jc…",
"amountUsd": "25.00",
"reference": "order-1042",
"livemode": false
}- Abre la url
En modo prueba la página alojada muestra controles de prueba en lugar de datos bancarios reales: completa C2P con el código de Portal → Sandbox, pulsa Simular pago recibido en Pago Móvil o usa los botones de prueba de la página de USDT.
- Revisa el resultado
GET /v1/checkout/sessions/:idmuestrastatus: "paid"y elpaymentId.GET /v1/payments/:idmuestra el pagoCOMPLETED.
Punto de control: la sesión está paid y el pago COMPLETED, todo con livemode: false.
Paso 05
Entrega los pedidos a partir de webhooks firmados
Entrega los pedidos solo desde el servidor: con un webhook payment.completed verificado (o un GET que muestre el pago completado). Las redirecciones del navegador y los eventos de @vexpay/js son indicios, nunca una prueba.
curl --request POST "${API_URL}/v1/webhooks" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{
"url": "https://shop.example/webhooks/vexpay",
"events": ["payment.completed", "payment.failed", "payment.reversed", "payout.completed", "payout.failed"]
}'app.post('/webhooks/vexpay', express.raw({ type: 'application/json' }), async (req, res) => {
const event = vexpay.webhooks.constructEvent(
req.body, // bytes crudos, no JSON parseado
req.headers['vexpay-signature'],
process.env.VEXPAY_WEBHOOK_SECRET,
);
if (event.event === 'payment.completed') {
// Pagos de checkout: identifica tu pedido con data.checkoutSession.reference
await markOrderPaid(event.data.checkoutSession?.reference, event.data.paymentId);
}
res.sendStatus(200);
});- Guarda el
secretde la respuesta de creación: nunca se vuelve a mostrar. - Deduplica con el encabezado
VexPay-Event-Id: el mismo evento puede llegarte más de una vez. - Cada evento se envía una vez, sin reintento automático, y tu endpoint tiene 10 segundos. Encola el trabajo y responde 200 rápido; el paso 6 cubre lo que se te escape.
- Usa
POST /v1/notifications/testpara enviarte una entrega de prueba.
Punto de control: un pago de prueba produce un payment.completed que pasa la verificación de firma y marca el pedido como pagado exactamente una vez. Más detalle: Webhooks.
Paso 06
Haz seguros los reintentos y recupera lo que se te escapó
- Envía Idempotency-Key en cada POST
Usa el id de tu pedido. La misma clave y el mismo body dentro de 24 h repiten la primera respuesta (
Idempotent-Replayed: true) en vez de crear un segundo pago. Los SDKs envían una automáticamente. - Guarda los ids que recibes
Guarda el id de la sesión, el
paymentIdy elpayoutIdcon tu pedido. En payouts y comerciantes,externalRefes en sí la clave de idempotencia. - Recupera por referencia
Si una respuesta o un webhook nunca llegó, consulta el pago:
GET /v1/payments/by-ref/:externalRefoGET /v1/checkout/sessions/:id. Decide según su estado, nunca por un timeout. - Corre un job de conciliación
Una vez al día (o cada hora), recorre
GET /v1/balance/transactionsy compara cada movimiento con tu contabilidad. La suma siempre es igual al total de tu ledger, así que nada puede esconderse.
Punto de control: repetir dos veces la misma solicitud de creación da el mismo pago, y un webhook perdido se detecta con la consulta o el job de conciliación. Más detalle: Idempotencia, Concilia tu saldo.
Paso 07
Lee tu saldo y la retención de 24 h
Cada pago completado llega a tu saldo, pero queda retenido 24 horas antes de que puedas enviarlo en un payout. GET /v1/balance muestra ambas partes y cuándo se libera el siguiente monto retenido.
{
"ledgerNetVes": "7342.50",
"reserveVes": "0.00",
"heldVes": "4342.50",
"nextReleaseAt": "2026-10-20T00:48:52.784Z",
"availableVes": "3000.00",
"balanceHoldHours": 24
}availableVes = ledgerNetVes − reserveVes − heldVes. Solo availableVes se puede enviar en un payout. Lo mismo aplica a USDT (held, heldUsdt) y a los pesos (heldCop). Punto de control: después de un pago de prueba puedes señalar el monto retenido y su hora de liberación. Explicación completa: Saldos, retenciones y payouts.
Paso 08
Envía payouts
| A dónde va el dinero | Endpoint | Antes del primer payout |
|---|---|---|
| Tu propia cuenta bancaria (Bs) | POST /v1/payouts/instant | Guarda y verifica tu cuenta de payouts (dos microdepósitos) |
| Un vendedor o proveedor (Bs) | POST /v1/payouts | Registra al comerciante y verifica su destino Pago Móvil |
| Una wallet cripto (USDT / USDC) | POST /v1/crypto/payouts | Ten saldo en USDT o USDC |
curl --request POST "${API_URL}/v1/payouts/instant" \
--header "content-type: application/json" \
--header "x-api-key: ${VEXPAY_API_KEY}" \
--data '{ "monto": "1000.00", "concepto": "Retiro", "externalRef": "withdraw-2026-10-19" }'Punto de control: un payout de prueba se completa y payout.completed llega a tu endpoint. Más detalle: Comerciantes y payouts, USDT y USDC.
Paso 09
Sal a producción
- Los pasos 4–8 se cumplen con la clave Test, incluida al menos una entrega de webhook (Portal → Webhooks la muestra).
- Tu perfil de negocio y el contacto del dueño están completos en el portal.
- Manejas
payment.failed,payment.reversedypayout.failed, no solo el camino feliz. - Tu job de conciliación corre y te alerta cuando los totales no coinciden.
- Solicita salir a producción
Pulsa Request go-live en el portal. El equipo de VEX Pay revisa tu cuenta; mientras tanto las claves Live responden 403
live_mode_not_activated. - Registra los webhooks Live
Los endpoints de webhook pertenecen a cada clave: registra tu URL de producción con la clave Live y guarda su nuevo secreto.
- Cambia de clave
Cuando recibas
tenant.live_status_changed, crea una clave Live en el portal y despliégala. Haz un pago real pequeño y síguelo hasta tu saldo.