MED Integration
Overview
This guide shows how to integrate the MED flow into your application. You will learn how to:
- Configure webhooks to receive MED notifications
- Query the list of MEDs in your account
- Handle each event type (creation, approval, rejection)
Before starting, read the MED overview to understand the lifecycle and concepts involved.
1. Configure MED webhooks
Configure an endpoint for each MED event type you want to receive. Use POST /api/webhooks:
Notification of a new MED received against your account.
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.yourcompany.com/webhooks/med-created",
"eventType": "med_created",
"headers": [
{ "key": "Authorization", "value": "Bearer your-secret-token" }
]
}'Notification of an approved MED (refund accepted — amount will be returned to payer).
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.yourcompany.com/webhooks/med-accepted",
"eventType": "med_accepted"
}'Notification of a rejected MED (refund denied — balance remains with beneficiary).
curl -X POST https://api.avista.global/api/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.yourcompany.com/webhooks/med-rejected",
"eventType": "med_rejected"
}'We recommend configuring all three webhook types (med_created, med_accepted, med_rejected) for full visibility of the MED lifecycle.
2. Query MEDs
Use GET /api/med to list MEDs in your account with filters and pagination.
List all MEDs
curl -X GET "https://api.avista.global/api/med" \
-H "Authorization: Bearer $TOKEN"Filter by status
curl -X GET "https://api.avista.global/api/med?status=RECEIVED" \
-H "Authorization: Bearer $TOKEN"Filter by period
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"Example response
{
"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
}
}The isReconciled field indicates whether the MED was automatically linked to a local transaction in your account. When true, originalTransactionId contains the ID of the original PIX transaction.
3. Handle MED webhooks
Example 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':
// New MED received — notify team and/or block beneficiary operations
await notifyTeam({
message: `MED #${medId} received — cause: ${cause}`,
amount: originalTransaction?.amount,
endToEndId: originalTransaction?.endToEndId,
});
break;
case 'MedAccepted':
// Refund approved — amount will be returned to payer
await updateTransaction({
medId,
status: 'REFUNDED',
note: 'MED approved — amount returned to original payer',
});
break;
case 'MedRejected':
// Refund rejected — balance remains with beneficiary
await updateTransaction({
medId,
status: 'KEPT',
note: 'MED rejected — balance unblocked',
});
break;
}
// Always return 200 to confirm receipt
res.status(200).json({ received: true });
});Example 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':
# New MED — alert team
notify_team(med_id, cause, data.get('originalTransaction'))
elif event == 'MedAccepted':
# Refund approved
update_transaction(med_id, 'REFUNDED')
elif event == 'MedRejected':
# Refund rejected
update_transaction(med_id, 'KEPT')
return jsonify({'received': True}), 2004. Recommended flow
┌─────────────────────────────────────────────────────────────┐
│ YOUR APPLICATION │
│ │
│ MedCreated webhook ──────▶ Alert risk team │
│ │ Mark transaction as "under MED" │
│ │ (Optional) Block beneficiary │
│ │ │
│ ▼ │
│ Query GET /api/med ──────▶ Check details and cause │
│ │ Track status │
│ │ │
│ ▼ │
│ MedAccepted webhook ─────▶ Record refund │
│ OR Update customer balance │
│ MedRejected webhook ─────▶ Unblock beneficiary │
│ Keep balance │
└─────────────────────────────────────────────────────────────┘Best Practices
Configure all 3 webhooks
Always configure med_created, med_accepted, and med_rejected for full lifecycle visibility.
Return 200 quickly
Process webhooks asynchronously. If the handler takes more than 5 seconds, the system will retry delivery.
Use idempotency
Use medId as the idempotency key. The same webhook may be redelivered on failure.
Monitor open MEDs
Periodically query GET /api/med?status=RECEIVED to ensure no MED is left unattended.