Webhooks Guide

Set up webhooks to receive real-time payment notifications

API Base URL

All webhook API requests should be made to the following base URL:

https://wallet.wearemarz.com/api/v1

Overview

Webhooks are HTTP callbacks that notify your application when events occur, such as payment status changes. This allows for real-time updates without polling the API.

Setting Up Webhooks

1

Go to Webhooks in your dashboard

2

Click "Create Webhook" and enter your endpoint URL

3

Select the events you want to receive notifications for

4

Test your webhook to ensure it's working correctly

Callback Flow

Understanding how callbacks work in our system and when you'll receive notifications.

Complete Transaction Flow

  1. Business creates collection request (with optional callback URL)
  2. MTN/Airtel processes payment
  3. MTN/Airtel sends callback to our system
  4. Our system processes the callback
  5. IF payment is successful:
  6. Transaction status updated to 'completed'
  7. Business balance updated
  8. Callback sent to business (from completeTransaction)
  9. All processing complete

Callback Priority System

  • Custom Callback URL: If provided during collection, takes priority
  • Webhooks: If no custom callback URL, webhooks are used as fallback

When Callbacks Are Sent

Callbacks are sent for ALL final transaction statuses:

  • Completed: Payment successful, balance updated
  • Failed: Payment failed, no balance change
  • Cancelled: Payment cancelled, no balance change
  • All internal processing complete

Callbacks are NOT sent for: pending, processing, or any intermediate statuses.

Callback Payload Structure

The structure of the data sent to your callback URL or webhook endpoint. The event_type and transaction status will vary based on the transaction outcome.

Successful Payment Payload

{
  "event_type": "collection.completed",
  "transaction": {
    "uuid": "transaction-uuid",
    "reference": "transaction-reference",
    "status": "completed",
    "amount": {
      "formatted": "10,000.00",
      "raw": 10000,
      "currency": "UGX"
    },
    "provider": "mtn",
    "phone_number": "+256712345678",
    "description": "Payment description",
    "created_at": "2025-08-20T15:18:48.000000Z",
    "updated_at": "2025-08-20T15:18:48.000000Z"
  },
  "collection": {
    "provider": "mtn",
    "phone_number": "+256712345678",
    "amount": {
      "formatted": "10,000.00",
      "raw": 10000,
      "currency": "UGX"
    },
    "mode": "mtnuganda",
    "provider_reference": "mtn-transaction-id"
  },
  "business": {
    "uuid": "business-uuid",
    "name": "Business Name"
  },
  "metadata": {
    "sandbox_mode": false,
    "environment": "production",
    "timestamp": "2025-08-20T15:18:48.000000Z"
  }
}

Failed Payment Payload

{
  "event_type": "collection.failed",
  "transaction": {
    "uuid": "transaction-uuid",
    "reference": "transaction-reference",
    "status": "failed",
    "amount": {
      "formatted": "10,000.00",
      "raw": 10000,
      "currency": "UGX"
    },
    "provider": "mtn",
    "phone_number": "+256712345678",
    "description": "Payment description",
    "created_at": "2025-08-20T15:18:48.000000Z",
    "updated_at": "2025-08-20T15:18:48.000000Z"
  },
  "collection": {
    "provider": "mtn",
    "phone_number": "+256712345678",
    "amount": {
      "formatted": "10,000.00",
      "raw": 10000,
      "currency": "UGX"
    },
    "mode": "mtnuganda",
    "provider_reference": "mtn-transaction-id"
  },
  "business": {
    "uuid": "business-uuid",
    "name": "Business Name"
  },
  "metadata": {
    "sandbox_mode": false,
    "environment": "production",
    "timestamp": "2025-08-20T15:18:48.000000Z"
  }
}

Status Mapping

How payment provider statuses are mapped to our internal statuses.

MTN Status Mapping

successful/completed/success → completed
failed/rejected/failure → failed
pending/timeout/pending_confirmation → pending
expired → failed

Airtel Status Mapping

TS (Transaction Successful) → completed
TF (Transaction Failed) → failed
TP (Transaction Pending) → pending

Best Practices

Always respond with HTTP 200 to acknowledge receipt of the callback

Implement idempotency to handle duplicate callbacks

Use the transaction reference to track and verify payments

Set up proper error handling and logging for callback processing