One API. Mobile Money, Cards, and the Flot App — with RSA-signed requests and real-time webhooks.
$ curl -X POST \
https://api.flotme.io/merchants/private/v1/payment-links \
-H "Content-Type: application/json" \
-H "X-Flot-Merchant-Signature: <sig>" \
-d '{
"merchantId": "your-id",
"type": "momo",
"payload": { "orderId": "ord-1", "amount": "5000", "currency": "SLE" }
'
const res = await fetch(
'https://api.flotme.io/merchants/private/v1/payment-links',
{ method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Flot-Merchant-Signature': signature
},
body: JSON.stringify({ merchantId, type: 'momo', payload }) })
const { data } = await res.json()
// data.link, data.code ← payment link + USSD
import requests
res = requests.post(
"https://api.flotme.io/merchants/private/v1/payment-links",
headers={"X-Flot-Merchant-Signature": signature},
json={
"merchantId": "your-id",
"type": "momo",
"payload": {"orderId": "ord-1", "amount": "5000", "currency": "SLE"}
}
)
data = res.json()["data"]
{ "data": { "link": "https://pay.flotme.io/...", "code": "*175*123#" } }
Overview
Every transaction follows a simple, consistent flow. Flot does not manage your orders — your system remains the source of truth.
Generate and store an order in your system with a unique identifier.
Call the Flot API to generate a payment link or USSD code.
The customer pays via Mobile Money, Card, or the Flot app.
Flot sends a real-time webhook notification to your backend.
Mark the order as completed or keep it pending based on the result.
Quick Start
Register your account, complete KYC, and configure your merchant profile. You'll need to provide the following before receiving your Merchant ID.
Merchant ID is required in every API request body.
Setup Checklist
Flot uses RSA-4096 for request signing. Generate a key pair using OpenSSL.
Server only. Never expose.
Share with Flot during setup.
$ openssl genpkey -algorithm RSA \
-out private_key.pem \
-pkeyopt rsa_keygen_bits:4096
$ openssl rsa -pubout \
-in private_key.pem \
-out public_key.pem
// ✓ private_key.pem → server only
// ✓ public_key.pem → share with Flot
Use the payment link endpoint to initiate a transaction.
/merchants/private/v1/payment-links
Payment Types
momoReturns a USSD codecardReturns a hosted payment linkin-appOpens Flot app payment flow{
"merchantId": "your-merchant-id",
"type": "momo",
"payload": {
"orderId": "order-123",
"amount": "100",
"currency": "SLE"
}
}
{
"data": {
"link": "https://...",
"code": "*175*123#"
}
}
All requests must include the header X-Flot-Merchant-Signature. The signature is generated by:
SHA512
Using your private key
RSA_PKCS1_PSS_PADDING
Set as the header value
const crypto = require('crypto')
const fs = require('fs')
const privateKey = fs.readFileSync('private_key.pem', 'utf8')
const requestBody = {
merchantId: "your-id",
type: "in-app",
payload: {
orderId: "order-123",
currency: "SLE",
amount: "10"
}
}
const signer = crypto.createSign('RSA-SHA512')
signer.update(JSON.stringify(requestBody))
const signature = signer.sign({
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
}, 'base64')
Webhooks
Flot sends one POST request to your webhook endpoint when payment state changes. This is where order state becomes final.
{
"orderId": "ord-1",
"flotRequestId": "123456",
"status": "completed"
}
app.post('/webhook', (req, res) => {
const { orderId, status } = req.body
if (status === 'completed') {
db.markOrderPaid(orderId) // idempotent
}
res.sendStatus(200)
})
Best Practices
Never mark orders as paid before webhook confirmation. Payment state is only final on webhook receipt.
Store all outgoing requests and incoming webhooks. Essential for debugging and reconciliation.
Design your webhook handler so the same event processed twice produces the same outcome.
Your order lifecycle is yours. Flot handles payment state only — keep the two separate in your data model.
Store it in an environment variable or secrets manager. Never commit it or send it over the wire.
Flot provides a staging environment. Validate every flow — success and failure — before switching to production.
Testing Your Integration
Flot provides a staging environment for testing. In this phase, you should:
Go Live
Before switching to production, make sure every part of your integration has been thoroughly verified in the staging environment. Follow these steps in order:
Ready for production access? Get in touch with the Flot team.
Use Cases
Start building
Mobile Money. Cards. In-app. One integration — built for Africa, ready for the world.