Mono Colombia
Estándares de API

Webhooks

Convenciones de webhooks entre productos para la API de Mono.

Un webhook es una notificación automática que Mono envía a tu sistema en el momento en que algo ocurre — una transferencia se aprueba, una tarjeta se carga, un recaudo se acredita. En vez de preguntarle a Mono repetidamente si algo cambió, tu servidor recibe una sola solicitud HTTPS apenas ocurre el evento.

Estas convenciones aplican a cada producto de Mono: Banking, Core y Bre-B Participant. Cada producto tiene su propio catálogo de eventos; esta página documenta la mecánica compartida que los rige a todos.

Antes de empezar

Vas a necesitar:

  • Un endpoint HTTPS accesible públicamente (no localhost, no 127.0.0.1).
  • La capacidad de verificar una firma HMAC-SHA256 en cada solicitud entrante.
  • Un handler de eventos idempotente — Mono reintenta en fallas, así que el mismo evento puede llegar más de una vez.

Envelope

Cada cuerpo de solicitud de webhook sigue el mismo envelope JSON:

{
  "event": {
    "data": { ... },
    "type": "event_type_or_name"
  },
  "timestamp": "2022-12-29T15:42:08.325158Z"
}
  • event.type — el nombre estable del evento (p. ej. bank_transfer_approved).
  • event.data — el payload del evento; su esquema depende del tipo de evento.
  • timestamp — timestamp ISO 8601 UTC de cuándo se generó el evento.

Firma

Cada solicitud está firmada con un webhook secret que obtienes desde el Dashboard. La firma y el timestamp viajan juntos en un header personalizado llamado Mono-Signature:

Mono-Signature: t=1672328528,v1=662255ca79c4b21914894d32da10189a1482cd0fee56b2765a8b472662ce55ac
  • t — timestamp Unix. Úsalo para protegerte contra ataques de repetición rechazando solicitudes cuyo timestamp caiga fuera de tu ventana de tolerancia.
  • v1 — la firma HMAC-SHA256. Mono actualmente solo usa la versión v1.

Verificación de firma

Paso 1: extraer timestamp y firma

Divide Mono-Signature por , para obtener:

t=1672328528
v1=662255ca79c4b21914894d32da10189a1482cd0fee56b2765a8b472662ce55ac

Paso 2: construir el string del payload firmado

Concatena el timestamp, un . literal, y el cuerpo crudo de la solicitud:

<timestamp>.<payload_rawbody>

Paso 3: calcular la firma esperada

Usa HMAC-SHA256 con tu webhook secret como llave y el string del payload firmado como mensaje:

require 'openssl'

timestamp = 1672774221
raw_payload = '{"respose_body": "example"}'

signed_payload = "#{timestamp}.#{raw_payload}"
secret = "whsec_example"

hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, signed_payload)
# => 652fdc1742906b4b23ce2a5f4ac417b52c264fea0207920a5e76330a87239924

Paso 4: comparar y validar

Compara el HMAC calculado contra el valor v1 usando una comparación de tiempo constante para prevenir ataques de temporización. Luego verifica que la diferencia entre el tiempo actual y t esté dentro de tu ventana aceptable (típicamente 5 minutos).

Política de reintentos

Mono reintenta solicitudes fallidas (cualquier respuesta que no sea 2xx) hasta diez veces con backoff exponencial. Tras el décimo intento, el evento no se reintenta más.

IntentoDelay desde el anterior
1inmediato
230 segundos
31.5 minutos
43.5 minutos
57.5 minutos
615.5 minutos
731.5 minutos
81.06 horas
92.13 horas
104.26 horas

Los diez intentos se completan en aproximadamente 8.4 horas.

Campos de dinero

Los montos monetarios siempre se representan en la unidad menor de la moneda (centavos para COP y USD):

  • 240000 = 2,400.00
  • 160 = 1.60

La excepción es fx_rates, que lleva la tasa de cambio decimal directamente: "4002.24" = 4002.24.

Restricciones de URL

Tu endpoint de webhook debe:

  • Empezar con http o https.
  • No usar localhost ni 127.0.0.1 como host.
  • Ser una URL HTTP/HTTPS válida y alcanzable.

Siguientes pasos

En esta página