/
Webhooks

Webhooks

Table of Contents

Introduction

This guide provides comprehensive instructions for integrating with our webhook system to receive real-time updates about various events in your application. It covers subscription creation, payload structure, security measures, and best practices for a reliable integration.

Prerequisites

To effectively use our webhook system, ensure you have the following:

  • A publicly accessible HTTPS endpoint to receive webhook events

  • Capability to verify HMAC-SHA256 signatures

  • Familiarity with RESTful APIs and JSON.

  • Terminal application version should be on 1.11.0 or higher.

Webhook Subscription

Creating a Subscription

  1. Follow the instructions at Suscription Management

  2. A unique secret will be generated for each subscription

  3. Retrieve this secret from the subscription menu after creation

Endpoint Requirements

  • Support POST HTTP method

  • Use HTTPS for secure communication

Please note that only the POST method is supported for webhooks.

Webhook Event Payload

When an event occurs, we send a POST request to your specified endpoint. The request includes the following headers and a JSON body.

Request Headers

{ "user-agent": "ReactorNetty/1.1.9", "content-length": "631", "accept": "application/json", "accept-encoding": "gzip", "content-type": "application/json", "moniepoint-webhook-id": "b15ec58f-fa1f-4abb-8329-efaef8aa2bef", "moniepoint-webhook-signature": "WMfZqwVUKvjo6eY/W4qh5FT2M6Wb/2nSuC3aVMbpSNA=", "moniepoint-webhook-timestamp": "1728651860073", "x-forwarded-for": "141.147.77.31", "x-forwarded-host": "wenhookdemo.free.beeceptor.com", "x-forwarded-proto": "https" }

Header

Description

Header

Description

moniepoint-webhook-id

A unique identifier for the webhook event

moniepoint-webhook-timestamp

The time when the webhook was created, in epoch milliseconds

moniepoint-webhook-signature

A Base64encoded HMAC-SHA256 signature used to verify the payload's integrity

Request Body

The body of the webhook POST request contains a JSON object with details about the transaction. Below is an example payload:

{ "data": { "amount": 25300, "businessId": 10, "customFields": { "Invoice ID": "82674382" }, "responseCode": "09", "terminalSerial": "P260678997653", "businessOwnerId": 100, "responseMessage": "Airtime Purchase Pending", "transactionTime": "2024-10-10T09:32:57.916+0100", "transactionType": "AIRTIME", "merchantReference": "", "transactionStatus": "PENDING", "transactionReference": "ATP|2MPT0073|183849658930533333120", "retrievalReferenceNumber": "" }, "eventId": "59630e16-34f0-40ee-b5c3-a3d66e71ca41", "subject": { "domain": "CHANNELS", "resource": "business", "resourceId": "10" }, "createdAt": "2024-10-11T14:04:20.051330639", "eventType": "V1_POS_AIRTIME_TRANSACTION" }

Payload Field Descriptions

Field

Type

Description

Example

Field

Type

Description

Example

data.amount

Integer

The amount involved in the transaction, represented in smallest currency units (e.g., kobo for NGN).

25300 (Twenty-five thousand, three hundred naira)

data.businessId

Integer

Unique identifier of the business associated with the transaction.

10

data.customFields

Object

A map of custom key-value pairs related to the transaction, such as Invoice ID.

{ "Invoice ID": "82674382" }

data.responseCode

String

Code representing the response status of the transaction.

09 (Pending), 00(Approved), etc.

data.terminalSerial

String

The serial number of the POS terminal used for the transaction.

P260678997653

data.businessOwnerId

Integer

Unique identifier of the owner of the business.

100

data.responseMessage

String

Message providing additional information about the transaction response.

Airtime Purchase Pending

data.transactionTime

String (ISO 8601)

Timestamp indicating when the transaction occurred, in ISO 8601 format.

2024-10-10T09:32:57.916+0100

data.transactionType

String

The type of transaction being processed.

"AIRTIME"

data.merchantReference

String

Reference provided by the merchant for the transaction (can be empty if not applicable).

““

data.transactionStatus

String

Current status of the transaction.

PENDING, APPROVED

data.transactionReference

String

A reference number used for transaction retrieval (may be empty if not provided). This is always unique per transaction

ATP|2MPT0073|1838496858930533333120

data.retrievalReferenceNumber

String

A reference number for retrieving the transaction, if applicable.

““

eventId

String(UUID)

This is the unique identifier of the events.

59630e16-34f0-40ee-b5c3-a3d66e71ca41

subject.domain

String

The domain related to the event, e.g., "CHANNELS".

CHANNELS

subject.resoureceId

String

Unique identifier of the resource subject associated with the event, such as the businessId.

business

subject.resourceId

String

Unique identifier of the resource subject associated with the event, such as the businessId.

150

createdAt

String (ISO 8601)

Timestamp indicating when the event was created, in ISO 8601 format.

2024-10-11T14:04:20.051330639

eventType

String

Type of the event that was triggered, e.g., "V1_POS_AIRTIME_TRANSACTION".

V1_POS_AIRTIME_TRANSACTION

Available Event Types

