API REST
Crea links de pago programáticamente desde tu backend.
Autenticación
Todas las llamadas requieren el header:
Authorization: Bearer {api_key}:{api_secret}Obtén tu api_key y api_secret en comercios.wepago.com → Configuración → API.
Seguridad
Nunca expongas api_key o api_secret en código frontend. Estas llamadas deben hacerse desde tu servidor.
Crear link de pago
POST https://merchant.api.wepago.com/merchants/subscription-linkBody:
{
"customer": {
"phone": "+573001234567",
"email": "juan@ejemplo.com",
"firstName": "Juan",
"lastName": "Pérez",
"idType": "CC",
"idNumber": "1234567890"
},
"plan": {
"externalReference": "orden-123",
"description": "Suscripción mensual Premium",
"amount": 49900,
"modality": "RECURRING"
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
customer.phone | string | ✅ | Teléfono con código de país (+57...) |
customer.email | string | ✅ | Email del cliente |
customer.firstName | string | — | Pre-llena el formulario |
customer.lastName | string | — | Pre-llena el formulario |
customer.idType | string | — | CC, CE, NIT, PP |
customer.idNumber | string | — | Número de documento |
plan.externalReference | string | ✅ | Tu ID de orden o referencia interna |
plan.description | string | ✅ | Nombre visible del plan en el checkout |
plan.amount | number | ✅ | Monto en centavos de COP (49900 = $499) |
plan.modality | string | — | RECURRING (default) o SINGLE |
Respuesta 200:
{
"token": "V1StGXR8Z5",
"url": "https://checkout.wepago.com/pay/V1StGXR8Z5",
"expiresAt": "2026-04-13T12:00:00.000Z",
"subscriptionPlanId": "01JR9H0BKMCAZ6PY1GR65B91J7"
}Guarda el subscriptionPlanId
Guarda este ID en tu base de datos. Lo necesitas para consultar el estado del pago más adelante con el endpoint de polling.
Redirige al usuario a url o úsala con WepagoPay.open({ token }) (ver SDK).
Consultar estado de un pago
Útil si quieres mostrar el estado en tiempo real en tu interfaz sin esperar el webhook.
GET https://merchant.api.wepago.com/merchants/plans/{subscriptionPlanId}/status
Authorization: Bearer {api_key}:{api_secret}Respuesta 200:
{
"subscriptionPlanId": "01JR9H0BKMCAZ6PY1GR65B91J7",
"externalReference": "orden-123",
"plan": {
"status": "ACTIVE",
"amount": 49900,
"currency": "COP",
"description": "Suscripción mensual Premium",
"nextChargeDate": 1744416000000
},
"lastTransaction": {
"subscriptionTransactionId": "01JR9H0BKMCAZ6PY1GR65B91J6",
"status": "APPROVED",
"amount": 49900,
"chargeDate": 1712534400000,
"wompiTransactionId": "1200969-1775447756-67089"
}
}Estados del plan (plan.status)
| Estado | Significado |
|---|---|
PENDING_ACTIVATION | Link generado, usuario aún no ha pagado |
ACTIVE | Suscripción activa — al menos un cobro exitoso |
PAUSED | Cobros pausados temporalmente |
CANCELLED | Suscripción cancelada |
COMPLETED | Suscripción finalizada |
Estados de la última transacción (lastTransaction.status)
| Estado | Significado |
|---|---|
PENDING | Procesando — espera o reintenta en 5 segundos |
APPROVED | Cobro exitoso |
DECLINED | Rechazado — notifica al usuario |
VOIDED | Anulado |
ERROR | Error técnico |
Patrón de polling recomendado:
async function waitForPayment(subscriptionPlanId, apiKey, apiSecret) {
const maxAttempts = 12
const delayMs = 5000
for (let i = 0; i < maxAttempts; i++) {
const res = await fetch(
`https://merchant.api.wepago.com/merchants/plans/${subscriptionPlanId}/status`,
{ headers: { Authorization: `Bearer ${apiKey}:${apiSecret}` } }
)
const { query } = await res.json()
if (query.lastTransaction?.status === 'APPROVED') return 'approved'
if (query.lastTransaction?.status === 'DECLINED') return 'declined'
if (query.plan.status === 'PENDING_ACTIVATION' && !query.lastTransaction) {
// Usuario aún no ha iniciado el pago
await new Promise(r => setTimeout(r, delayMs))
continue
}
if (query.lastTransaction?.status === 'PENDING') {
await new Promise(r => setTimeout(r, delayMs))
continue
}
break
}
return 'timeout'
}Webhooks vs polling
Para flujos asíncronos (el usuario paga más tarde), usa webhooks. Para flujos donde el usuario paga en el momento y tu interfaz espera el resultado, combina webhooks + polling.
Recibir el resultado del pago
Opción 1 — Webhooks (recomendado)
Wepago envía un POST a tu servidor cuando el pago se completa. Ver guía de webhooks.
Opción 2 — SDK callback
Si usas el widget embebido, el SDK dispara onSuccess / onError en el momento del pago:
WepagoPay.open({
token: 'V1StGXR8Z5',
onSuccess(data) {
// data.transactionId — confirma contra tu backend antes de activar el servicio
verifyPaymentOnYourServer(data.transactionId)
}
})No confíes solo en el callback del frontend
onSuccess puede ser manipulado por el usuario. Siempre confirma el estado en tu backend via webhook o polling antes de activar el servicio.