← Back to blog
insights15 min read

Why We Built DGateway: The Payment Problem in East Africa

The story behind DGateway — why the fragmented payment landscape in East Africa demanded a unified API and how we set out to fix it.

Why We Built DGateway: The Payment Problem in East Africa

Why We Built DGateway: The Payment Problem in East Africa

DGateway is a unified payment and commerce platform for Africa. It lets developers and businesses accept mobile money (MTN, Airtel) and card payments through a single API, eliminating the need to integrate with each provider separately.

Every product has an origin story. For DGateway, ours starts with frustration — the kind of frustration that every developer in East Africa has felt when trying to accept payments online. We did not set out to build a payment gateway. We set out to build products. But every time we tried, we hit the same wall: payments.

This is the story of why that wall exists, how we decided to tear it down, and what we learned building the infrastructure that East African developers actually need.


The Fragmented Landscape

East Africa is one of the most dynamic mobile money markets in the world. MTN Mobile Money dominates in Uganda. M-Pesa leads in Kenya and Tanzania. Airtel Money has a strong presence across multiple countries. Then there are card payments through Visa and Mastercard, bank transfers, and a growing number of fintech wallets.

For consumers, this diversity is great. For developers and businesses trying to accept payments, it is a nightmare.

Each provider has its own API. Its own authentication mechanism. Its own webhook format. Its own error codes. Its own sandbox environment. Its own documentation — often incomplete, sometimes outdated, occasionally contradictory.

Here is a snapshot of what you face when integrating directly with providers in East Africa:

ProviderAuth MethodCallback FormatSandbox AvailableDocumentation QualityCurrencies
Iotec (MTN/Airtel UG)OAuth2 (Client Credentials)Custom JSON POSTYes (unreliable)ModerateUGX
RelworxBasic AuthJSON POSTYesGoodUGX, KES, TZS, RWF
StripeBearer Token (API Key)Signed JSON POSTYes (excellent)ExcellentUSD, EUR, GBP, KES, UGX
M-Pesa (Safaricom)OAuth2 + PasskeyCustom XML/JSONYes (slow)ModerateKES

If you want to accept MTN Mobile Money in Uganda and M-Pesa in Kenya, you are not integrating one payment system. You are integrating two completely separate systems with different architectures, different flows, and different failure modes.


The Developer's Dilemma: A Real Example

We have been there ourselves. Building products for the East African market meant spending weeks — sometimes months — just on payment integration. And that was before handling edge cases.

The Pain of Direct Iotec Integration

Let us show you what integrating with Iotec (the provider behind MTN Mobile Money and Airtel Money in Uganda) looks like without DGateway. First, you need to obtain an OAuth2 access token:

// Step 1: Get an OAuth2 token from Iotec
async function getIotecToken(): Promise<string> {
  const response = await fetch("https://auth.iotec.io/oauth2/token", {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
      grant_type: "client_credentials",
      client_id: process.env.IOTEC_CLIENT_ID!,
      client_secret: process.env.IOTEC_CLIENT_SECRET!,
      scope: "payments",
    }),
  });
 
  if (!response.ok) {
    throw new Error(`Iotec auth failed: ${response.status}`);
  }
 
  const data = await response.json();
  return data.access_token;
  // Token expires in ~1 hour — you need to cache and refresh it
}
 
// Step 2: Initiate a collection
async function collectWithIotec(phone: string, amount: number) {
  const token = await getIotecToken();
 
  const response = await fetch("https://api.iotec.io/v1/payments/collect", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      msisdn: phone,
      amount: amount,
      narrative: "Payment for order",
      reference: generateReference(),
      callback_url: process.env.IOTEC_CALLBACK_URL,
    }),
  });
 
  // Handle Iotec-specific error codes
  // Handle token expiry mid-request
  // Handle timeout (Iotec can take 30+ seconds)
  // Handle duplicate reference errors
  // Parse Iotec-specific response format
  return response.json();
}
 
// Step 3: Handle Iotec's callback (different format from every other provider)
app.post("/callbacks/iotec", (req, res) => {
  const { status, transactionId, msisdn, amount } = req.body;
 
  // Iotec uses different status strings than other providers
  if (status === "SUCCESSFUL") {
    // Map to your internal status
  } else if (status === "FAILED") {
    // Different error codes than Relworx, Stripe, etc.
  } else if (status === "PENDING") {
    // Transaction still processing — need to poll or wait
  }
 
  res.status(200).send("OK");
});

Now multiply that by every provider you need to support. Airtel has a different auth flow. Relworx uses Basic Auth with a completely different request format. Stripe is well-documented but designed for cards, not mobile money.

The Same Thing with DGateway: One API Call

// That's it. One call. Any provider. Any currency.
const response = await fetch("https://api.dgateway.io/v1/collections", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.DGATEWAY_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    amount: 50000,
    currency: "UGX",
    phone_number: "256771234567",
    provider: "mtn", // or "airtel", or omit for auto-detection
    description: "Order #1234",
    callback_url: "https://your-app.com/webhooks/dgateway",
    metadata: { order_id: "order_1234" },
  }),
});
 
