> ## 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.

# cash_in Webhook

> Lifecycle notifications for a SPEI cash-in

## When it fires

The `cash_in` webhook type receives the lifecycle events of a charge created via `POST /api/spei/cash-in`:

| `event`                        | `status`     | Meaning                                                           |
| ------------------------------ | ------------ | ----------------------------------------------------------------- |
| `transaction.cash_in.settled`  | `LIQUIDATED` | The SPEI transfer arrived at the disposable CLABE and was settled |
| `transaction.cash_in.rejected` | `REJECTED`   | The SPEI network rejected the transfer                            |
| `transaction.cash_in.expired`  | `EXPIRED`    | The CLABE expired (\~24h) without receiving the transfer          |
| `transaction.cash_in.pending`  | `PENDING`    | Intermediate processing update                                    |

<Info>
  The **return** of an already settled cash-in (`transaction.cash_in.returned`) is delivered on the [`refund_in`](/en/guides/webhooks/refund-in) webhook type, not on `cash_in`.
</Info>

## Payload

```json theme={"system"}
{
  "event": "transaction.cash_in.settled",
  "transactionId": "12345",
  "amount": 50000,
  "currency": "MXN",
  "status": "LIQUIDATED",
  "destinationClabe": "012180001234567890",
  "sourceClabe": "646180123456789012",
  "payerName": "Juan Perez",
  "reference": "1234567",
  "voucher": "CEP20260512A1B2C3",
  "occurredAt": "2026-05-12T14:31:05.000Z"
}
```

* `destinationClabe` — the disposable CLABE issued when the charge was created
* `sourceClabe` — the payer's CLABE (when provided by the network)
* `amount` — amount in MXN cents
* Reference fields (`reference`, `voucher`) may be `null` depending on the flow

## Headers

| Header               | Value                              |
| -------------------- | ---------------------------------- |
| `x-event-id`         | Unique event UUID (use for dedupe) |
| `X-NTXPay-Signature` | `sha256=<hmac>` of the raw body    |

## Expected Response

Respond `200 OK` in under 10 seconds. On any status other than `2xx`, NTX Pay retries up to 5 times with exponential backoff.

```http theme={"system"}
HTTP/1.1 200 OK
Content-Type: application/json

{"received": true}
```

## Processing

Mark the order as paid only when `event` is `transaction.cash_in.settled` (or `status: LIQUIDATED`):

```typescript theme={"system"}
const event = JSON.parse(rawBody.toString());
if (event.event === 'transaction.cash_in.settled') {
  await markOrderPaid(event.transactionId, event.amount);
}
```

For the complete handler with HMAC validation and dedupe in Node.js, Python, Java, and Go, see [Implementation](/en/guides/webhooks/implementation).
