# Money In confirmation

This guide explains how to receive notifications every time you get a Money In transaction into your Monato accounts.

Money In notifications are sent as webhooks with `msg_name = "MONEY_IN"` and a common payload format for:

- **External credits (SPEI)** coming from other banks.
- **Internal credits** generated by `POST /v1/transactions/internal_transaction` (book-to-book transfers between Monato accounts).


You can distinguish between these cases using fields such as `sub_category` and `payer_institution`.

## Register for Money In notifications

In order to receive `MONEY_IN` notifications, you must register the endpoint where you expect the webhook.

**Endpoint**
`POST /v1/clients/{client_id}/webhooks`

**Request**
**Path parameters**:

- `client_id` – your Monato client identifier.


**Query Parameters**: none
**Request**
**Headers**

- `Authorization: Bearer <token>`
- `Content-Type: application/json`


**Body**


```json
{
  "client_id": "{{clientId}}",
  "url": "https://example.com/money-in-webhook",
  "token": "secretToken0123",
  "webhook_type": "MONEY_IN",
  "auth_type": "AUTH"
}
```

**Response**
**Status Code**: 200 OK
**Response Body**:


```json
{
  "id": "0c2d358f-0626-4c4e-b40b-9ab7c9dffe71",
  "clientId": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
  "url": "https://example.com/money-in-webhook",
  "token": "secretToken0123",
  "webhookType": "MONEY_IN",
  "webhookStatus": "ACTIVE",
  "createdAt": "2025-05-19 15:52:51.593012-06:00",
  "updatedAt": "2025-05-19 15:52:51.593012-06:00",
  "deletedAt": null,
  "blockedAt": null,
  "deletedBy": null,
  "blockedBy": null
}
```

The request body uses `snake_case` (e.g. `webhook_type`) while the response uses `camelCase` (e.g. `webhookType`). This is expected and consistent across the API.

### Managing client webhooks (list, update, delete)

You can manage your webhooks via the client-scoped API:

| Method | Path | Description |
|  --- | --- | --- |
| GET | `/v1/clients/{client_id}/webhooks` | List client webhooks |
| POST | `/v1/clients/{client_id}/webhooks` | Create a client webhook |
| GET | `/v1/clients/{client_id}/webhooks/{id}` | Get a client webhook by ID |
| DELETE | `/v1/clients/{client_id}/webhooks/{id}` | Delete a client webhook |
| PATCH | `/v1/clients/{client_id}/webhooks/{id}` | Update a client webhook |


Typical fields in the response include:

- `id`, `clientId`, `url`, `token`
- `webhookType` (for example: `MONEY_IN`, `CEP`, `STATUS_UPDATE`)
- `authType` (`AUTH`)
- `webhookStatus` (`ACTIVE`, `INACTIVE`)
- Audit fields such as `createdAt`, `updatedAt`, `deletedAt`, etc.


> A more detailed guide on payloads and error codes for webhook management will be added soon. For now, use this section together with the examples above and the OpenAPI reference.


## Webhook notification

Once you register your endpoint for our webhook, you will get a POST request every time a Money In arrives.

**Common envelope**

We always send a JSON object with the following envelope:


```json
{
  "id_msg": "a7a126e8-fa74-411c-ad2b-b000f277bb0d",
  "msg_name": "MONEY_IN",
  "msg_date": "2025-04-02",
  "body": {
    "...": "..."
  }
}
```

* `id_msg`: unique identifier of the message.
* `msg_name`: for Money In notifications it is always `"MONEY_IN"`.
* `msg_date`: message date (`YYYY-MM-DD`).
* `body`: contains the Money In details.


**Example – External Money In (SPEI)**


```json
{
  "id_msg": "a7a126e8-fa74-411c-ad2b-b000f277bb0d",
  "msg_name": "MONEY_IN",
  "msg_date": "2025-04-02",
  "body": {
    "id": "0196da9a-8947-703e-9a3b-bf8c7d9f6059",
    "beneficiary_account": "734180123045603216",
    "beneficiary_name": "John Smith",
    "beneficiary_rfc": "XYZ123456789",
    "payer_account": "137180210044008609",
    "payer_name": "Juan Perez",
    "payer_rfc": "XYZ987654321",
    "payer_institution": "40002",
    "amount": "123.00",
    "transaction_date": "2025-04-02 10:14:05",
    "tracking_key": "50118609TBRNZ00I07219647",
    "payment_concept": "Payment for invoice 4567",
    "numeric_reference": "2504021",
    "sub_category": "SPEI_CREDIT",
    "registered_at": "2025-04-02T10:14:05.915184-06:00",
    "owner_id": "24f1e5d5-4045-4b1a-a0c4-5e6c6b1d44ef"
  }
}
```