const transaction = await response.json();
// { id: "txn_abc123", status: "pending", amount: 50000, ... }

No OAuth token management. No provider-specific error handling. No format translation. One API key, one request format, one webhook format — regardless of whether the customer pays with MTN, Airtel, or a Visa card.


The Questions That Haunted Us

What happens when a mobile money transaction times out? What if the callback URL never fires? How do you reconcile payments when the provider's API returns a success but the money never arrives? How do you handle the differences between a push-based flow (where the customer confirms on their phone) and a redirect-based flow?

Every developer in the region has war stories:

  • Failed transactions with no clear error message — The provider returns a generic "failed" status with no reason code.
  • Webhooks that arrive hours late — Or never arrive at all, leaving transactions in limbo.
  • Test environments that do not behave like production — You build and test for months, then everything breaks when you go live.
  • Documentation that says one thing while the API does another — Field names in the docs do not match the actual response.
  • OAuth tokens that expire mid-transaction — Your collection request fails because the token you cached 55 minutes ago just expired.
  • Duplicate charge scenarios — The provider charges the customer but your callback fails, so you retry and the customer gets charged twice.

The result is predictable: developers spend more time fighting payment infrastructure than building their actual product.


Why Not Just Use Stripe?

This is the question we heard most often. And the answer is simple: Stripe does not solve the mobile money problem.

Stripe is an excellent product for card-based payments in markets where credit and debit cards are the primary payment method. But in East Africa, mobile money accounts for the vast majority of digital transactions. In Uganda alone, mobile money transaction volumes exceed traditional banking volumes by a wide margin.

Here are the numbers that matter:

MetricMobile Money (Uganda)Bank Cards (Uganda)
Registered accounts30M+~5M
Monthly active users18M+~2M
Transaction volume (annual)UGX 100T+UGX 15T
Agent network200,000+ points~1,000 branches
Smartphone requiredNo (USSD works)Yes (for online)

You cannot build for East Africa and ignore mobile money. And you cannot rely on a payment gateway that treats mobile money as an afterthought — or does not support it at all.


What About Flutterwave and Paystack?

This is the next question people ask. Both are excellent companies that have done a lot to advance payments in Africa. But there are real differences in approach and focus.

FeatureDGatewayFlutterwavePaystack
Primary focusEast Africa (UG, KE, TZ, RW)West Africa (NG) + Pan-AfricanWest Africa (NG, GH)
Mobile Money depthDeep (MTN, Airtel, M-Pesa native)Available but secondaryLimited
UGX supportNative, first-classAvailableLimited
Digital product storeBuilt-inNoNo
Course platformBuilt-inNoNo
Payment linksBuilt-in with digital deliveryAvailableAvailable
WordPress pluginYes (WooCommerce + standalone)YesYes
Smart routingAuto provider selection + failoverYesNo
Self-hosted optionComing soonNoNo
Pricing transparencyPublished, no hidden feesPublishedPublished
Settlement to mobile moneyYes (disbursements)YesLimited

DGateway is purpose-built for the East African market. We are not a West African gateway trying to expand eastward. The providers we integrate with, the currencies we optimize for, the edge cases we handle — they all come from building in this market, for this market.


The Vision for DGateway

We built DGateway to be the payment infrastructure layer that East African developers and businesses actually need. The core idea is straightforward:

One API. Every payment method. Every market.

Instead of integrating separately with MTN, Airtel, M-Pesa, Stripe, and whatever comes next, you integrate once with DGateway. We handle the complexity of talking to each provider, normalizing their responses, managing retries, and delivering consistent webhooks.

When you make a collection request through DGateway, you specify the amount, the currency, and the customer's payment method. DGateway figures out the best provider, initiates the transaction, monitors its progress, and notifies you when it completes. The response format is the same whether the customer paid with MTN Mobile Money in Uganda or a Visa card in Kenya.


Technical Architecture Decisions

Building DGateway meant making deliberate architectural choices. Here are the ones that matter most:

Go Backend for Performance

We chose Go for the backend. Payment processing demands low latency, high concurrency, and reliability. Go gives us all three. A single DGateway API server handles thousands of concurrent connections with minimal memory usage. Compare that to Node.js or Python, where you would need process managers, worker pools, and significantly more infrastructure to achieve the same throughput.

// DGateway's provider interface — every provider implements this
type PaymentProvider interface {
    Collect(ctx context.Context, req CollectRequest) (*Transaction, error)
    Disburse(ctx context.Context, req DisburseRequest) (*Transaction, error)
    CheckStatus(ctx context.Context, txnID string) (*Transaction, error)
    ValidateCallback(ctx context.Context, payload []byte) (*CallbackResult, error)
}

Smart Routing with Automatic Failover

DGateway does not just forward requests to providers. It actively monitors provider health and routes transactions intelligently:

  1. Health checks — Daily automated health checks on every provider line (Iotec MTN, Iotec Airtel, Relworx, Stripe). If a line goes down, we detect it and notify affected app owners.
  2. Priority routing — Each app can set provider priorities per currency. If your preferred provider for UGX collections is Iotec, DGateway uses Iotec first.
  3. Automatic failover — If the primary provider is unhealthy or returns an error, DGateway automatically tries the next available provider. The developer does not need to handle this.

