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

# Webhooks

## Overview

Webhooks allow your system to receive real-time updates from our platform. Instead of constantly checking (polling) for updates, we notify your system as soon as something happens — like a payment being made or a user completing a form.

It’s like getting a text message when a delivery arrives, instead of refreshing the tracking page every 5 minutes!

***

## How It Works

1. You configure your webhook URL (an API endpoint on your server).
2. We send a `POST` request to that URL when a payment/collection is successfully processed on behalf of **you** or your **customer**.
3. You verify the authenticity of the webhook by using your apikey to hash the notification payload and compare with the signature attached in the headers of the webhook.
4. If, verification is successful process the transaction data on your end — e.g., mark an order as paid - and respond to the notification with a light response like 200 Success.

<Info>
  If we receive an error response from your webhook url, our system would automatically retry sending you that notification 4 times.
  We will retry with the schedule below:

  1st try => immediately

  2nd try => after 5mins

  3rd try => after 5mins

  4th try => after 1hour

  5th//last try => after 4hours.

  If we don't get a 200 Success response after the last and 5th retry, we stop resending the webhook.
</Info>

Here is simple example of a webhook URL

```json theme={null}
app.post('/your-url/webhook', (req, res) => {
  const event = req.body;
    // Handle the event
  res.status(200).send('OK');
});
```

<Info>
  The below is the field name of the signature header to verify the authenticity of the request. This is important for security, ensuring that the data comes from us and hasn't been tampered with.

  `**x-embedly-signature : sha512(notification payload, api_key)**`
</Info>

## Sample code for payload verification

<CodeGroup>
  ```javascript JavaScript theme={null}
  app.post('/webhook', jsonParserWithRaw, (req, res) => {
    const signature = req.headers['x-embedly-signature'];
    const rawBody = req.rawBody;
    if (!signature || !rawBody) {
      return res.status(400).json({ error: 'Missing signature or body' });
    }

    const hmac = crypto.createHmac('sha512', api_key);
    hmac.update(rawBody, 'utf8');
    const computedSignature = hmac.digest('hex');

    if (computedSignature !== signature) {
      return res.status(401).json({
        status: 'error',
        message: 'Invalid signature',
      });
    }

    res.status(200).json({
      status: 'success',
      message: 'Webhook received and verified',
      data: req.body,
      timestamp: new Date().toISOString(),
    });
  });
  ```

  ```go Go theme={null}
  func webhookHandler(w http.ResponseWriter, r *http.Request) {
  	if r.Method != "POST" {
  		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  		return
  	}

  	signature := r.Header.Get("x-embedly-signature")
  	bodyBytes, err := io.ReadAll(r.Body)
  	if err != nil {
  		http.Error(w, "Error reading request body", http.StatusBadRequest)
  		return
  	}

  	if signature == "" || len(bodyBytes) == 0 {
  		http.Error(w, "Missing signature or body", http.StatusBadRequest)
  		return
  	}

  	mac := hmac.New(sha512.New, []byte(api_key))
  	mac.Write(bodyBytes)
  	computedSignature := hex.EncodeToString(mac.Sum(nil))

  	if computedSignature != signature {
  		response := map[string]interface{}{
  			"status":  "error",
  			"message": "Invalid signature",
  		}
  		w.Header().Set("Content-Type", "application/json")
  		w.WriteHeader(http.StatusUnauthorized)
  		json.NewEncoder(w).Encode(response)
  		return
  	}

  	var bodyData interface{}
  	if err := json.Unmarshal(bodyBytes, &bodyData); err != nil {
  		http.Error(w, "Error parsing JSON body", http.StatusBadRequest)
  		return
  	}

  	response := map[string]interface{}{
  		"status":    "success",
  		"message":   "Webhook received and verified",
  		"data":      bodyData,
  		"timestamp": time.Now().Format(time.RFC3339),
  	}

  	w.Header().Set("Content-Type", "application/json")
  	json.NewEncoder(w).Encode(response)
  }
  ```
</CodeGroup>

| Field Name           | Description                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------- |
| AccountNumber        | The wallet account that received the payment. This belongs to your customer or business.       |
| transactionReference | A unique ID for the transaction. Use this to avoid duplicate processing.                       |
| TransactionAmount    | The amount paid (in NGN).                                                                      |
| Fee                  | Transaction fee (if any). In most cases this may be 0.                                         |
| SenderName           | The name of the person who sent the money.                                                     |
| SenderBank           | The sender’s bank name.                                                                        |
| DateOfTransaction    | The timestamp of the transaction (in ISO format).                                              |
| Source               | The payment channel used (e.g., NIP for real-time transfers).                                  |
| Description          | The transfer message or narration, if any.                                                     |
| DC                   | "C" for credit (money in), "D" for debit (money out). In this context, it will usually be "C". |