**Example – Internal Money In (book-to-book)**

This is the type of Money In you will receive when funds are moved via
`POST /v1/transactions/internal_transaction` towards one of your Monato instruments.


```json
{
  "id_msg": "6daea2d2-ccb0-48f3-917c-f387dc8e99b0",
  "msg_name": "MONEY_IN",
  "msg_date": "2025-11-20",
  "body": {
    "id": "a0037594-5064-4dda-896b-f9b5dd4988dd",
    "beneficiary_account": "734185000000001177",
    "beneficiary_name": "MERCHANT TEST",
    "beneficiary_rfc": "FTR230125Q00",
    "payer_account": "734185000000000822",
    "payer_name": "Customer Test-1 Legal",
    "payer_rfc": "ND",
    "payer_institution": "90734",
    "amount": "1.00",
    "transaction_date": "2025-11-20 15:05:59",
    "tracking_key": "20251120FINCHESDHI7FVTU",
    "payment_concept": "CUST - SPEI",
    "numeric_reference": "1100003",
    "sub_category": "INT_CREDIT",
    "registered_at": "2025-11-20T15:05:59.915184-06:00",
    "owner_id": "24f1e5d5-4045-4b1a-a0c4-5e6c6b1d44ef"
  }
}
```

Another example between customers of the same merchant:


```json
{
  "id_msg": "2293f8fd-2fc5-4f4c-8985-e97466341b61",
  "msg_name": "MONEY_IN",
  "msg_date": "2025-11-20",
  "body": {
    "id": "ba964d20-c9dc-4bf1-8ffb-f0f9d5238485",
    "beneficiary_account": "734185000000000819",
    "beneficiary_name": "Customer Test-2 Legal",
    "beneficiary_rfc": "ND",
    "payer_account": "734185000000000822",
    "payer_name": "Customer Test-1 Legal",
    "payer_rfc": "ND",
    "payer_institution": "90734",
    "amount": "1.00",
    "transaction_date": "2025-11-20 14:59:56",
    "tracking_key": "20251120FINCHUSE4PV5VNY",
    "payment_concept": "CUST - CUST",
    "numeric_reference": "1100001",
    "sub_category": "INT_CREDIT",
    "registered_at": "2025-11-20T14:59:56.705283-06:00",
    "owner_id": "fd140e3c-29d8-4e39-bdd8-6e82c94ecad3"
  }
}
```

**Money In body fields**

Main fields you will see in the `body`:

- `id` – Internal transaction identifier in Monato.
- `beneficiary_account` – Beneficiary CLABE (or Monato CLABE for internal credits).
- `beneficiary_name` – Beneficiary account holder name.
- `beneficiary_rfc` – Beneficiary RFC.
- `payer_account` – Payer account number (CLABE or internal account).
- `payer_name` – Payer name.
- `payer_rfc` – Payer RFC, or `"ND"` when not provided.
- `payer_institution`
  - For SPEI credits: Banxico institution code of the originating bank (e.g. `40002`).
  - For internal credits: Monato internal institution code (e.g. `90734`).
- `amount` – Amount credited, as a string with 2 decimal places (e.g. `"123.00"`).
- `transaction_date`
  - Date and time when the transaction was registered in the rail.
  - Format: `YYYY-MM-DD HH:MM:SS`.
- `tracking_key` – SPEI tracking key or internal tracking id.
- `payment_concept` – Payment description / concept.
- `numeric_reference` – Numeric reference used by the payer.
- `sub_category`
  - Internal classification of the credit.
  - Typical values:
    - `SPEI_CREDIT` – external SPEI credit.
    - `INT_CREDIT` – internal credit from `internal_transaction`.
- `registered_at` – Timestamp in Monato when the transaction was created / persisted (ISO-8601 with timezone).
- `owner_id` – Identifier of the owner of the destination instrument (e.g. the customer that owns the receiving account).


You can use `sub_category` and `payer_institution` together to identify if a Money In comes from an external SPEI transfer or from an internal transaction.

## Accepting or rejecting a Money In

There are two behaviors depending on the type of Money In:

### 1. External Money In (SPEI)

For SPEI Money In, you can accept or reject the transaction directly from the webhook response:

* **Accept a Money In**
Respond to the Money In webhook with HTTP `201 Created`.
We will consider that you accepted the Money In.
* **Reject a Money In**
Respond to the Money In webhook with HTTP `422 Unprocessable Entity` and the Money In will be automatically refunded.
Additionally, you can send a JSON body with the reason:



```json
{
  "refundReason": "Invalid Amount"
}
```

### 2. Internal Money In

