Webhooks
Endpoints para recibir eventos en tiempo real de Manteca y Bridge.
1. Webhook de Manteca
POST /webhook
Endpoint para recibir eventos de webhook de Manteca.
Headers:
Content-Type: application/json
X-Manteca-Signature: <signature>
Body (Ejemplo - Validación de Documento):
{
"event": "DOCUMENT_VALIDATION",
"data": {
"numberId": "12345",
"userExternalId": "swp_98808656",
"document": "DNI_FRONT",
"validated": true,
"comment": "Documento válido",
"date": "2024-01-15T10:30:00Z",
"newLimit": 50000,
"newLimitMonth": 10000
}
}
Respuesta Exitosa (200):
{
"success": true,
"message": "Evento procesado exitosamente"
}
Respuesta de Error (200):
{
"success": false,
"message": "Error al procesar evento",
"error": "Error message"
}
2. Webhook de Bridge
POST /bridge/webhook
Endpoint para recibir eventos de webhook de Bridge.
Headers:
Content-Type: application/json
X-Bridge-Signature: <signature>
X-Bridge-Timestamp: <timestamp>
Body (Ejemplo - Customer Actualizado):
{
"event_category": "customer",
"event_type": "customer.updated",
"event_object_id": "bridge_customer_123",
"event_object": {
"id": "bridge_customer_123",
"status": "active",
"email": "user@example.com"
}
}
Respuesta Exitosa (200):
{
"success": true,
"message": "Evento procesado exitosamente"
}
🔔 Eventos de Manteca
DOCUMENT_VALIDATION
Notifica cambios en el estado de validación de documentos KYC.
{
"event": "DOCUMENT_VALIDATION",
"data": {
"numberId": "12345",
"userExternalId": "swp_98808656",
"document": "DNI_FRONT",
"validated": true,
"comment": "Documento válido",
"date": "2024-01-15T10:30:00Z",
"newLimit": 50000,
"newLimitMonth": 10000
}
}
ORDER_COMPLETED
Notifica cuando una orden se completa exitosamente.
{
"event": "ORDER_COMPLETED",
"data": {
"numberId": "67890",
"userExternalId": "swp_98808656",
"coin": "DAI_ARS",
"operation": "BUY",
"amount": "100.00",
"price": "1250.75",
"fee": "2.50",
"completedAt": "2024-01-15T10:35:00Z"
}
}
FIAT_DEPOSIT
Notifica depósitos fiat recibidos.
{
"event": "FIAT_DEPOSIT",
"data": {
"depositId": "dep_123",
"userExternalId": "swp_98808656",
"amount": "5000.00",
"currency": "ARS",
"status": "COMPLETED",
"reference": "DEP20240115001",
"completedAt": "2024-01-15T11:00:00Z"
}
}
🔵 Eventos de Bridge
customer.created
Customer creado exitosamente.
{
"event_category": "customer",
"event_type": "customer.created",
"event_object_id": "bridge_customer_123",
"event_object": {
"id": "bridge_customer_123",
"status": "pending",
"email": "user@example.com",
"first_name": "Juan",
"last_name": "Pérez",
"created_at": "2024-01-15T10:30:00Z"
}
}
customer.verified
Customer verificado tras completar KYC.
{
"event_category": "customer",
"event_type": "customer.verified",
"event_object_id": "bridge_customer_123",
"event_object": {
"id": "bridge_customer_123",
"status": "active",
"kyc_status": "verified",
"verified_at": "2024-01-15T12:00:00Z"
}
}
virtual_account.credited
Fondos recibidos en cuenta virtual.
{
"event_category": "virtual_account",
"event_type": "virtual_account.credited",
"event_object_id": "va_123456",
"event_object": {
"id": "va_123456",
"amount": "1000.00",
"currency": "usd",
"transaction_id": "tx_789",
"credited_at": "2024-01-15T14:30:00Z"
}
}
🔒 Verificación de Seguridad
Manteca Signature
const crypto = require('crypto');
function verifyMantecaWebhook(payload, signature, secret) {
const computedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === computedSignature;
}
Bridge Signature
function verifyBridgeWebhook(payload, signature, timestamp, secret) {
const signedPayload = `${timestamp}.${payload}`;
const computedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return signature === `sha256=${computedSignature}`;
}
🔄 Manejo de Errores
Reintentos
- Manteca: 3 intentos con backoff exponencial
- Bridge: 5 intentos con backoff exponencial
- Timeout: 30 segundos por intento
Estados de Respuesta
// Éxito - No se reintenta
return res.status(200).json({ success: true });
// Error temporal - Se reintenta
return res.status(500).json({ error: "Database unavailable" });
// Error permanente - No se reintenta
return res.status(400).json({ error: "Invalid payload format" });
📊 Logging y Monitoreo
Log Structure
{
"timestamp": "2024-01-15T10:30:00Z",
"webhook_type": "manteca",
"event": "DOCUMENT_VALIDATION",
"user_id": "swp_98808656",
"processing_time_ms": 150,
"status": "success",
"ip_address": "192.168.1.1"
}
Métricas
- Latencia promedio: < 200ms
- Tasa de éxito: > 99%
- Tiempo de procesamiento: < 5s
- Reintentos: < 1% de eventos
🛠️ Testing
Webhook Testing Tool
// Simular webhook de Manteca
const mockMantecaWebhook = {
event: "DOCUMENT_VALIDATION",
data: {
numberId: "test_123",
userExternalId: "test_user",
document: "DNI_FRONT",
validated: true
}
};
// Enviar a endpoint local
fetch('http://localhost:3000/webhook', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(mockMantecaWebhook)
});
⚠️ Errores Comunes
Webhook Failures
- Invalid Signature: Verificar secreto y algoritmo
- Timeout: Optimizar procesamiento de eventos
- Duplicate Events: Implementar idempotencia
- Missing Headers: Validar headers requeridos
Debugging Checklist
- ✅ Validar formato de payload
- ✅ Verificar signature del webhook
- ✅ Comprobar conectividad de base de datos
- ✅ Revisar logs de errores
- ✅ Validar respuesta HTTP
📝 Notas Importantes
- Idempotencia: Manejar eventos duplicados con IDs únicos
- Timeouts: Responder en < 30 segundos para evitar reintentos
- Seguridad: Siempre validar signatures
- Logs: Registrar todos los eventos para auditoría
- Monitoreo: Alertas para fallos de webhook > 5%