<RequestExample>
  ```json Card Transaction ATM Success theme={null}
  {
    "event": "card.transaction.atm",
    "data": {
      "sessionId": "009988770011",
      "stan": "123456",
      "rrn": "009988770011",
      "debitAccountNumber": "9710002753",
      "debitAccountName": "Becca Duru",
      "amount": 5000.0,
      "currency": "NGN",
      "status": "success",
      "paymentReference": "009988770011",
      "dateOfTransaction": "2026-01-14T09:49:08"
    }
  }
  ```

  ```json Card Transaction POS Success theme={null}
  {
    "event": "card.transaction.pos",
    "data": {
      "sessionId": "009988770011",
      "stan": "123456",
      "rrn": "009988770011",
      "debitAccountNumber": "9710002753",
      "debitAccountName": "Becca Duru",
      "amount": 5000.0,
      "currency": "NGN",
      "status": "success",
      "paymentReference": "009988770011",
      "dateOfTransaction": "2026-01-14T09:49:08"
    }
  }
  ```

  ```json Card management update info theme={null}
  {
    "event": "card.management.updateInfo",
    "data": {
      "source": "CARD_OPERATION",
      "customerId": "bbb065d1-9325-11f0-a7cf-0274f77d4a81",
      "walletId": "41bf2e86-93e1-11f0-a7cf-0274f77d4a81",
      "organizationId": "f7e33625-9324-11f0-a7cf-0274f77d4a81",
      "accountNumber": "9710006893",
      "maskedCardNumber": "564019********3212",
      "isSuccessful": true,
      "dateCreated": "2025-09-17T17:00:09"
    }
  }
  ```

  ```json Card management relink theme={null}
  {
    "event": "card.management.relink",
    "data": {
      "source": "CARD_OPERATION",
      "customerId": "b8cfbc3b-9325-11f0-a7cf-0274f77d4a81",
      "walletId": "1c0e05ad-93e1-11f0-a7cf-0274f77d4a81",
      "organizationId": "f7e33625-9324-11f0-a7cf-0274f77d4a81",
      "accountNumber": "9710006884",
      "maskedCardNumber": "564019********3204",
      "isSuccessful": true,
      "dateCreated": "2025-09-17T16:15:22"
    }
  }
  ```

  ```json Payout theme={null}
  {
    "event": "payout",
    "data": {
      "sessionId": null,
      "debitAccountNumber": "0097411531",
      "creditAccountNumber": "0003433020",
      "debitAccountName": "Olufunso Olunaike",
      "creditAccountName": "OLUNAIKE OLUFUNSO ABRAHAM",
      "amount": 500.0,
      "currency": "NGN",
      "status": "Success",
      "paymentReference": "668931654633533785081478974241",
      "deliveryStatusMessage": null,
      "deliveryStatusCode": null,
      "dateOfTransaction": "0001-01-01T00:00:00"
    }
  }
  ```

  ```json Inflow theme={null}
  {
    "event": "nip",
    "data": {
      "accountNumber": "9710301635",
      "accountName": "Embedly Financial Technology Company Limited/Ifeoluwa Olunubi",
      "bankCode": "000001",
      "reference": "100004260219092716152725991782",
      "amount": 100,
      "fee": 0,
      "senderName": "IFEOLUWA EMMANUEL OLUNUBI",
      "senderBank": "OPAY",
      "senderBankCode": "100004",
      "dateOfTransaction": "2026-02-19T09:27:22.5396459Z",
      "description": "Transfer from IFEOLUWA EMMANUEL OLUNUBI",
      "senderAccountNumber": "8147615700"
    }
  }
  ```

  ```json Checkout Success theme={null}
  {
    "event": "checkout.payment.success",
    "data": {
      "transactionId": "f958ce5d-4878-4e4d-ab64-6e8a6209ed6e",
      "walletId": "9bea6e3e-2e55-46c4-a624-b47b0c8c8053",
      "checkoutRef": "CHK202510172015590962305",
      "amount": 200.0,
      "status": "success",
      "message": "Payment received successfully",
      "senderAccountNumber": "0098960218",
      "senderName": "OLALEKAN YUSUF BALOGUN",
      "senderBankCode": "000001",
      "recipientAccountNumber": "9550016702",
      "recipientName": "Crow Pilot Checkout",
      "reference": "000001251017211645a630c9aa9405",
      "createdAt": "2025-10-17T20:18:38.0815347Z"
    }
  }
  ```
</RequestExample>