For internal credits (`sub_category = "INT_CREDIT"`), the funds have already been moved book-to-book by the time you receive the webhook. In this case:

* The Money In webhook is **informational only**.
* HTTP status codes on your response **do not** trigger an automatic refund.
* If you need to reverse an internal movement, you must create a new `internal_transaction` in the opposite direction (see **Internal Transactions API**).


## Refund a Money In (SPEI only)

Sometimes you accept a Money In but later you need to refund it. For external SPEI credits, you can do this with the refund endpoint.

**Endpoint**

`POST /v1/clients/{{clientId}}/transactions/{{transactionId}}/refund`

**Request**
**Path parameters**:

- **clientId**: `c2d1d1e3-3340-4170-980e-e9269bbbc551`
- **transactionId**: `e43171ad-af3b-40e3-913c-24cc386bf5ff`
This is sent in the Money In webhook or can be retrieved via the Transactions API.


**Query Parameters**: none
**Request Body**:


```json
{
    "description": "Lorem ipsum",
    "amount": "9.99"
}
```

**Response**
**Status Code**: 200 OK
**Response Body**:


```json
{
    "id": "e43171ad-af3b-40e3-913c-24cc386bf5ff",
    "bankId": "1953a92c-11e5-4315-b406-b89dd6b699b4",
    "clientId": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
    "externalReference": "2505201",
    "trackingId": "20250520FINCHARNJK5NHQG",
    "description": "Lorem ipsum",
    "amount": "9.99",
    "currency": "MXN",
    "category": "DEBIT_TRANS",
    "subCategory": "SPEI_DEBIT",
    "transactionStatus": "LIQUIDATED",
    "audit": {
        "createdAt": "2025-05-20 10:57:44.220281-06:00",
        "updatedAt": "2025-05-20 10:57:44.220281-06:00",
        "deletedAt": "None",
        "blockedAt": "None"
    },
    "originalTransactionId": "a1392ef1-75f2-457a-8203-d4fd4b435559"
}
```

This endpoint applies to **external SPEI transactions**.

> To “reverse” an internal transaction, you must create a new `internal_transaction` in the opposite direction.


Take note that the `/refund` endpoint return a transaction data, this is because we need to create a new SPEI transaction to return the money to the original sourcing account.

In this case, you will have two transactions:

* The original, with `transactionStatus = "REFUNDED"`.
* The refund transaction, with `transactionStatus = "LIQUIDATED"`.


## Retrieve a transaction

You can retrieve the details of a transaction with a call to:

**Endpoint**
`GET /v1/clients/{{clientId}}/transactions/{{transactionId}}`

**Request**
**Path parameters**:

- **clientId**: `c2d1d1e3-3340-4170-980e-e9269bbbc551`
- **transactionId**: `e43171ad-af3b-40e3-913c-24cc386bf5ff`
*This is sent in the Money In webhook or known from your own records.*


If you don’t send query parameters, the transaction is retrieved by `transactionId` only.

**Query parameters** (optional):

- **transaction_status** – Filter by transaction status.
Example: `LIQUIDATED`
- **tracking_id** – Filter by the SPEI tracking key associated with the transaction.
Example: `20250520FINCHARNJK5NHQG`
- **transaction_category** – Filter by transaction category.
Example: `DEBIT_TRANS`
- **bank_id** – Filter by bank identifier.
Example: `1953a92c-11e5-4315-b406-b89dd6b699b4`


**Example using tracking_id**


```http
GET /v1/clients/c2d1d1e3-3340-4170-980e-e9269bbbc551/transactions/e43171ad-af3b-40e3-913c-24cc386bf5ff?tracking_id=20250520FINCHARNJK5NHQG
```

**Response**
**Status Code**: 200 OK
**Response Body**:


```
{
  "id": "e43171ad-af3b-40e3-913c-24cc386bf5ff",
  "bankId": "1953a92c-11e5-4315-b406-b89dd6b699b4",
  "clientId": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
  "externalReference": "2505201",
  "trackingId": "20250520FINCHARNJK5NHQG",
  "description": "Lorem ipsum",
  "amount": "9.99",
  "currency": "MXN",
  "category": "DEBIT_TRANS",
  "subCategory": "SPEI_DEBIT",
  "transactionStatus": "LIQUIDATED",
  "audit": {
    "createdAt": "2025-05-20 10:57:44.220281-06:00",
    "updatedAt": "2025-05-20 10:57:44.220281-06:00",
    "deletedAt": "None",
    "blockedAt": "None"
  },
  "jsonReference": "{'transaction_date': '2025-05-20 10:14:05', ...}",
  "sourceInstrument": { ... },
  "destinationInstrument": { ... }
}
```