Avistadocs
Integration Guides

MED Integration

Overview

This guide shows how to integrate the MED flow into your application. You will learn how to:

  1. Configure webhooks to receive MED notifications
  2. Query the list of MEDs in your account
  3. 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}), 200
┌─────────────────────────────────────────────────────────────┐
│                   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.

Next Steps

On this page