Recibir eventos en tu sistema (webhooks)
Recibe en tu servidor un aviso firmado por cada venta, reembolso, suscripción o cliente nuevo, con reintentos automáticos e historial de entregas.
Un webhook es una dirección de tu sistema a la que Vipter llama cuando algo pasa en la tienda: una venta aprobada, un reembolso, una suscripción cancelada. Cada llamada es un POST con los datos en JSON y una firma que prueba que vino de Vipter. Esta página es para quien va a programar la recepción, o para que se la pases a esa persona.
Antes de empezar
- Una dirección
https://en tu sistema que aceptePOSTy responda con un código 2xx en hasta 10 segundos. - Rol Admin o Propietario en el proyecto de Vipter.
Paso 1: agregar el endpoint
- En el panel de Vipter, abre GeneralIntegracionesAutomatizacionesWebhooks.
- Haz clic en Agregar endpoint.
- Completa los campos numerados:

| # | Campo | Qué pegar |
|---|---|---|
| 1 | URL del endpoint | La dirección que va a recibir los eventos. Tiene que empezar con https://. |
| 2 | Descripción | Un recordatorio para ti, como "ERP de la tienda". Hasta 200 caracteres. |
| 3 | Tipos de evento | Marca solo los eventos que usa tu sistema. Sin ninguno marcado, el endpoint recibe todos, incluso los que se creen en el futuro. |
- Haz clic en Crear endpoint.
Los eventos de un endpoint no se pueden editar después. Para cambiar la lista, crea un endpoint nuevo y quita el anterior.
Paso 2: guardar el secreto de firma
Justo después de crearlo, Vipter muestra Tu secreto de firma: un valor que empieza con whsec_. Guárdalo ahora. Solo se muestra una vez; puedes rotarlo después.
Copia el secreto y guárdalo en tu sistema, por ejemplo en una variable de entorno. Después de cerrar la ventana, el endpoint solo muestra el final del secreto.
Trata el secreto como una contraseña
Quien tiene el secreto puede falsificar eventos que pasan la verificación. No pongas el secreto en el código fuente ni lo envíes por correo. Si se filtra, genera otro con el botón Rotar secreto.
Paso 3: verificar la firma
Cada llamada trae estos encabezados:
| Encabezado | Contenido |
|---|---|
Vipter-Signature | t=<fecha en segundos Unix>,v1=<firma>. Durante la rotación del secreto, viene un segundo v1=. |
Vipter-Event-Id | El ID del evento, como evt_…. |
Vipter-Event-Type | El tipo del evento, como order.paid. |
User-Agent | Vipter-Webhooks/1.0 |
La firma es un HMAC SHA-256, en hexadecimal, calculado con tu secreto sobre el texto <t>.<cuerpo>: el valor de t, un punto y el cuerpo de la solicitud exactamente como llegó. Para comprobarla:
- Lee el cuerpo sin procesar, antes de cualquier conversión a JSON. Un cuerpo reformateado genera otra firma.
- Recalcula el HMAC con tu secreto y compáralo con cada
v1=del encabezado. Basta con que uno coincida. - Rechaza las llamadas con un
tdemasiado antiguo. El ejemplo de abajo acepta hasta 5 minutos de diferencia.
El mismo código aparece en el panel, en Fragmento de verificación (Node.js):
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyVipterSignature(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return header.split(',').filter((p) => p.startsWith('v1=')).some((p) => {
const given = Buffer.from(p.slice(3), 'hex');
return given.length === expected.length / 2 && timingSafeEqual(given, Buffer.from(expected, 'hex'));
});
}Un ejemplo con Express, que recibe el cuerpo sin procesar y responde enseguida:
import express from 'express';
const app = express();
app.post('/webhooks/vipter', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body.toString('utf8');
if (!verifyVipterSignature(raw, req.get('Vipter-Signature') ?? '', process.env.VIPTER_WEBHOOK_SECRET)) {
return res.status(400).send('firma inválida');
}
const event = JSON.parse(raw);
// Guarda event.id e ignóralo si ya se procesó.
res.sendStatus(200);
// Procesa event.type y event.data.object después de responder.
});Paso 4: enviar un evento de prueba
- Con el endpoint activo, haz clic en Enviar evento de prueba, arriba en la página.
- Aparece Evento de prueba en cola. y la entrega aparece en Entregas recientes.
La prueba es un evento customer.created con un cliente ficticio y "test": true dentro de data.object. Solo llega a los endpoints activos que reciben customer.created o todos los eventos.
Funcionó si
La entrega aparece en Entregas recientes con el estado succeeded y el código HTTP que respondió tu sistema, y tu sistema aceptó la firma.
El formato de los eventos
Todos los eventos tienen el mismo sobre. El objeto en data.object depende del tipo.
{
"id": "evt_4f1c2a9b0d3e5f6a7b8c9d0e",
"object": "event",
"type": "order.paid",
"created": 1790000000,
"livemode": true,
"api_version": "2026-09-01",
"data": {
"object": {
"object": "order",
"id": "…",
"status": "…",
"total_amount": 19700,
"currency": "BRL"
}
}
}ides único por evento. Úsalo para ignorar repeticiones: una entrega reenviada llega con el mismoid.- Los montos de dinero vienen en centavos, como
19700para R$ 197,00. - Pedido (
"object": "order"):id,customer_id,customer_email,subscription_id,status,total_amount,currency,refunded_amount,order_type,recurrence,offer_id,payment_method,provider_slug,paid_at,items,external_order_id,status_source,created_at,updated_at. Enorder.paid, tambiéndownloads, con los enlaces de descarga del comprador cuando el producto tiene archivos. - Suscripción (
"object": "subscription"):id,customer_id,customer_email,customer_name,status,current_offer_id,offer_name,product_id,product_name,billing_cycle,currency,current_amount,current_period_start,current_period_end,next_billing_at,trial_start,trial_end,cycles_completed,cycle_limit,cancel_at_period_end,cancelled_at,cancellation_reason,payment_instrument_id,created_at,updated_at. - Cliente (
"object": "customer"):id,email,name,phone,document_type,metadata,created_at,updated_at. - Checkout abandonado (
"object": "checkout_abandonment"): el comprador (customer), la oferta, el producto, la cantidad y el monto.
Lista de eventos
| Evento | Cuándo se envía |
|---|---|
order.paid | Se aprobó un pago. También vale para las renovaciones de suscripción, con recurrence: "subsequent", y para las ventas marcadas como pagadas por el equipo, con status_source: "manual". |
order.failed | Se rechazó un cobro. |
order.refunded | Se reembolsó un pedido. |
order.partially_refunded | Se reembolsó parte de un pedido. |
order.charged_back | El comprador disputó la compra con su banco (contracargo). |
subscription.created | Se creó una suscripción. |
subscription.renewed | Se renovó una suscripción. |
subscription.dunning | El cobro de la renovación falló y la suscripción está en morosidad. |
subscription.reactivated | Una suscripción volvió a estar activa. |
subscription.upgraded | El suscriptor cambió a un plan más caro. |
subscription.downgraded | El suscriptor cambió a un plan más barato. |
subscription.payment_method_changed | Se cambió la tarjeta de la suscripción. |
subscription.paused | Se pausó la suscripción. |
subscription.resumed | La suscripción pausada se reanudó. |
subscription.cancelled | Se canceló la suscripción. |
subscription.expired | La suscripción terminó. |
customer.created | Se registró un cliente nuevo. |
customer.updated | Cambiaron los datos de un cliente. |
checkout.abandoned | El comprador completó los datos en el checkout y no pagó. Se envía después de un tiempo sin actividad, y solo si no compró en el intervalo. |
checkout.recovered | Un checkout abandonado terminó en compra. |
Entregas y reintentos
Una entrega funciona cuando tu sistema responde con un código 2xx en hasta 10 segundos. Cualquier otra respuesta, incluidas las redirecciones, o la falta de respuesta cuenta como fallo.
Después de un fallo, Vipter lo intenta de nuevo, hasta 8 intentos en total. La espera entre ellos es de 1 minuto, 5 minutos, 30 minutos, 2 horas, 6 horas, 24 horas y 48 horas. Después del octavo intento, la entrega queda con el estado exhausted.
En Entregas recientes, cada fila muestra el Evento, el Estado con el código HTTP y el error, los Intentos y el Último intento. Las entregas que no funcionaron tienen el botón Reenviar, que reinicia los intentos desde cero.
Endpoint desactivado automáticamente
Si 20 entregas seguidas agotan los intentos, Vipter desactiva el endpoint y muestra el motivo en su tarjeta. Una entrega exitosa pone ese conteo en cero. Corrige tu sistema y vuelve a encender el endpoint con el interruptor Activo.
Mientras un endpoint está desactivado, los eventos nuevos no se guardan para él. Usa la lista de pedidos y de suscripciones del panel para revisar qué pasó en ese período.
Rotar el secreto o quitar el endpoint
- Rotar secreto: genera un secreto nuevo y lo muestra una sola vez. ¿Rotar el secreto? El anterior sigue válido por 24 horas. En ese período, cada llamada trae las dos firmas, y tu sistema puede cambiar el secreto sin perder eventos.
- Quitar: ¿Quitar este endpoint y su historial de entregas?
Problemas comunes
-
Ingresa una URL https://
La dirección no empieza con
https://o tiene un error de escritura. No se aceptan direccioneshttp://. -
La firma nunca coincide
El cuerpo se convirtió a JSON antes de la verificación, o el secreto es de otro endpoint. Verifica el cuerpo sin procesar y revisa el final del secreto en la tarjeta del endpoint.
-
Las entregas fallan con
timeoutTu sistema tarda más de 10 segundos en responder. Responde 200 en cuanto valides la firma y procesa el evento después.
-
El botón de prueba está deshabilitado
No hay ningún endpoint activo. Enciende el interruptor Activo de un endpoint.
Qué hacer después
- Para enviar las ventas a una plataforma de anuncios en lugar de a tu sistema, consulta cómo funciona el seguimiento de conversiones.
- Conecta un área de miembros lista, como MemberKit, sin programar.
Verificar el dominio de envío (SPF, DKIM y DMARC)
Entiende los registros DNS que prueban que los correos de la tienda son tuyos, dónde conseguir cada uno y cómo leer la verificación de dominio de Vipter.
Datos del proyecto
Edita el nombre, país, moneda, zona horaria, contacto, sitio, MCC, slug, página de éxito predeterminada y dirección de la tienda, y conoce lo que queda fijo después del registro ante las marcas de tarjeta.