Vas a lograr recibir un evento por webhook, verificar que lo mandó Mozart y responder correctamente para que no se reintente de más.

Cómo se da de alta

Los webhooks no se autogestionan: se dan de alta desde el panel de administración interno de Mozart, a pedido de tu organización. Pedile a tu contacto en Mozart que registre tu URL y los eventos que querés recibir — queda registrado bajo Organización → Webhooks del cliente correspondiente. La URL tiene que ser https://; Mozart no entrega eventos a endpoints http://.
El secret de firma se muestra una sola vez, en el momento en que se da de alta la suscripción. Mozart no puede volver a mostrártelo después: si lo perdés, hay que dar de baja la suscripción y crear una nueva.
El secret tiene el formato whsec_<43 caracteres>. Lo vas a necesitar para verificar la firma de cada evento (ver abajo).

Eventos disponibles

Los pagos que llegan dentro de un archivo de carga de cartera (por la plataforma o por el flujo de Carga de cartera de la API) no generan payment.registered: son una carga masiva de histórico, no un pago puntual. Sólo los pagos registrados individualmente —por POST /v1/payments, desde el panel, por un link de cobro, o al marcar una promesa de pago como cumplida— disparan el evento.

Forma del evento

Cada entrega es un POST a tu URL con este body:
data tiene exactamente la misma forma que el recurso equivalente en la API pública: un payment.registered trae el mismo objeto que devuelve GET /v1/payments/:id, un promise.created el mismo que lista GET /v1/promises, y un call.completed el mismo que GET /v1/calls (sin el bloque analysis, que sólo trae el detalle por id). id identifica la entrega — usalo para idempotencia (ver abajo) —, no la confundas con el id del recurso dentro de data.

Verificar la firma

Cada entrega trae dos headers:
X-Mozart-Signature tiene dos partes separadas por coma: t es un timestamp Unix (segundos) y v1 es un HMAC-SHA256 en hexadecimal, calculado sobre el string "<t>.<body crudo>" con tu secret (whsec_...).
1

Recuperá el body crudo

Calculá la firma sobre los bytes exactos que llegaron, antes de parsear el JSON — cualquier framework que reformatee el body (indentación, orden de claves) invalida la comparación.
2

Recalculá el HMAC

Con tu secret, sobre "<t>." + body, y comparalo contra v1 en tiempo constante (nunca con ===/==, que corta apenas encuentra la primera diferencia y filtra información por temporización).
3

Chequeá la tolerancia de reloj

Rechazá la entrega si t está a más de ~5 minutos del momento actual — protege contra un replay de una entrega vieja capturada por un tercero.

Reintentos e idempotencia

Una entrega se considera exitosa con cualquier respuesta 2xx. Cualquier otra cosa —un error, un timeout— cuenta como fallo:
  • Cada intento tiene un timeout de 10 segundos.
  • Mozart reintenta hasta 5 veces en total. Después del quinto intento fallido, la entrega se da por perdida (queda en una cola de mensajes fallidos para diagnóstico interno, no se vuelve a reintentar).
  • Un reintento manda el mismo id de entrega. Usalo para no procesar dos veces el mismo evento si tu endpoint llega a recibirlo más de una vez.
Respondé 2xx apenas confirmes que recibiste el request, y procesá el evento aparte (una cola propia, un job en segundo plano). Si tu procesamiento tarda más de 10 segundos, Mozart lo va a contar como fallo y reintentar, aunque tu lado ya lo haya procesado.

Siguiente paso

Con webhooks cubiertos, revisá Paginación, errores y límites si todavía no lo hiciste, o volvé a Pagos y Carga de cartera para el resto de la escritura.