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

# Webhooks

> Receive real-time event updates from Monirates directly to your server.

Webhooks allow your system to receive real-time event notifications from Monirates. When key events happen — like a payment or currency exchange — Monirates sends an HTTP `POST` request with a JSON payload to your registered URL.

***

## Setup Overview

All webhook configuration happens in your Monirates dashboard:

1. Log in at [business.monirates.com](https://business.monirates.com) (or [dev.business.monirates.com](https://dev.business.monirates.com) for sandbox).
2. Navigate to **Settings**.
3. Generate your **API Key** and **Secret Key**.
4. Register your **Webhook URL**.

***

## Step 1: Generate Your API Key

Your API key authorizes requests and enables your webhook to receive events. Include it in your request headers:

```text theme={null}
x-api-key: MR_v1_your_unique_api_key
```

***

## Step 2: Generate Your Secret Key

The Secret Key is used to verify that incoming webhook events genuinely originate from Monirates. Every webhook delivery includes a signature header:

```text theme={null}
x-monirates-signature: <signature>
```

The signature is computed using **HMAC SHA256** over the raw request body combined with your Secret Key.

### Validating the Signature

Always validate the signature before processing any webhook event.

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  const signature = req.headers['x-monirates-signature'];

  const computed = crypto
    .createHmac('sha256', process.env.MONIRATES_SECRET_KEY)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (computed !== signature) {
    return res.status(401).send('Invalid signature');
  }

  // Safe to process the event
  ```

  ```python Python theme={null}
  import hmac
  import hashlib
  import json
  import os

  secret_key = os.environ.get("MONIRATES_SECRET_KEY").encode()
  signature = request.headers.get("x-monirates-signature")

  body = json.dumps(request.json, separators=(',', ':')).encode()
  computed = hmac.new(secret_key, body, hashlib.sha256).hexdigest()

  if not hmac.compare_digest(computed, signature):
      return {"error": "Invalid signature"}, 401

  # Safe to process the event
  ```

  ```php PHP theme={null}
  $secretKey = getenv('MONIRATES_SECRET_KEY');
  $signature = $_SERVER['HTTP_X_MONIRATES_SIGNATURE'];

  $body = file_get_contents('php://input');
  $computed = hash_hmac('sha256', $body, $secretKey);

  if (!hash_equals($computed, $signature)) {
      http_response_code(401);
      exit('Invalid signature');
  }

  // Safe to process the event
  ```
</CodeGroup>

<Warning>
  Never share your Secret Key. Store it securely as an environment variable and never commit it to version control.
</Warning>

***

## Step 3: Register Your Webhook URL

Your webhook endpoint must:

* Accept **POST** requests
* Receive **JSON** payloads
* Be **publicly accessible** over HTTPS

Register your endpoint URL in the **Settings** section of your Monirates dashboard.

***

## Retry Behavior

If Monirates cannot reach your endpoint, deliveries are retried automatically:

| Attempt           | Behavior                          |
| ----------------- | --------------------------------- |
| 1st               | Initial delivery                  |
| 2nd               | Retry after delay                 |
| 3rd               | Final retry after increased delay |
| After 3rd failure | Retries stop                      |

### Manual Retry via API

You can also view and retry failed webhook events programmatically:

| Method | Endpoint                     | Description                      |
| ------ | ---------------------------- | -------------------------------- |
| `GET`  | `/webhooks`                  | List all webhook events          |
| `GET`  | `/webhook/{webhookId}`       | View details of a specific event |
| `POST` | `/webhook/{webhookId}/retry` | Manually retry a failed event    |

***

## Security Requirements

Two headers are used to secure webhook communication:

| Header                  | Purpose                                      |
| ----------------------- | -------------------------------------------- |
| `x-api-key`             | Authorizes the incoming webhook request      |
| `x-monirates-signature` | Validates authenticity and payload integrity |

<Warning>
  Always reject webhook events that are missing or have an invalid `x-monirates-signature`. Do not process unsigned events.
</Warning>

***

## Event Types & Sample Payloads

### Payment Link Event

Triggered when a payment link transaction is initiated or updated.

```json theme={null}
{
  "_id": "690df12b358c9311463ac6d4",
  "userId": "67e5345cdce758f487ab6ca6",
  "userGlobalId": "6976ea90-0afd-11f0-8cd1-296b05bbd448",
  "amount": 105500,
  "currencyIso2": "NG",
  "paymentDetails": {
    "accountName": "MONIRATES LIMITED",
    "accountNumber": "0115847370",
    "providerName": "MTN",
    "bankCode": "90221",
    "paymentMethod": "BANK_TRANSFER",
    "currency": "NGN"
  },
  "payerDetails": {
    "name": "Monirates",
    "email": "info@monirates.com"
  },
  "status": "PENDING",
  "source": "API",
  "globalId": "f7cfd470-bbdb-11f0-9062-8dd914a47085",
  "createdAt": "2025-11-07T13:16:27.986Z"
}
```

### Currency Exchange Event

Triggered when a currency exchange transaction is initiated or completed.

```json theme={null}
{
  "_id": "68ff77732efaebbdad28c843",
  "globalId": "2fd81ca0-b33b-11f0-82b7-2929f12a03df",
  "offerId": "68b5a636793705d3cc1578e7",
  "buyerGlobalId": "6976ea90-0afd-11f0-8cd1-296b05bbd448",
  "fromCurrency": "GBP",
  "toCurrency": "NGN",
  "rate": 1972.2,
  "fee": 0,
  "amount": 200,
  "status": "SUCCESSFUL",
  "buyerDebitPaymentMethod": "BANK_TRANSFER",
  "buyerCreditPaymentMethod": "BANK_TRANSFER",
  "buyerCreditPaymentDetails": {
    "accountName": "MONIRATES LIMITED",
    "accountNumber": "0115847370",
    "providerName": "SAFE HAVEN SANDBOX BANK",
    "bankCode": "999240",
    "paymentMethod": "BANK_TRANSFER",
    "iso2": "NG",
    "currency": "NGN"
  },
  "buyerDebitPaymentDetails": {
    "accountName": "MONIRATES LIMITED",
    "accountNumber": "0115847370",
    "providerName": "1234567",
    "bankCode": "1234567",
    "paymentMethod": "BANK_TRANSFER",
    "iso2": "GB",
    "currency": "GBP"
  },
  "sellerCreditPaymentDetails": {
    "accountName": "Rahama Rahama",
    "accountNumber": "2580369147",
    "providerName": "5566447755",
    "bankCode": "5566447755",
    "paymentMethod": "BANK_TRANSFER",
    "iso2": "GB",
    "currency": "GBP",
    "isUssdCode": false
  },
  "source": "API",
  "buyerMadePayment": true,
  "hasBuyerPaymentProof": false,
  "buyerPaymentProofUrl": null,
  "paymentReferenceCode": 938663,
  "createdAt": "2025-10-27T13:45:23.941Z",
  "updatedAt": "2025-10-27T13:55:26.972Z"
}
```

***

## Fetching Webhook Logs

Beyond the API, you can also view webhook delivery history directly in the Monirates dashboard — filter by `SUCCESSFUL` or `FAILED` and track retry attempts for reconciliation.

***

<Note>
  Need help integrating? Reach out to the Monirates support team from your dashboard.
</Note>
