Skip to main content
Los webhooks permiten que tu aplicación reciba notificaciones en tiempo real cuando ocurren eventos en la plataforma de Fluz. En lugar de hacer polling para detectar cambios, registras un endpoint HTTPS y Fluz envía los datos del evento en el momento en que sucede algo: una transacción con tarjeta virtual, una compra rechazada, un depósito completado, un usuario que vincula su cuenta mediante OAuth, y más.
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.
Los webhooks funcionan en todos los tipos de aplicaciones de la plataforma Fluz: apps privadas que operan en tu propia cuenta, apps públicas OAuth que actúan en nombre de otros usuarios vía API, y apps de widget embebido.

Cómo funciona

  1. Registras una URL de webhook en tu aplicación en el Developer Portal.
  2. Seleccionas qué tipos de evento quieres escuchar (o te suscribes a todos).
  3. Cuando ocurre un evento que coincide, Fluz envía un POST HTTP a tu URL con un payload JSON firmado.
  4. Tu servidor verifica la firma, responde con un 2xx y procesa el evento.
Si tu endpoint no está disponible o devuelve un error, Fluz reintenta hasta 5 veces con backoff exponencial antes de abandonar esa entrega.

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 (como OAUTH_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_COMPLETE y WIDGET_WITHDRAW_COMPLETE describen transferencias cliente↔app; la redacción DEPOSIT/WITHDRAW es 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 OAuthWebhook URLs.
  • Apps de widget: pestaña WidgetWebhook 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 un POST 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 2xx dentro de 30 segundos. Respuestas que no sean 2xx o timeouts activan reintentos.
  • Verificar la firma HMAC en cada solicitud.

Verificación de firmas

Cada entrega incluye un encabezado X-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 2xx dentro 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/5xx para 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: userId es el ID de usuario de Fluz. Para eventos de OAuth/widget, externalReferenceId se asigna a tu identificador de usuario desde el flujo OAuth.
  • App: los payloads de transacción incluyen connectedAppId y connectedAppName. Si enrutas varias apps a un endpoint, bifurca según connectedAppId. Para OAUTH_USER_LINKED, la app se identifica con appId.

Referencia de payloads

Cada payload incluye un eventType. 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 de status. Para transacciones creadas/actualizadas el campo status toma uno de PENDING, SETTLED o FAILED. Las transacciones rechazadas llevan un status de DECLINED (o FAILED). Versiones anteriores de esta página mostraban COMPLETED como estado — ese valor no se emite; usa SETTLED para 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.
Los campos coinciden con 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.
Campos comunes de payload del 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 200 de inmediato y maneja el evento de forma asíncrona para evitar timeouts y reintentos innecesarios.
  • Verifica cada solicitud. Valida X-HMAC-Signature contra el cuerpo crudo usando tu clave API antes de procesar.
  • Desduplica con IDs de evento. Rastrea X-Event-ID para manejar entregas reintentadas/duplicadas.
  • Trata los campos tipo enum como cadenas abiertas. Con el tiempo pueden aparecer nuevos valores de transactionType, channel y declineCategory; 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?