docs
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

Register an endpoint for each MED event type you want to receive in the dashboard https://banking.fypay.me, under Settings → Webhooks. The URL must be HTTPS; each event accepts up to 3 URLs and up to 5 custom headers. See the step-by-step in Configure Webhooks.

EventDescription
med_createdNotification of a new MED received against your account.
med_acceptedNotification of an approved MED (refund accepted — amount will be returned to payer).
med_rejectedNotification of a rejected MED (refund denied — balance remains with beneficiary).

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.

ParameterTypeDescription
statusstringOPEN, RECEIVED, CANCELLED, or ANALYZED (CANCELED is also accepted)
isReconciledbooleantrue for MEDs linked to a transaction in your account
startDatestringStart date (ISO 8601)
endDatestringEnd date (ISO 8601)
pageintegerPage (default: 1)
pageSizeintegerItems per page (default: 20, maximum: 100)

List all MEDs

curl -X GET "https://api.fypay.me/api/med" \
  -H "Authorization: Bearer $TOKEN"

Filter by status

curl -X GET "https://api.fypay.me/api/med?status=RECEIVED" \
  -H "Authorization: Bearer $TOKEN"

Filter by period

curl -X GET "https://api.fypay.me/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": "REQUESTING BANK S.A."
      },
      "contestedBank": {
        "ispb": "11111111",
        "name": "CONTESTED INSTITUTION S.A."
      },
      "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.

Get MED details

Use GET /api/med/\{id\} (the numeric MED id) to get all fields, including the status history (statusHistory), the detailed original transaction, the regulatory identifier idSolicitacaoDevolucao, and the block data (blockStatus, blockAmount). If the MED does not belong to your account, the API responds 404.

curl -X GET "https://api.fypay.me/api/med/42" \
  -H "Authorization: Bearer $TOKEN"

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 the webhook asynchronously. Delivery has a 10-second timeout and only 2xx responses count as success; otherwise, the system retries delivery.

Use idempotency

Use the medId + event combination as the idempotency key (the same medId appears in MedCreated and later in MedAccepted or MedRejected). The same webhook may be redelivered if delivery fails.

Monitor open MEDs

Periodically query GET /api/med?status=RECEIVED to ensure no MED is left unattended.

Next Steps

On this page