Business Developers

Build Payments
Into Your
Product.

One API. Mobile Money, Cards, and the Flot App — with RSA-signed requests and real-time webhooks.

99.9%Uptime SLA
<200msAvg. Latency
3Payment Types
RSA-4096Auth Standard

$ 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"]

● 200 OK 118ms

{ "data": { "link": "https://pay.flotme.io/...", "code": "*175*123#" } }

Overview

How the API works.

Every transaction follows a simple, consistent flow. Flot does not manage your orders — your system remains the source of truth.

01

Create an Order

Generate and store an order in your system with a unique identifier.

02

Request Payment Link

Call the Flot API to generate a payment link or USSD code.

03

Customer Pays

The customer pays via Mobile Money, Card, or the Flot app.

04

Receive Webhook

Flot sends a real-time webhook notification to your backend.

05

Update Order State

Mark the order as completed or keep it pending based on the result.

Backend-driven — you own the order lifecycle
Event-based — payment state via webhooks
Multi-channel — momo, card, in-app

Quick Start

Four steps to go live.

Step 01

Create a Flot Merchant

Register your account, complete KYC, and configure your merchant profile. You'll need to provide the following before receiving your Merchant ID.

Merchant name
Webhook URL
Webhook credentials
RSA-4096 public key
Your Merchant ID is required in every API request body.

Setup Checklist

Register a Flot account
Complete KYC verification
Configure merchant profile
Generate RSA-4096 key pair
Receive Merchant ID
Step 02

Generate Security Keys

Flot uses RSA-4096 for request signing. Generate a key pair using OpenSSL.

private_key.pem

Server only. Never expose.

public_key.pem

Share with Flot during setup.

terminal

$ 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

Step 03

Create a Payment Link

Use the payment link endpoint to initiate a transaction.

POST /merchants/private/v1/payment-links

Payment Types

momoReturns a USSD code
cardReturns a hosted payment link
in-appOpens Flot app payment flow
request.json

{

  "merchantId": "your-merchant-id",

  "type": "momo",

  "payload": {

    "orderId": "order-123",

    "amount": "100",

    "currency": "SLE"

  }

}

response.json 200 OK

{

  "data": {

    "link": "https://...",

    "code": "*175*123#"

  }

}

Step 04

Sign Your Requests

All requests must include the header X-Flot-Merchant-Signature. The signature is generated by:

1
Hash the request body

SHA512

2
Sign with RSA-4096 private key

Using your private key

3
Apply PSS padding

RSA_PKCS1_PSS_PADDING

4
Encode in Base64

Set as the header value

sign-request.js Node.js

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

Real-time payment
events.

Flot sends one POST request to your webhook endpoint when payment state changes. This is where order state becomes final.

Endpoint Requirements

Accepts POST requests
Protected with Basic Authentication
Highly available — webhook sent once only

Status Values

completed
Payment successful — mark order paid
failed
Unsuccessful — keep order pending, user may retry
Ensure your handler is idempotent. The same webhook must not produce duplicate order state changes.
webhook-payload.json

{

  "orderId": "ord-1",

  "flotRequestId": "123456",

  "status": "completed"

}

webhook-handler.js

app.post('/webhook', (req, res) => {

  const { orderId, status } = req.body


  if (status === 'completed') {

    db.markOrderPaid(orderId) // idempotent

  }


  res.sendStatus(200)

})

Best Practices

Build it right
from day one.

Webhook-first confirmation

Never mark orders as paid before webhook confirmation. Payment state is only final on webhook receipt.

Log everything

Store all outgoing requests and incoming webhooks. Essential for debugging and reconciliation.

Idempotent webhooks

Design your webhook handler so the same event processed twice produces the same outcome.

Separate lifecycles

Your order lifecycle is yours. Flot handles payment state only — keep the two separate in your data model.

Guard your private key

Store it in an environment variable or secrets manager. Never commit it or send it over the wire.

Test on staging first

Flot provides a staging environment. Validate every flow — success and failure — before switching to production.

Testing Your Integration

Test before
you go live.

Flot provides a staging environment for testing. In this phase, you should:

Generate payment links
Simulate payment flows
Validate webhook handling
Confirm order state transitions
Ensure your system correctly handles both success and failure cases before going live.

Go Live

Once your integration
is complete.

Before switching to production, make sure every part of your integration has been thoroughly verified in the staging environment. Follow these steps in order:

1Confirm all flows are working in staging
2Verify webhook reliability
3Contact Flot team for production access
4Switch to production endpoints
Do not switch to production until both success and failure webhook flows are confirmed working end-to-end.

Ready for production access? Get in touch with the Flot team.

Use Cases

Built for how
developers ship.

E-commerce checkout systems
Payment links and invoicing
Mobile-first payment experiences
WhatsApp-based commerce flows

Start building

One API.
Every payment channel.

Mobile Money. Cards. In-app. One integration — built for Africa, ready for the world.