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

# Webhook cash_out

> Notificaciones del ciclo de vida de un SPEI cash-out

## Cuándo se dispara

El webhook del tipo `cash_out` recibe los eventos del ciclo de vida de una transferencia creada vía `POST /api/spei/cash-out`:

| `event`                         | `status`     | Significado                                                          |
| ------------------------------- | ------------ | -------------------------------------------------------------------- |
| `transaction.cash_out.settled`  | `LIQUIDATED` | La transferencia fue liquidada en la red SPEI                        |
| `transaction.cash_out.rejected` | `REJECTED`   | La red SPEI rechazó la transferencia — el saldo debitado se devuelve |
| `transaction.cash_out.pending`  | `PENDING`    | Actualización intermedia de procesamiento                            |

<Info>
  La **devolución** de un cash-out ya liquidado (`transaction.cash_out.returned`) — cuando el banco de la contraparte devuelve la transferencia — se entrega en el webhook del tipo [`refund_out`](/es/guides/webhooks/refund-out), no en el `cash_out`.
</Info>

## Payload

```json theme={"system"}
{
  "event": "transaction.cash_out.settled",
  "transactionId": "56789",
  "amount": 50000,
  "currency": "MXN",
  "status": "LIQUIDATED",
  "destinationClabe": "012180001234567890",
  "sourceClabe": null,
  "reference": "9876543",
  "voucher": "CEP20260513D4E5F6",
  "occurredAt": "2026-05-13T12:00:42.000Z"
}
```

En `status: REJECTED`, los campos de comprobante (`reference`, `voucher`) pueden venir `null` — la red SPEI nunca confirmó la transacción.

## Headers

| Header               | Valor                                     |
| -------------------- | ----------------------------------------- |
| `x-event-id`         | UUID único del evento (úsalo para dedupe) |
| `X-NTXPay-Signature` | `sha256=<hmac>` del cuerpo crudo          |

## Comportamiento

* **At-least-once**: puedes recibir el mismo evento más de una vez. Deduplica por `x-event-id`.
* **Falla después del éxito**: no sucede. Una transacción no cambia de `LIQUIDATED` a `REJECTED`.
* **Devolución**: si la contraparte devuelve después de la liquidación, recibes `transaction.cash_out.returned` en el webhook `refund_out`, con el mismo `transactionId`.

## Respuesta Esperada

`200 OK` en un máximo de 10 segundos.

## Procesamiento

```typescript theme={"system"}
const event = JSON.parse(rawBody.toString());
if (event.event === 'transaction.cash_out.settled') {
  await markPayoutSettled(event.transactionId);
} else if (event.event === 'transaction.cash_out.rejected') {
  await markPayoutFailed(event.transactionId); // saldo devuelto automáticamente
}
```

Para el handler completo con validación HMAC y dedupe en Node.js, Python, Java y Go, consulta [Implementación](/es/guides/webhooks/implementation).
