API Reference
Outbound Webhooks
The Orchestrator dispatches signed webhook events to your configured destination URL whenever a split is processed.
Event Types
| Event | Description |
|---|---|
| split.processed | Fired when a split has been fully processed (all disbursements completed) |
| split.partial_failure | Fired when some disbursements succeeded and others failed |
| split.failed | Fired when the entire split processing failed |
Webhook Payload
Every processed split triggers a POST request to your registered webhook destination with the following JSON body:
{
"event": "split.processed",
"merchantId": "merchant_id",
"transactionId": "txn_id",
"externalId": "moolre_txn_ref",
"amount": 10000,
"currency": "GHS",
"splits": [
{
"recipientType": "MOMO",
"destination": "233501234567",
"amount": 7000
},
{
"recipientType": "BANK",
"destination": "1234567890",
"bankCode": "GH120100",
"amount": 3000
}
],
"feeBreakdown": {
"orchestrationFeePesewas": 150,
"moolreCollectionFeePesewas": 200,
"networkFeePesewas": 50,
"moolreTransferFeePesewas": 100,
"totalFeesPesewas": 500
},
"processedAt": 1715000000000
}Fields
| Field | Type | Description |
|---|---|---|
| event | string | Event type identifier (e.g. split.processed) |
| merchantId | string | The merchant this event belongs to |
| transactionId | string | Internal Orchestrator transaction ID |
| externalId | string | Moolre transaction reference |
| amount | integer | Total transaction amount in pesewas |
| splits | array | Individual disbursements with recipient, amount, and destination |
| feeBreakdown | object | Detailed fee breakdown in pesewas |
| processedAt | integer | Unix timestamp (ms) when the split was processed |
Security
Although the Moolre API returns a secret UUID when creating or updating wallets, Moolre does not currently document or implement signature headers for inbound webhooks sent to the Orchestrator. Therefore, inbound webhooks are processed unauthenticated (fail-open) and verified by matching the transaction ID and amount against database records.
However, outbound callbacks dispatched by the Orchestrator to your integration endpoints are signed using SHA256 HMAC (hashed using your workspace webhook secret and sent in the X-Signature header) to ensure authenticity.
const crypto = require('crypto')
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)
}Retry Policy
If your endpoint returns a non-2xx status, the Orchestrator retries with exponential backoff:
- 3 retry attempts with 10s, 60s, and 300s delays
- Idempotency key in
Idempotency-Keyheader - Failed deliveries logged for manual inspection