AES-256-GCM Credential Encryption

Every provider credential stored in DGateway is encrypted at rest using AES-256-GCM. Your Iotec client secret, your Relworx API key, your Stripe secret key — they are never stored in plaintext. Even if our database were compromised, your credentials would be unreadable without the encryption key.

Redis-Backed Background Jobs

Payment processing is inherently asynchronous. A customer initiates a payment, confirms on their phone, and the provider notifies us minutes later. DGateway uses Redis-backed background jobs (via Asynq) to handle webhook delivery, retry logic, health checks, and scheduled tasks without blocking the main API.


The Timeline: What We Have Shipped

DGateway did not arrive fully formed. We built it piece by piece, driven by what our users needed:

PhaseFeaturesImpact
v1.0Core API (collections, disbursements), MTN + Airtel via IotecDevelopers could accept mobile money with one API
v1.5Webhook system, Stripe integration, multi-currencyCard payments + international customers
v2.0Payment links, digital product store, dashboardNon-technical users could sell without code
v2.5Course platform, event ticketing, templatesFull commerce platform
v3.0Organizations, affiliates, AI assistant, landing pages, coupons, customer portalEnterprise features + creator economy tools

Each phase was driven by real feedback from real users in Uganda, Kenya, and across East Africa.


Beyond the API

But we did not stop at the API. We realized that many businesses — especially small businesses, creators, and entrepreneurs — do not have developers on staff. They need to accept payments without writing code.

That is why DGateway includes:

  • Payment links — Generate a shareable URL that accepts MTN, Airtel, or card payments. Share on WhatsApp, Twitter, or email.
  • Digital product store — Upload an ebook, template, or software package. Set a price. Get a product page with checkout built in.
  • Course platform — Create structured courses with video lessons, progress tracking, and student enrollment. Accept payment in UGX or any supported currency.
  • Event ticketing — Sell tickets with unique QR codes for door check-in. Support VIP, Regular, and Free RSVP tiers.
  • WordPress plugin — Install our WooCommerce plugin and accept mobile money payments on your WordPress site in minutes.
  • Organization management — For associations, churches, and clubs that need member management, contribution tracking, and savings groups.

For developers, the API is the foundation. For everyone else, the no-code tools built on top of that API are the entry point.


What We Believe

We believe that accepting payments should not be the hardest part of building a business in East Africa. It should be the easiest.

We believe that a developer in Kampala should have access to payment infrastructure that is just as reliable, just as well-documented, and just as developer-friendly as what a developer in San Francisco takes for granted.

We believe that the mobile money ecosystem deserves a purpose-built gateway — not a bolted-on feature from a company that does not understand the market.

We believe that a creator in Jinja selling an ebook should not need to hire a developer to accept UGX 10,000 payments via MTN Mobile Money.

We believe that an association in Mbarara should be able to collect membership fees from 500 members without spreadsheets and manual bank reconciliation.


Where We Are Today

DGateway now processes transactions across multiple East African markets. We support MTN Mobile Money, Airtel Money, card payments through Stripe, and more providers are being added regularly. Our API handles smart routing, automatic failover, real-time health monitoring, and comprehensive audit logging.

Here is what the platform looks like in numbers:

  • 3 payment providers integrated (Iotec, Relworx, Stripe)
  • 5 currencies supported natively (UGX, KES, TZS, RWF, USD)
  • 30+ API endpoints for collections, disbursements, subscriptions, and more
  • 6 product types in the digital store (generic, ebook, software, audio, graphics, video)
  • Full course platform with HLS video streaming and discussion forums
  • Event ticketing with QR code check-in
  • Organization tools for associations and savings groups
  • Affiliate program support built into every app
  • AI-powered content assistant for product descriptions and marketing copy

Thousands of businesses use DGateway to power their checkout flows, subscription billing, and digital product sales. And we are just getting started.


Getting Started

If you are a developer, the fastest path is the API:

# Create your first collection in under 60 seconds
curl -X POST https://api.dgateway.io/v1/collections \
  -H "Authorization: Bearer dg_test_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "currency": "UGX",
    "phone_number": "256771234567",
    "provider": "mtn",
    "description": "My first DGateway payment"
  }'

If you are a creator or business owner, sign up at dgateway.io, create a product or payment link, and start selling in minutes.


What is Next

The payment problem in East Africa is not fully solved. But with every integration we simplify, every failed transaction we prevent, and every developer hour we save, we are getting closer.

Here is what is on our roadmap:

  • More providers — Expanding to cover more mobile money networks and bank transfer options across East Africa.
  • Improved analytics — Deeper insights into transaction patterns, conversion rates, and revenue trends.
  • SDKs — Official client libraries for Node.js, Python, Go, PHP, and Flutter.
  • Self-hosted option — For enterprises that need to run DGateway on their own infrastructure.
  • Interoperability — Cross-provider mobile money transfers and settlements.

If you have ever felt the pain of payment integration in East Africa, DGateway was built for you. We know, because we felt it too.