POST firmada al endpoint de webhook que configuraste, con el cuerpo del evento.
Configuración del endpoint
Tu endpoint debe ser accesible públicamente por HTTPS y responder con cualquier código de estado 2xx. Configura su URL con tu contacto de Meru o desde el dashboard. Al crearlo recibes un secreto de firma (con prefijowhsec_) — guárdalo de forma segura; lo necesitas para verificar las firmas.
Estructura del evento
Todos los cuerpos de entrega tienen la misma forma de nivel superior:string
El tipo de evento (ver los eventos más abajo).
string
Marca de tiempo ISO 8601 de cuándo se emitió el evento.
object
El cuerpo del evento. Su forma depende de
type.Eventos
Las cuentas virtuales no tienen eventos de ciclo de vida
No existe un eventovirtual_account.created, virtual_account.activated ni virtual_account.deactivated. La creación de una cuenta virtual, y su activación o desactivación, no generan un webhook.
La única señal asociada a una cuenta virtual es el depósito en sí: cuando llegan los fondos recibes un payin.updated. Si necesitas su estado actual, consulta los endpoints de cuentas en la API.
Migración de nombres de eventos
Estamos estandarizando algunos nombres de eventos. Durante la transición, se entregan tanto el nombre nuevo como el heredado para el mismo evento, así no se pierde nada mientras migras. Cada evento incluye undata.eventId estable —idéntico entre el nombre nuevo y el heredado—, con el que puedes deduplicar el par.
Los nombres heredados se eliminarán el 15 de noviembre de 2026. Apunta tus handlers a los nombres nuevos antes de esa fecha.
Versionado y deprecación
Los eventos de webhook se versionan por tipo de evento, no por un header ni por un campo del payload. Tu endpoint se suscribe a tipos de evento específicos, así que mantener la versión en el nombre es lo que te permite elegir qué versión recibes.Qué se considera un cambio incompatible
Agregar un campo opcional nuevo adata no es incompatible, y lo publicamos sin una versión nueva: se anuncia en el changelog. Tu handler debe ignorar los campos que no reconozca.
Los cambios incompatibles son eliminar o renombrar un campo, cambiar su tipo o cambiar el significado de un valor. Nunca los aplicamos sobre un tipo de evento existente: en su lugar publicamos uno nuevo con un sufijo de versión —por ejemplo payin.updated.v2— y entregamos ambos en paralelo durante la ventana de deprecación.
Política de deprecación
Cuando deprecamos un tipo de evento o un campo:- Lo anunciamos con al menos 90 días de anticipación, a través del changelog, un aviso en la página de referencia del evento con la fecha de eliminación, y un correo a los suscriptores del evento afectado.
- El evento deprecado y su reemplazo se entregan en paralelo durante toda la ventana, ambos con el mismo
data.eventIdpara que puedas deduplicar el par. - No eliminamos un evento deprecado hasta que sus suscriptores hayan migrado.
Headers de entrega
Cada solicitud incluye estos headers:Verificación de firmas
Cada solicitud se firma con HMAC-SHA256 para que puedas confirmar que viene de nosotros. El contenido firmado es el string{webhook-id}.{webhook-timestamp}.{cuerpoCrudo}, con clave en tu secreto de firma (decodificado de base64 tras quitar el prefijo whsec_), y el resultado se codifica en base64 dentro del header webhook-signature.
Para verificar: recalcula la firma sobre el cuerpo crudo de la solicitud (antes de cualquier parseo de JSON) y compárala contra el header en tiempo constante. Rechaza las entregas cuyo webhook-timestamp tenga más de 5 minutos.
Idempotencia
El mismo evento puede entregarse más de una vez. Usa el headerwebhook-id como clave de idempotencia: guarda los IDs procesados y descarta los duplicados.
Reintentos
Si tu endpoint no devuelve un estado2xx (o agota el tiempo de espera), reintentamos la entrega automáticamente con backoff exponencial a lo largo de varias horas, respetando Retry-After en respuestas de error. Confirma rápido (en pocos segundos) y procesa el trabajo pesado de forma asíncrona. Los endpoints que fallan de forma persistente pueden quedar deshabilitados.
Buenas prácticas
- Verifica siempre la firma contra el cuerpo crudo antes de procesar.
- Responde rápido con un
2xxy procesa de forma asíncrona. - Sé idempotente usando
webhook-id. - No asumas orden — apóyate en
state/previousStateyupdatedAt, no en el orden de entrega. - Registra el
webhook-id, eltypey eldatade cada entrega.
Ejemplo de handler
Pruebas
Expón tu servidor local con un túnel (por ejemplo, ngrok) y registra la URL pública como tu endpoint de webhook:Solución de problemas
- Firma inválida: verifica contra el cuerpo crudo (no un JSON re-serializado), usa el secreto
whsec_correcto y lee los headerswebhook-id/webhook-timestamp/webhook-signaturetal cual. - Eventos duplicados: deduplica usando
webhook-id. - Eventos perdidos: asegúrate de que tu endpoint devuelva
2xxrápido; las respuestasnon-2xxy los timeouts se reintentan, pero las fallas persistentes pueden deshabilitar la entrega. - Errores de SSL: tu endpoint necesita un certificado TLS válido.
webhook-id.