MariFlow

Payments and subscriptions for Uganda

Get paid for every job, then every month.

Send a payment link on WhatsApp or sell from your own page. Customers pay by MTN MoMo, Airtel Money or card, and receipts, VAT and reminders are handled for you. When clients come back, turn them into monthly plans, with no code or through the API.

Hosted storefront

acme.mariflow.com
AcmePro plan

USh 212,400 / month, incl. VAT

MTN MoMoCard
+256 772 ••• 412
Subscribe

Headless API

POST /v1/subscriptions

customer_id: cus_42
price_id: price_pro
payment_method_id: pm_card

→ status: incomplete

One MariFlow engine

Same rules for both

incompleteactive
subscription.created → your appsigned

Two pathways

Start with zero code. Go headless when you're ready.

Both pathways run on the same engine, so switching from one to the other, or running both, never changes how your customers are billed.

For merchants

Hosted storefront

A branded, PCI-compliant checkout on your own subdomain, live the moment you sign up. Customers pay by card or mobile money.

For developers

Headless API

Build your own checkout and hear about every change through signed webhooks.

POST /v1/subscriptions

→ incomplete, client_secret for 3D Secure

→ webhook subscription.created

Money in and out

Get paid the way Uganda pays.

Links for one-off jobs, subscriptions for repeat clients, renewals customers approve on their phone, and payouts to MTN MoMo, Airtel Money or your bank.

One-off payments

A payment link for any job

Put a price on a service once and share its link anywhere, or send a one-time link for a quoted job. Customers pay by MTN MoMo, Airtel Money or card, and you both get a receipt.

Renewals

Mobile money that renews

Cards renew automatically. Where mobile money can't be collected automatically, customers get a payment link by SMS and email 3 days before each renewal and approve it on their phone. Missed it? A reminder with a fresh link goes out on each retry day, and only the newest link works, so nobody pays twice.

Self-service

Customers manage their own plan

Every receipt links to a page where customers switch between card and mobile money, cancel, and print invoices with your business details. No customer accounts or passwords to look after.

Payouts

A wallet you withdraw from

Payments land in your wallet after the 6% fee and become available after 3 days (7 in your first 30 days live). Withdraw to MTN MoMo, Airtel Money or a bank account, or turn on daily or weekly payouts. Payouts are free.

Receipts and VAT

Paperwork done for you

Every payment gets a receipt and a printable invoice with your business details. VAT is added only if you're VAT-registered.

Refunds

Full or partial refunds

Refund all or part of any payment from the dashboard or the API. The money goes back the way the customer paid, and your webhooks hear about it.

Lifecycle

A strict state machine you can reason about.

Every subscription moves through a fixed set of states, and each change sends your app a webhook. MariFlow rejects and logs any change that isn't allowed, so a canceled plan never quietly comes back to life.

  • incompletewhen Initial payment succeedsbecomes activesubscription.created
  • activewhen Renewal succeeds; next billing date setstaysactiveinvoice.paid
  • activewhen Renewal failsbecomes past_duesubscription.past_due
  • past_duewhen Dunning retry succeedsbecomes activesubscription.recovered
  • past_duewhen Retries exhaustedbecomes unpaidsubscription.unpaid
  • unpaidwhen Customer pays a payment link; a new period startsbecomes activesubscription.recovered
  • activewhen Customer or tenant cancelsbecomes canceledsubscription.canceled

Dunning

Failed renewals recover themselves

A failed renewal moves to past_due. On your retry days, cards are charged again and mobile money customers get a reminder with a fresh payment link. If none is paid, it ends unpaid or canceled, whichever you choose.

  1. 1Day 1
  2. 2Day 3
  3. 3Day 7
  4. unpaidor canceled

Concurrency

Race-condition safe

A cancel click mid-renewal? Distributed locks on each subscription_id run them one at a time, so a renewal and a cancellation never collide.

Reliability

The hard parts of billing, already handled.

Duplicate clicks, flaky networks, currency swings. MariFlow is built around the failures that cost you revenue.

Retries

Never a double charge

If a request is sent twice, MariFlow returns the original result for up to 24 hours instead of charging again.

Payments

No payment provider to set up

MariFlow handles payment processing behind one integration, so you never connect, maintain or switch a provider yourself.

Pricing

Flat or per seat, with trials

Flat-rate or per-seat pricing with free trials and discount codes (usage-based billing is coming), priced in Uganda shillings with VAT worked out for you. More East African currencies follow.

Isolation

Your data stays yours

Each merchant's records are walled off at the database, and every change is written to an audit log you can't edit.

Developers

An API that holds up on the worst network day.

Authenticate with a secret key, send an idempotency key with every write, and verify each webhook's signature. Products and prices are separate, so one plan can bill monthly, annually or per seat.

  • A sandbox from day one; live keys once your business is verified
  • Webhooks dispatched within 2 seconds of a subscription going active
  • Failed deliveries retried at 1m, 5m, 30m, 2h and 24h, then held for replay
  • Changes that break the lifecycle rejected with a 422
subscribe.ts
import { MariFlow } from "@mariflow/node";
import { randomUUID } from "node:crypto";

const mariflow = new MariFlow(process.env.MARIFLOW_SECRET_KEY);

const sub = await mariflow.subscriptions.create(
  {
    customer_id: "cus_42",
    price_id: "price_pro_monthly",
    payment_method_id: "pm_card",
  },
  { idempotencyKey: randomUUID() },
);

// status: "incomplete" — hand client_secret to the
// browser to finish 3D Secure if the card issuer asks
return { clientSecret: sub.client_secret };

Pricing

One price. You pay when you get paid.

MariFlow takes a share of each successful payment, whether it comes through your storefront or the API.

6%

of each successful payment

  • No setup or monthly fee
  • The sandbox is free: no real money moves there
  • The same rate for one-off payments and subscriptions
  • The same rate for storefronts and the API
  • Free payouts to mobile money or your bank

When a customer pays USh 212,400 (USh 180,000 plus 18% VAT), MariFlow keeps USh 12,744 and USh 199,656 goes to your wallet.

Get started

Pick a pathway. Add the other whenever you like.

Both run on the same engine, so your plans and customers carry over.