Integración MED
Visión General
Esta guía muestra cómo integrar el flujo MED en su aplicación. Aprenderá a:
- Configurar webhooks para recibir notificaciones de MED
- Consultar la lista de MEDs de su cuenta
- Manejar cada tipo de evento (creación, aprobación, rechazo)
Antes de comenzar, lea la visión general del MED para entender el ciclo de vida y los conceptos involucrados.
1. Configurar los webhooks de MED
Configure un endpoint para cada tipo de evento MED que desee recibir. Use POST /api/webhooks:
Notificación de un nuevo MED recibido contra su cuenta.
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.suempresa.com/webhooks/med-created",
"eventType": "med_created",
"headers": [
{ "key": "Authorization", "value": "Bearer your-secret-token" }
]
}'Notificación de un MED aprobado (devolución aceptada — el monto será devuelto al pagador).
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.suempresa.com/webhooks/med-accepted",
"eventType": "med_accepted"
}'Notificación de un MED rechazado (devolución negada — el saldo permanece con el beneficiario).
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.suempresa.com/webhooks/med-rejected",
"eventType": "med_rejected"
}'Recomendamos configurar los tres tipos de webhook (med_created, med_accepted, med_rejected) para tener visibilidad completa del ciclo de vida del MED.
2. Consultar MEDs
Use GET /api/med para listar los MEDs de su cuenta con filtros y paginación.
Listar todos los MEDs
curl -X GET "https://api.avista.global/api/med" \
-H "Authorization: Bearer $TOKEN"Filtrar por estado
curl -X GET "https://api.avista.global/api/med?status=RECEIVED" \
-H "Authorization: Bearer $TOKEN"Filtrar por período
curl -X GET "https://api.avista.global/api/med?startDate=2026-01-01T00:00:00.000Z&endDate=2026-01-31T23:59:59.999Z&page=1&pageSize=50" \
-H "Authorization: Bearer $TOKEN"Ejemplo de respuesta
{
"data": [
{
"id": 42,
"endToEnd": "E12345678202604101030abcdef123456",
"status": "RECEIVED",
"reason": "REFUND_REQUEST",
"cause": "UNAUTHORIZED_TRANSACTION",
"description": "Customer claims not to have performed the transaction",
"analysisResult": null,
"analysisDetails": null,
"requestingBank": {
"ispb": "00000000",
"name": "BCO DO BRASIL S.A."
},
"contestedBank": {
"ispb": "13140088",
"name": "ACESSO SOLUÇÕES DE PAGAMENTO"
},
"originalTransaction": {
"amount": 1500.00,
"type": "PIX",
"transactionType": "CASH_IN",
"name": "João da Silva",
"document": "***456789**",
"dateTime": "2026-04-05T14:30:00.000Z"
},
"isReconciled": true,
"originalTransactionId": 78432,
"createdAt": "2026-04-10T10:00:00.000Z",
"updatedAt": "2026-04-10T10:00:00.000Z"
}
],
"metadata": {
"total": 1,
"page": 1,
"pageSize": 20,
"totalPages": 1
}
}El campo isReconciled indica si el MED fue vinculado automáticamente a una transacción local de su cuenta. Cuando es true, originalTransactionId contiene el ID de la transacción PIX original.
3. Manejar los webhooks de MED
Ejemplo de handler (Node.js)
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhooks/med', async (req, res) => {
const { event, medId, status, cause, originalTransaction } = req.body;
console.log(`MED ${medId}: ${event} (status: ${status})`);
switch (event) {
case 'MedCreated':
// Nuevo MED recibido — notificar al equipo y/o bloquear operaciones del beneficiario
await notifyTeam({
message: `MED #${medId} recibido — causa: ${cause}`,
amount: originalTransaction?.amount,
endToEndId: originalTransaction?.endToEndId,
});
break;
case 'MedAccepted':
// Devolución aprobada — el monto será devuelto al pagador
await updateTransaction({
medId,
status: 'REFUNDED',
note: 'MED aprobado — monto devuelto al pagador original',
});
break;
case 'MedRejected':
// Devolución rechazada — el saldo permanece con el beneficiario
await updateTransaction({
medId,
status: 'KEPT',
note: 'MED rechazado — saldo desbloqueado',
});
break;
}
// Siempre devuelva 200 para confirmar la recepción
res.status(200).json({ received: true });
});Ejemplo de handler (Python)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/med', methods=['POST'])
def handle_med_webhook():
data = request.json
event = data.get('event')
med_id = data.get('medId')
cause = data.get('cause')
print(f"MED {med_id}: {event} (cause: {cause})")
if event == 'MedCreated':
# Nuevo MED — alertar al equipo
notify_team(med_id, cause, data.get('originalTransaction'))
elif event == 'MedAccepted':
# Devolución aprobada
update_transaction(med_id, 'REFUNDED')
elif event == 'MedRejected':
# Devolución rechazada
update_transaction(med_id, 'KEPT')
return jsonify({'received': True}), 2004. Flujo recomendado
┌─────────────────────────────────────────────────────────────┐
│ SU APLICACIÓN │
│ │
│ Webhook MedCreated ──────▶ Alertar al equipo de riesgo │
│ │ Marcar transacción como │
│ │ "bajo MED" │
│ │ (Opcional) Bloquear beneficiario│
│ │ │
│ ▼ │
│ Consultar GET /api/med ──▶ Verificar detalles y causa │
│ │ Acompañar el estado │
│ │ │
│ ▼ │
│ Webhook MedAccepted ─────▶ Registrar devolución │
│ O Actualizar saldo del cliente │
│ Webhook MedRejected ─────▶ Desbloquear al beneficiario │
│ Mantener el saldo │
└─────────────────────────────────────────────────────────────┘Mejores Prácticas
Configure los 3 webhooks
Configure siempre med_created, med_accepted y med_rejected para tener visibilidad completa del ciclo de vida.
Devuelva 200 rápidamente
Procese los webhooks de forma asíncrona. Si el handler tarda más de 5 segundos, el sistema reintentará la entrega.
Use idempotencia
Utilice medId como clave de idempotencia. El mismo webhook puede ser reenviado en caso de falla.
Monitoree MEDs abiertos
Consulte periódicamente GET /api/med?status=RECEIVED para garantizar que ningún MED quede desatendido.