Event Type

Description

Event Type

Description

V1_POS_WITHDRAWAL_TRANSACTION

Event triggered for a POS withdrawal transaction.

V1_POS_PURCHASE_TRANSACTION

Event for purchase transactions made via POS.

V1_POS_CARD_TRANSFER_TRANSACTION

Event for transferring funds using a card at POS.

V1_POS_BILL_PAYMENT_TRANSACTION

Event for bill payments made through POS.

V1_POS_TRANSFER_TRANSACTION

Event for pos transfers initiated from POS.

V1_TRANSFER_TRANSACTION

General transfer transaction event.

V1_POS_COLLECTION_TRANSACTION

Event triggered when a merchant monnify collection is made through POS

V1_POS_PAY_CODE_TRANSACTION

Event for transactions using a merchant monnify pay code at POS.

V1_POS_AIRTIME_TRANSACTION

Event for airtime purchase transactions through POS

V1_POS_BOOM_TRANSACTION

Event related to Boom-specific transactions via POS.

More event types may be added in the future. Ensure your system can accommodate new events.

Verifying Webhook Signatures

To ensure the authenticity of webhook requests, verify the signature included in the moniepoint-webhook-signatureheader.

Verification Process

  1. Concatenate moniepoint-webhook-id, moniepoint-webhook-timestamp, and the request body using '"__"' as a delimiter.

  2. Generate an HMAC-SHA256 hash using your webhook secret and the concatenated string.

  3. Compare the generated signature with the moniepoint-webhook-signature header to ensure integrity.

Code Sample for Signature Verification


const crypto = require('crypto'); /** * Validates the webhook payload signature against the expected signature. * * @param {string} webhookId - The unique identifier for the webhook. * @param {string} timestamp - The timestamp of the webhook event. * @param {string} requestBody - The body of the request as a JSON string. * @param {string} signature - The signature received in the webhook request. * @param {string} secretKey - The secret key used to generate the signature. * @returns {boolean} - Returns true if the signature is valid, false otherwise. * * @example * const webhookId = "your_webhook_id"; * const timestamp = "timestamp_value"; * const requestBody = '{"key": "value"}'; * const expectedSignature = "HvzIH3TaI0jFiMPbcuH4NblQ9Mmz+WKzodD1dpFlMHM="; * const secretKey = "your_secret_key"; * * const isValid = isPayloadSignatureValid(webhookId, timestamp, requestBody, expectedSignature, secretKey); * console.log(`Signature is valid: ${isValid}`); */ const isPayloadSignatureValid = (webhookId, timestamp, requestBody, signature, secretKey) => { const data = `${webhookId}__${timestamp}__${requestBody}`; const expectedSignature = crypto.createHmac('sha256', secretKey).update(data).digest('base64'); return signature === expectedSignature; };

 

Online Verification Tool

To manually verify the HMAC-SHA256 hash, you can use the https://www.devglan.com/online-tools/hmac-sha256-online

  1. Data: Use the concatenated string: moniepoint-webhook-id__moniepoint-webhook-timestamp__requestBody.

  2. Use your secret key.

  3. Algorithm: Select HMAC-SHA256.

This will generate the hash, which should match the moniepoint-webhook-signature header if the webhook request is valid.

Retry Mechanism

Our webhook system implements an automatic retry mechanism for failed deliveries, using exponential backoff.

  • Maximum Retries: The system will retry a given number of times. If the maximum number of attempts is reached without a successful delivery, the system will back off, ceasing further retries.

Conditions for Retry

  • A non2xx status code is returned by the subscriber's endpoint.

  • The request times out.

Handling Retries

  • Implement idempotent processing for incoming webhooks using the moniepoint-webhook-id to avoid duplicate processing.

  • Log failed attempts and responses for debugging purposes.

Best Practices

  1. Idempotency: Use the moniepoint-webhook-id from the header to ensure that the processing of each webhook event is idempotent. Since the same event will always have the same moniepoint-webhook-id, store and check this ID before processing. If an event with the same moniepoint-webhook-id has already been processed, ignore subsequent attempts to prevent duplication.

  2. Asynchronous Processing: Respond quickly with a 2xx status code and process the event in a background job to prevent timeouts.

  3. Security: Keep your endpoint_url and webhook_secret secure. Regenerate secrets if a compromise is suspected.

  4. Logging: Log webhook events and their processing status to troubleshoot issues effectively.

  5. Timeout: Set a reasonable timeout (e.g., 10 seconds) on your endpoint to avoid long delays.

  6. Testing: Use a staging environment to test webhooks before moving to production.

By following these guidelines, you can ensure a secure and reliable integration with our webhook system. If you have any questions or require further assistance, please don't hesitate to reach out.

 Contact Support:

pos-integrations@moniepoint.com

Related content

Push Payment Request (API Reference)
Push Payment Request (API Reference)
Read with this
Accept Payments with Moniepoint terminals - Getting started
Accept Payments with Moniepoint terminals - Getting started
Read with this
Odoo <> Moniepoint Terminal Configuration
Odoo <> Moniepoint Terminal Configuration
Read with this