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.completed | Fired when a split reaches a terminal state. The payloadstatus field differentiates between COMPLETED, PARTIAL_FAILURE, and FAILED. |
Webhook Payload
Every processed split triggers a POST request to your registered webhook destination with the following JSON body:
{
"transactionId": "txn_id",
"externalId": "order_12345",
"routingRuleId": "rule_id",
"amount": 10000,
"currency": "GHS",
"status": "COMPLETED",
"orchestratorFeePesewas": 150,
"parentMerchantId": "parent_merchant_id",
"environment": "sandbox",
"disbursements": [
{
"recipientType": "MOMO",
"destination": "233501234567",
"amount": 7000,
"status": "SUCCESSFUL",
"moolreDisbursementId": "moolre_ref_1"
},
{
"recipientType": "BANK",
"destination": "1234567890",
"amount": 3000,
"status": "SUCCESSFUL",
"moolreDisbursementId": "moolre_ref_2"
}
]
}Fields
| Field | Type | Description |
|---|---|---|
| transactionId | string | Internal Orchestrator transaction ID |
| externalId | string (optional) | External reference passed through from the split request |
| routingRuleId | string | The routing rule that was applied to this transaction |
| amount | integer | Total transaction amount in pesewas |
| currency | string | Currency code (e.g. "GHS") |
| status | string | Transaction status: COMPLETED, PARTIAL_FAILURE, or FAILED |
| orchestratorFeePesewas | integer | Platform orchestration fee deducted in pesewas |
| parentMerchantId | string (optional) | Parent merchant ID if the transaction was processed under a sub-account |
| branch | string (optional) | "dev" when the inbound payment link included custom_metadata[branch]=dev. Omitted for production transactions. Use this to route callbacks to a dev endpoint without requiring a second wallet. |
| environment | string | Environment the transaction was processed in ("sandbox" | "live") |
| disbursements | array | Individual disbursements with recipient, amount, status, and Moolre reference |
Dev / Prod Callback Branching
Moolre allows only one callback URL per wallet. To test changes without disrupting production callbacks, embed custom_metadata[branch]=devin your payment link.
When a transaction arrives with branch=dev and the merchant has a Dev Callback URL configured (see Merchant Settings → Dev Callback URL), the outbound webhook is dispatched to that dev endpoint instead of the platform callback URL. Transactions without a branch or with branch=prodalways use the platform callback URL.
This lets you maintain separate dev and production callback destinations from a single wallet. No second wallet or account is needed.
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.
Outbound callbacks are dispatched via direct HTTP POST to your configured callback URL (set during provisioning). Signatures are not currently applied — ensure your callback endpoint validates the payload internally or restrict access by IP.
We recommend verifying callbacks by storing thetransactionIdat request time and checking it matches the callback value. For additional security, restrict your endpoint to known IP ranges or implement a shared secret via a custom header check.
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

