Esta página cubre todos los eventos de webhook, que abarcan múltiples áreas de la plataforma (actividad de transacciones, depósitos, flujos del widget y vinculación de cuentas con OAuth) en lugar de pertenecer a una sola función.
Cómo funciona
- Registras una URL de webhook en tu aplicación en el Developer Portal.
- Seleccionas qué tipos de evento quieres escuchar (o te suscribes a todos).
- Cuando ocurre un evento que coincide, Fluz envía un
POSTHTTP a tu URL con un payload JSON firmado. - Tu servidor verifica la firma, responde con un
2xxy procesa el evento.
Webhooks por tipo de app
Cómo se enrutan los eventos a tu app depende de tu modelo de aplicación.Apps privadas — tu propia cuenta
Los webhooks se disparan por actividad en tu propia cuenta. Cualquier transacción, rechazo o depósito en cuentas que posees activa los webhooks registrados en tu app. Casos de uso comunes: notificaciones cuando se autoriza o liquida una transacción con tarjeta virtual; alertas en tiempo real sobre rechazos; monitoreo de depósitos y cambios de saldo en tus cuentas de gasto.Apps públicas (OAuth) — actuando en nombre de usuarios
Los webhooks se disparan por actividad en cuentas que han autorizado tu app. Cuando un usuario otorga acceso a tu app mediante OAuth, sus eventos se enrutan a tus webhooks registrados, siempre que la concesión OAuth del usuario incluya los scopes requeridos. Esto funciona tanto si el usuario interactúa mediante tu integración directa con la API como a través de un widget embebido; el requisito clave es una relación OAuth entre el usuario y tu app. Casos de uso comunes: saber cuándo un usuario vinculó (o revinculó) su cuenta a tu app; monitoreo del gasto con tarjetas virtuales en cuentas conectadas; notificaciones de rechazos en tiempo real; seguimiento de depósitos completados; recepción de actualizaciones de estado KYC.Apps de widget
Las apps de widget son una app pública especializada. Los eventos se enrutan del mismo modo (basados en la relación OAuth), y además las apps de widget admiten eventos específicos del widget como finalización de transferencias y compras de tarjetas de regalo.Tipos de eventos
Fluz solo entrega un evento si tu aplicación — y, para apps públicas/OAuth, la concesión OAuth del usuario individual — posee los scopes requeridos. Los eventos sin scopes requeridos (comoOAUTH_USER_LINKED) se entregan a cualquier app pública/OAuth suscrita.
Eventos de transacción
Cubren todo el ciclo de vida de la transacción. Aplican a todos los tipos de app.Eventos de depósito
Eventos de OAuth
Aplican a apps públicas/OAuth y de widget.OAUTH_USER_LINKED se entrega solo a tipos de app públicas/OAuth — los suscriptores de apps privadas no lo reciben. Como no tiene requisito de scope, lo recibes para cada usuario que vincule o revincule su cuenta con tu app, sin importar qué scopes otorguen. Úsalo para aprovisionar o actualizar tu registro local del usuario conectado, capturar el conjunto de scopes otorgados y mapear tu propio identificador de usuario mediante externalReferenceId.
Eventos específicos de widget
Aplican a integraciones de widget y OAuth donde los usuarios interactúan mediante flujos embebidos de Fluz.📘 Nota sobre la nomenclatura:WIDGET_DEPOSIT_COMPLETEyWIDGET_WITHDRAW_COMPLETEdescriben transferencias cliente↔app; la redacciónDEPOSIT/WITHDRAWes histórica. Trata “depósito” como “cliente → app” y “retiro” como “app → cliente”.
Configurar webhooks
1. Abre el Developer Portal
Ve al Developer Portal y selecciona tu aplicación.2. Abre la sección de Webhooks
- Apps OAuth: pestaña OAuth → Webhook URLs.
- Apps de widget: pestaña Widget → Webhook URLs.
- Apps API / privadas: la sección Webhook URLs en la configuración de tu app.
3. Agrega una URL de webhook
Haz clic en Add new URL e ingresa tu endpoint HTTPS (p. ej.,https://api.yourapp.com/webhooks/fluz).
4. Selecciona eventos
Elige los tipos de eventos que quieres recibir.5. Guarda
Haz clic en Create Webhook. Tu endpoint comienza a recibir eventos de inmediato.Administrar webhooks
- Múltiples endpoints: puedes registrar más de una URL de webhook por aplicación.
- Cambiar eventos suscritos: elimina el webhook y créalo de nuevo con la nueva selección de eventos.
- Eliminar un webhook: haz clic en Remove junto a él. El webhook se archiva de inmediato y deja de recibir eventos.
Recibir webhooks
Formato de la solicitud
Cada webhook se entrega como unPOST HTTP con estos encabezados:
El cuerpo es un objeto JSON, y cada payload incluye un campo
eventType que identifica el evento.
Requisitos del endpoint
- Solo HTTPS — endpoints HTTP en claro se rechazan al registrarlos.
- Públicamente accesible y capaz de aceptar solicitudes
POST. - Responder con un
2xxdentro de 30 segundos. Respuestas que no sean2xxo timeouts activan reintentos. - Verificar la firma HMAC en cada solicitud.
Verificación de firmas
Cada entrega incluye un encabezadoX-HMAC-Signature, un hash HMAC-SHA256 del cuerpo JSON crudo, firmado con la clave API de tu aplicación. Verifícalo siempre antes de confiar en un payload.
⚠️ Verifica contra el cuerpo crudo de la solicitud. Calcula el HMAC sobre los bytes exactos que envió Fluz — no vuelvas a serializar el JSON parseado. Re-serializar puede reordenar claves o cambiar espacios en blanco y hacer que fallen firmas válidas. Los ejemplos a continuación capturan el cuerpo crudo por esta razón.
Node.js (Express)
Python (Flask)
Responder a webhooks
Tu endpoint debe:- Responder con un estado
2xxdentro de 30 segundos. - Responder rápido — reconoce primero y luego procesa de forma asíncrona.
- Ser accesible por HTTPS. Tu endpoint no debe:
- Responder con redirecciones (
3xx). - Responder con
4xx/5xxpara webhooks válidos (esto activa reintentos).
Política de reintentos
Los nuevos eventos reanudan la entrega automáticamente una vez que tu endpoint se recupere. Para reenviar eventos cuyos reintentos ya se agotaron, contacta al soporte con el
X-Event-ID correspondiente.
Idempotencia y orden
Los webhooks pueden entregarse más de una vez, y no se garantiza el orden de entrega.- Desduplica usando el encabezado
X-Event-ID. Conserva los IDs procesados (Redis o una base de datos en producción) y omite eventos que ya hayas manejado. - Ordena por los datos, no por la llegada. Si la secuencia importa, ordena por las marcas de tiempo del payload (
createdAt,updatedAt,transactionDateTime) y los IDs de evento.
Identificar la app y el usuario
- Usuario:
userIdes el ID de usuario de Fluz. Para eventos de OAuth/widget,externalReferenceIdse asigna a tu identificador de usuario desde el flujo OAuth. - App: los payloads de transacción incluyen
connectedAppIdyconnectedAppName. Si enrutas varias apps a un endpoint, bifurca segúnconnectedAppId. ParaOAUTH_USER_LINKED, la app se identifica conappId.
Referencia de payloads
Cada payload incluye uneventType. La disponibilidad de campos puede variar según el evento; los handlers deben ignorar campos no reconocidos para mantener compatibilidad futura.
📘 Una nota sobre los valores destatus. Para transacciones creadas/actualizadas el campostatustoma uno dePENDING,SETTLEDoFAILED. Las transacciones rechazadas llevan unstatusdeDECLINED(oFAILED). Versiones anteriores de esta página mostrabanCOMPLETEDcomo estado — ese valor no se emite; usaSETTLEDpara detectar una transacción finalizada.
Transacción creada (TRANSACTION_CREATE)
Se dispara para cualquier transacción nueva — compras con tarjeta virtual, depósitos, transferencias y más.
Transacción actualizada (TRANSACTION_UPDATE)
Se dispara cuando cambian el estado o los detalles de una transacción — por ejemplo, cuando una autorización pendiente se liquida.
TRANSACTION_CREATE donde están presentes, más updatedAt (ISO 8601) que marca cuándo ocurrió el cambio. userId, connectedAppId y connectedAppName se mantienen de la misma forma que en TRANSACTION_CREATE, para que puedas identificar al usuario y la app de forma consistente a lo largo del ciclo de vida. Una transición de status a SETTLED es la señal de que una transacción previamente pendiente se ha finalizado.
Transacción rechazada (TRANSACTION_DECLINE)
Se dispara cuando se rechaza una transacción. Incluye motivos de rechazo estructurados con los que tu app puede actuar.
Pueden estar presentes campos opcionales adicionales según la transacción (p. ej.,
merchantId, merchantCity, merchantState, merchantCountry, cardDisplayName, virtualCardProgram, channel, bankAccountNickname, bankAccountLastFour). Ignora los que no uses.
Depósito completado (DEPOSIT_COMPLETE)
Se dispara cuando se completa un depósito desde una fuente de fondos a una cuenta de gasto.
Usuario OAuth vinculado (OAUTH_USER_LINKED)
Se dispara cuando un usuario completa la vinculación OAuth con tu aplicación — tanto en el enlace inicial como en actualizaciones posteriores (por ejemplo, cuando el usuario vuelve a autorizar con un conjunto de scopes diferente). Solo apps públicas/OAuth y de widget. No se requiere ningún scope para recibir este evento.
Dado que
OAUTH_USER_LINKED se dispara nuevamente en revinculaciones/actualizaciones, trátalo como un upsert: crea al usuario conectado en la primera recepción y actualiza el conjunto de scopes almacenado en entregas posteriores.
Inicio de KYC (WIDGET_KYC_INITIATION)
Se dispara cuando un usuario inicia la verificación de identidad. Solo apps públicas/widget.
Transferencia completada — cliente a app (WIDGET_DEPOSIT_COMPLETE)
Se dispara cuando un usuario transfiere fondos a tu aplicación.
Transferencia completada — app a cliente (WIDGET_WITHDRAW_COMPLETE)
Se dispara cuando tu aplicación transfiere fondos a un usuario.
Compra de tarjeta de regalo (WIDGET_PURCHASE_GIFT_CARD)
Se dispara cuando se completa una compra de tarjeta de regalo mediante el widget.
userId (ID de usuario de Fluz), accountId (ID de cuenta de Fluz), externalReferenceId (tu identificador de usuario del flujo OAuth) y amount cuando aplique.
Mejores prácticas
- Responde rápido, procesa después. Devuelve
200de inmediato y maneja el evento de forma asíncrona para evitar timeouts y reintentos innecesarios. - Verifica cada solicitud. Valida
X-HMAC-Signaturecontra el cuerpo crudo usando tu clave API antes de procesar. - Desduplica con IDs de evento. Rastrea
X-Event-IDpara manejar entregas reintentadas/duplicadas. - Trata los campos tipo enum como cadenas abiertas. Con el tiempo pueden aparecer nuevos valores de
transactionType,channelydeclineCategory; ramifica según los valores que te interesen y tolera los desconocidos. - Haz upsert en
OAUTH_USER_LINKED. Puede dispararse más de una vez por usuario; actualiza el conjunto de scopes almacenado cada vez en lugar de asumir semántica de solo primer enlace. - Acepta campos desconocidos. Los payloads pueden ganar campos con el tiempo; ignora los no reconocidos en lugar de fallar.
- Monitorea tu endpoint. Genera alertas ante respuestas repetidas que no sean
2xx— después de 5 intentos fallidos se abandona la entrega de un evento.
Solución de problemas
¿Necesitas ayuda?
- Problemas técnicos: revisa los registros de tu endpoint y contacta soporte con el
X-Event-ID. - Preguntas sobre scopes: consulta Scopes de la aplicación y Códigos de rechazo.