# Callback Notifications

After a **successful payment** in the Bank App, the platform sends a **server-to-server** notification to your **Callback URL**. The payload contains the payment outcome and attributes required for fulfillment and reconciliation, along with a **signature** you must verify.

***

### When it is sent

* **Trigger:** after successful payment execution.
* **Primary signal:** use the callback as the **source of truth** for order fulfillment.
* If a callback is delayed or rejected by your server, you may cross-check with `GET /v2/rtp/{id}`.

> A notification is considered **successfully received** only if your server responds with **HTTP 200 OK**.

***

### Notification structure

**Content-Type:** `application/json`

```json
{
  "result": {
    "rtpId": "string (GUID)",
    "rtpStatus": "Accepted",
    "orderId": "string",
    "payId": "string (GUID)",
    "amount": 0,
    "commission": 0,
    "currency": "MDL",
    "payerName": "string",
    "payerIban": "string",
    "executedAt": "YYYY-MM-DDThh:mm:ss±hh:mm"
  },
  "signature": "string (Base64)"
}
```

#### Fields

| Field               | Type                     | Description                                          |
| ------------------- | ------------------------ | ---------------------------------------------------- |
| `result`            | object                   | Wrapper for notification data.                       |
| `result.rtpId`      | string (GUID)            | RTP unique identifier.                               |
| `result.rtpStatus`  | enum                     | Notification status. Possible values: **Accepted**.  |
| `result.orderId`    | string                   | Merchant order identifier (if provided at create).   |
| `result.payId`      | string (GUID)            | Unique **payment** identifier.                       |
| `result.amount`     | number (decimal)         | Payment amount.                                      |
| `result.commission` | number (decimal)         | Payment commission.                                  |
| `result.currency`   | string (ISO 4217)        | Payment currency. Possible values: `MDL`.            |
| `result.payerName`  | string                   | Payer abbreviated name (e.g., “John D.”).            |
| `result.payerIban`  | string                   | Payer IBAN.                                          |
| `result.executedAt` | string (ISO 8601-1:2019) | Payment execution timestamp.                         |
| `signature`         | string (Base64)          | Validation signature for integrity and authenticity. |

***

### Example notification

```json
{
  "result": {
    "rtpId": "123e4567-e89b-12d3-a456-426614174000",
    "rtpStatus": "Accepted",
    "orderId": "123",
    "payId": "c56a4180-65aa-42ec-a945-5fd21dec0538",
    "amount": 100.00,
    "commission": 1.00,
    "currency": "MDL",
    "payerName": "John D.",
    "payerIban": "MD24AG000225100014156789",
    "executedAt": "2029-10-22T10:32:28+03:00"
  },
  "signature": "r4KwwIUXQGHhcEM7C4um8o9rSrGEriTRcYQuBbmjEec="
}
```

***

### Signature validation

Merchants receive a **Signature Key** (in maibmerchants project settings). Validate every callback as follows:

1. Take all fields from the **`result`** object (do **not** include the top-level `signature`).
2. **Exclude** any field that is `null` or an empty string.
3. Format **`amount`** and **`commission`** with **exactly two decimals** (e.g., `0.50`, `2.31`).
4. **Sort** the remaining field names **alphabetically (case-insensitive)**.
5. **Concatenate** the corresponding field values using `:` as a separator, in the sorted order.
6. **Append** `:` and the **Signature Key** to the end of the string.
7. Compute **SHA-256** over the resulting string (binary).
8. Encode the hash with **Base64** → this must equal the incoming `signature`.

> If the calculated signature does not match the received `signature`, do **not** fulfill the order and respond with a **non-200** status to allow redelivery.

***

{% hint style="info" %}
**Handling recommendations**

* **Verify the signature first**, then update your order/payment state.
* Make the handler **idempotent**: repeated notifications with the same `payId` must not duplicate fulfillment.
* Log `rtpId`, `payId`, `rtpStatus`, `executedAt`, and the verification outcome.
* Respond with **HTTP 200 OK** only after successful processing. If verification fails or processing errors occur, return a **non-200** status.
  {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.maibmerchants.md/request-to-pay/api-reference/callback-notifications.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
