> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nyxpag.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos de MED: med.created e med.updated

> Formato dos webhooks med.created e med.updated: quando um pagador contesta um Pix, o valor retido e como acompanhar a decisão até a liberação.

Quando um pagador contesta um Pix pelo MED, a NyxPag avisa a sua URL assim que o valor é retido, e de novo a cada mudança de situação. Esses eventos usam o mesmo endpoint e a mesma [assinatura](/webhooks/assinatura) dos eventos de transação.

<Note>
  Para entender o que é um MED e o que acontece com o dinheiro em cada situação, leia o guia [Contestações (MED)](/guides/disputas/med).
</Note>

## Os dois eventos

| Evento | Quando chega |
| - | - |
| `med.created` | Uma nova contestação foi aberta e o valor ficou retido |
| `med.updated` | A situação da contestação mudou |

O cabeçalho `X-NyxPag-Event` e o campo `event` do corpo sempre trazem exatamente `med.created` ou `med.updated`. O que mudou está em `data.status` e em `data.previousStatus`.

## Formato do corpo

```json med.created theme={"dark"}
{
  "event": "med.created",
  "data": {
    "id": "med_01JABCDEF0123456789",
    "status": "pending",
    "amount": 149.9,
    "currency": "BRL",
    "transactionId": "txn_mabc123_0123456789abcdef",
    "orderId": "PEDIDO-1042",
    "reason": "Contestação MED registrada pela NyxPag.",
    "createdAt": "2026-10-03T16:20:00.000Z",
    "updatedAt": "2026-10-03T16:20:00.000Z",
    "resolvedAt": null
  },
  "requestId": "0f7c1a9e-3b7d-4c52-9a0e-5d8f3c2b1a44",
  "createdAt": "2026-10-03T16:20:01.000Z"
}
```

```json med.updated theme={"dark"}
{
  "event": "med.updated",
  "data": {
    "id": "med_01JABCDEF0123456789",
    "status": "rejected",
    "previousStatus": "pending",
    "amount": 149.9,
    "currency": "BRL",
    "transactionId": "txn_mabc123_0123456789abcdef",
    "orderId": "PEDIDO-1042",
    "reason": "Contestação MED registrada pela NyxPag.",
    "createdAt": "2026-10-03T16:20:00.000Z",
    "updatedAt": "2026-10-05T10:02:00.000Z",
    "resolvedAt": "2026-10-05T10:02:00.000Z"
  },
  "requestId": "6d2e8b10-72aa-4f1c-8c1d-1b7f0c9a2e55",
  "createdAt": "2026-10-05T10:02:01.000Z"
}
```

<Warning>
  O corpo de MED **não tem o campo `id` no nível de cima**, diferente dos eventos `transaction.*`. Para deduplicar, use o cabeçalho `X-NyxPag-Delivery`. O `data.id` identifica a contestação, não a entrega: a mesma contestação gera vários eventos.
</Warning>

## Campos do objeto MED

| Campo | Tipo | Descrição |
| - | - | - |
| `data.id` | string | ID da contestação, no formato `med_...` |
| `data.status` | string | `pending`, `approved`, `rejected`, `cancelled` ou `closed` |
| `data.previousStatus` | string ou ausente | Situação anterior. Só aparece em `med.updated` |
| `data.amount` | number | Valor contestado, em reais |
| `data.currency` | string | Sempre `BRL` |
| `data.transactionId` | string | ID da transação NyxPag que foi contestada |
| `data.orderId` | string | Seu `externalId`, quando existe. Senão, o ID da transação |
| `data.reason` | string | Motivo registrado, até 1000 caracteres |
| `data.createdAt` | string ou null | Abertura da contestação |
| `data.updatedAt` | string ou null | Última mudança |
| `data.resolvedAt` | string ou null | Quando foi decidida. `null` enquanto está `pending` |
| `requestId` | string | UUID desta emissão |
| `createdAt` | string | Quando o evento foi gerado |

## O que cada status significa para o seu dinheiro

| Status | O que aconteceu | O que fazer |
| - | - | - |
| `pending` | Contestação em análise. O valor está **retido** | Aguarde. Não conte esse valor como disponível |
| `approved` | A contestação do pagador foi **aceita** | O valor não volta para a sua conta |
| `rejected` | A contestação foi **negada** | O valor retido é liberado para a sua conta |
| `cancelled` | A contestação foi cancelada | Confira o estado em `GET /meds/{id}` e o saldo em `GET /balance` |
| `closed` | Contestação encerrada | Registre e confira o saldo em `GET /balance` |

<Note>
  O nome `approved` descreve a decisão sobre o pedido do **pagador**, não sobre o seu recebimento. `approved` significa que o pagador teve razão.
</Note>

## Receptor

<CodeGroup>
  ```javascript Node.js theme={"dark"}
  async function handleMedEvent(event, deliveryId) {
    // MED não tem event.id: deduplique pelo cabeçalho X-NyxPag-Delivery
    if (!(await db.webhookEvents.insertIfAbsent({ id: deliveryId }))) return;

    const med = event.data;

    if (event.event === "med.created") {
      await orders.flagDisputed(med.orderId, { medId: med.id, amount: med.amount });
      return;
    }

    // med.updated
    if (med.status === "rejected") await orders.releaseDisputeHold(med.orderId);
    if (med.status === "approved") await orders.confirmDisputeLoss(med.orderId);
  }
  ```

  ```python Python theme={"dark"}
  def handle_med_event(event: dict, delivery_id: str) -> None:
      # MED não tem event["id"]: deduplique pelo cabeçalho X-NyxPag-Delivery
      if not db.webhook_events.insert_if_absent(delivery_id):
          return

      med = event["data"]

      if event["event"] == "med.created":
          orders.flag_disputed(med["orderId"], med_id=med["id"], amount=med["amount"])
          return

      if med["status"] == "rejected":
          orders.release_dispute_hold(med["orderId"])
      elif med["status"] == "approved":
          orders.confirm_dispute_loss(med["orderId"])
  ```

  ```php PHP theme={"dark"}
  function handleMedEvent(array $event, string $deliveryId): void
  {
      // MED não tem $event['id']: deduplique pelo cabeçalho X-NyxPag-Delivery
      if (!$GLOBALS['db']->webhookEvents->insertIfAbsent($deliveryId)) {
          return;
      }

      $med = $event['data'];

      if ($event['event'] === 'med.created') {
          orders_flag_disputed($med['orderId'], $med['id'], $med['amount']);
          return;
      }

      if ($med['status'] === 'rejected') orders_release_dispute_hold($med['orderId']);
      if ($med['status'] === 'approved') orders_confirm_dispute_loss($med['orderId']);
  }
  ```
</CodeGroup>

<Tip>
  Os webhooks podem falhar ou chegar fora de ordem. Concilie periodicamente com [`GET /meds`](/api-reference/med/listar-contestações-med): ele é a fonte de verdade da situação atual de cada contestação.
</Tip>

<CardGroup cols={2}>
  <Card title="Guia de MED" icon="book-open" href="/guides/disputas/med">
    O que é o MED e como a NyxPag trata o valor retido.
  </Card>

  <Card title="Listar contestações" icon="code" href="/api-reference/med/listar-contestações-med">
    Referência do endpoint GET /meds.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.