Mojo Money × Mojo Connect
System overview · for a non-technical read

How Mojo Connect works, end to end

Mojo Connect adds private calls, private chat and in-chat money to Mojo Money — running on Mojo's own servers, with no Google or Firebase in the loop. Here's the whole picture, and exactly what a new user does to get in.

Self-hosted · sip.mojomoney.africa No Firebase / FCM LIME end-to-end chat ZRTP encrypted calls TLS-only signalling
Updated 26 Jul 2026 · reflects the committed build
The two apps

One identity, two jobs

Think of them as a wallet and a private phone line that share the same account. You sign up once; Mojo Connect rides on your Mojo Money identity.

Mojo Money

The wallet

Your account, balance and payments — the money side. It owns your identity and sets your transfer limits, and it's what provisions your secure line behind the scenes.

Mojo Connect

The private line

Encrypted calls, encrypted chat, and sending money right inside a conversation. It signs in with your Mojo account and turns on end-to-end security.

The whole system at a glance

What talks to what

Your phone runs the app; everything it connects to is a server Mojo runs itself. Nothing routes through a third-party push or identity provider.

%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui, sans-serif','fontSize':'13px','primaryColor':'#ede9fe','primaryTextColor':'#2e1065','primaryBorderColor':'#7c3aed','lineColor':'#7c5bd0','clusterBkg':'#faf8ff','clusterBorder':'#c9b8ef'}}}%%
graph TB
  classDef client fill:#ede9fe,stroke:#7c3aed,color:#2e1065;
  classDef server fill:#dcfce7,stroke:#15803d,color:#0f3d24;
  classDef ext fill:#e9e7ef,stroke:#6b7280,color:#1f2430;

  subgraph PHONE["📱 Your phone — Mojo Connect app"]
    direction TB
    UI["Chats · Calls · Wallet
(app screens)"] LM["Secure engine
liblinphone 5.5.10"] FGS["Always-on line
background service"] PROBE["Push listener"] end subgraph CLOUD["☁ sip.mojomoney.africa — Mojo's own servers"] direction TB APACHE["Apache
TLS · reverse proxy"] FLEX["Flexisip
call routing · group chat"] LIME["LIME key server
end-to-end keys"] RELAY["Mojo push relay
(no Firebase)"] end MM["🏦 Mojo Money
identity + wallet"] UI --> LM LM -.-> FGS FGS -.-> PROBE LM ==>|"TLS · register, call, chat"| FLEX LM ==>|"fetch encryption keys"| LIME FLEX ==>|"message waiting"| RELAY RELAY ==>|"wake the phone"| PROBE MM -->|"provisions the secure account"| FLEX class UI,LM,FGS,PROBE client; class FLEX,LIME,RELAY,APACHE server; class MM ext;
Solid arrows = live encrypted connections · dotted = kept alive on the phone
On your phone Mojo's self-hosted servers Mojo Money account
Flow · a call

How a call rings a locked phone

Calls ride on the always-on secure line, so they reach you even when the screen is off. This is fully working today.

  1. Alice taps Call

    The app opens an encrypted call invite and sends it over a TLS connection to Flexisip.

  2. Flexisip finds Bob

    Bob's phone keeps its secure line registered in the background, so the invite is delivered straight to it — locked or not.

  3. The phone wakes

    A full-screen "Incoming secure call" alert lights up over the lock screen with Accept / Decline.

  4. Encrypted end to end

    On answer, audio is protected with ZRTP. Both people see a short verification code (SAS) to confirm no one is listening in.

Verified on two phones

An incoming call reliably wakes a locked device and rings over the keyguard.

Flow · a message

How a message reaches a closed phone

Chat is trickier than calls: when the app is closed the phone freezes its chat connection, so we use Mojo's own push relay to tap you on the shoulder — no Google in the middle.

  1. Alice sends

    The text is end-to-end encrypted with LIME and sent through Flexisip's private group-chat room for Alice & Bob.

  2. Bob's phone is closed

    If the app is open it arrives instantly. If it's backgrounded or locked, the phone has frozen the app's connection, so the message parks safely on Mojo's server.

  3. Flexisip fires a push

    The server tells Mojo's own push relay "a message is waiting for Bob" — no Firebase, no third party.

  4. The phone is nudged

    The relay pings the small listener inside Bob's app, which posts "You have a new secure message" on the lock screen in about two seconds.

  5. Bob opens it

    Tapping the alert opens the app, which pulls the parked message and decrypts it — Bob reads it with the real sender and text.

Known limit — deliberate

Showing the decrypted words on the lock screen without opening the app needs a system-level push channel (Google's FCM, or a self-hosted UnifiedPush). Doing it inside the app crashes on modern Android. So today Bob is reliably notified, and reads the message on tap — all on Mojo's own infrastructure. Full lock-screen previews are a clear future step.

Getting started · your options

"I don't have an account — what do I do?"

Signing up is two steps: pick how you identify yourself, then link the secure line. You choose one of three ways to sign up — and you can start messaging and calling on any of them.

%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui, sans-serif','fontSize':'13px','primaryColor':'#ede9fe','primaryTextColor':'#2e1065','primaryBorderColor':'#7c3aed','lineColor':'#7c5bd0'}}}%%
graph TD
  classDef start fill:#ede9fe,stroke:#7c3aed,color:#2e1065;
  classDef q fill:#ffffff,stroke:#7c3aed,color:#2e1065;
  classDef path fill:#eef0f4,stroke:#6b7280,color:#1f2430;
  classDef good fill:#dcfce7,stroke:#15803d,color:#0f3d24;
  classDef warn fill:#fdf0d6,stroke:#b45309,color:#6b3608;

  A["Open the app —
no account yet"]:::start Q{"How do you want
to sign up?"}:::q P["📞 Phone number"]:::path E["✉ Email address"]:::path U["🏷 Username only
subscriber · R120/yr once-off"]:::path O["Enter the 6-digit code"]:::path V["Verified —
full transfer limits"]:::good L["Low transfer limits
until you add & verify
a phone or email"]:::warn S["Link secure messaging —
sign in, E2E calls & chat turn on"]:::path H["You're in —
Chats · Calls · Wallet"]:::good A --> Q Q --> P --> O Q --> E --> O Q --> U --> L O -->|correct| V O -->|skip for now| L V --> S L --> S S --> H
Messaging and calls work on every path — verification only lifts your money limits
Sign-up optionWhat you giveCostTransfer limitsBest for
PhonePhone number + a one-time codeFreeFull, once verifiedMost people
EmailEmail address + a one-time codeFreeFull, once verifiedNo SIM, or email-first
UsernameJust a handle — no phone or emailR120/yrLow, until you add a phone/emailPrivacy-first sign-up

Then: the last step is "Link secure messaging" — you sign in with your Mojo Connect account (you@sip.mojomoney.africa + password), the phone registers to the server over TLS, and you land on the home screen with encrypted calls and chat switched on. Skipping verification is fine — you can still chat and call; you just carry a low transaction cap until you verify a phone or email.

Security & who runs it

Built on Mojo's own stack

No part of a conversation is readable by the servers in between, and no part depends on Google, Apple or Firebase to be delivered.

Servers
sip.mojomoney.africa · 154.65.101.121 — self-hosted, single host
Chat security
LIME (X3DH, c25519) — end-to-end encrypted, keys from Mojo's own LIME server
Call security
ZRTP with a spoken/shown code (SAS) to confirm no eavesdropper
Signalling
TLS only — no cleartext, enforced in code as well as config
Call routing & chat
Flexisip (SIP proxy, conference & group-chat, reg-event)
Notifications
Mojo's own push relay behind Apache — no Firebase / FCM
Engine
liblinphone 5.5.10 inside the Android app