Payment gateway · Integration guide

Accept payments through the Flot network.

A complete instruction set for merchants to integrate the Flot payment gateway, from KYC and key generation to payment links and webhooks.

ContentsFive sections
Section 01

Technical requirements.

Before integrating with Flot, your application must satisfy two requirements: every order needs a stable identifier, and you must expose a webhook endpoint that Flot can notify when an order is processed.

REQ · 01

Each order needs an ID

Every order must carry a unique identifier in your system. This identifier is what Flot references throughout the lifecycle.

REQ · 02

Webhook endpoint to track status

Implement an endpoint that receives webhook notifications so order status can be tracked once Flot finishes processing.

Webhook endpoint specification

One-shot delivery.

Because Flot does not retry webhooks, treat the endpoint as a critical path. Queue the request immediately on receipt and acknowledge with a 2xx response before any heavy processing.

What good looks like

An endpoint behind a load balancer with redundancy, request logging, and idempotent handling of repeated orderId + flotRequestId combinations. Treat the webhook as the source of truth that flips your order from pending to a terminal state.

Section 02

Steps for the merchant.

  1. 01
    Register as a user in the Flot application.
  2. 02
    Upgrade KYC level to the maximum level possible. This increases the maximum possible order amount available to your merchant account.
  3. 03
    Generate a pair of RSA-4096 keys (via OpenSSL), then store the private key securely. It signs your payment-link requests.
    generate-private-key.sh
    openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096
    extract-public-key.sh
    openssl rsa -pubout -in private_key.pem -out public_key.pem
    encode-public-key.sh
    cat public_key.pem | base64
  4. 04
    Contact Flot Staff at +232 80 800100 or +232 99 800100 to create a merchant ID and assign destination wallets.
    • By default, orders can be paid in the Flot app.
    • If you want orders to also be payable by credit card, specify this when contacting Flot Staff.
    • Provide Flot Staff with: merchant name, webhook URL, webhook basic-auth credentials, and the Base64-encoded RSA-4096 public key.
    • Ask Flot Staff to provide your Merchant ID. It is required when requesting payment links.
Keep your Merchant ID safe.

You'll reference it on every payment-link request, alongside the signature generated with your private key.

Section 04

Signature code examples.

Reference implementations in Node.js and Go. Use the same private key whose public counterpart you submitted during onboarding. Any mismatch causes Flot to reject the request. Replace your-merchant-id with the Merchant ID issued by Flot Staff.

Body-present requests

Sign the stringified JSON body.

flot-signature-gen.js
const crypto = require("crypto");
const fs = require("fs");

const privateKey = fs.readFileSync("private_key.pem", "utf8");

const requestBody = {
  merchantId: "your-merchant-id",
  type: "in-app",
  payload: {
    orderId: "some-test-order-id-12345",
    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"
);
flot-signature-gen.go
payload, _ := json.Marshal(requestBody)
// struct fields: merchantId, type,
// payload{ orderId, currency, amount }

hashed := sha512.Sum512(payload)

signature, err := rsa.SignPSS(
    rand.Reader, privateKey, crypto.SHA512,
    hashed[:], &rsa.PSSOptions{
        SaltLength: rsa.PSSSaltLengthEqualsHash,
        Hash:       crypto.SHA512,
    })
if err != nil {
    return "", err
}

sig := base64.StdEncoding.EncodeToString(signature)
return sig, nil

Body-less requests

Sign the canonical {METHOD}\n{PATH} string.

flot-signature-gen-bodyless.js
const crypto = require("crypto");
const fs = require("fs");

const privateKey = fs.readFileSync("private_key.pem", "utf8");

const canonical =
  "GET\n/merchants/private/v1/external-orders/order-123/payment-attempts/att-456";

const signer = crypto.createSign("RSA-SHA512");
signer.update(canonical);

const signature = signer.sign(
  {
    key: privateKey,
    padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
    saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
  },
  "base64"
);

// Send with the X-Flot-Merchant-Id and
// X-Flot-Merchant-Signature headers
flot-signature-gen-bodyless.go
func canonicalRequestString(method, path string) string {
    return fmt.Sprintf("%s\n%s", method, path)
}

method := "GET"
path := "/merchants/private/v1/external-orders/order-123/payment-attempts/att-456"

dataToSign := canonicalRequestString(method, path)
sig, err := signPayload(privateKey, []byte(dataToSign))

// Remember the X-Flot-Merchant-Id header
X-Flot-Merchant-Id is required for body-less requests.

Because there is no body to carry the merchant context, the signature is computed over the canonical {METHOD}\n{PATH} string and the merchant is identified by this header instead.

Section 05

Outgoing webhooks.

Authentication

Basic authentication should be used on the merchant side. Flot includes the credentials you provided at onboarding in every webhook request.

Payload structure

application/json
{
  "orderId": "order-123",
  "flotRequestId": "123456",
  "status": "completed"
}
FieldTypeDescription
orderIdstringOrder ID in the merchant's system.
flotRequestIdstringUnique transfer request ID in Flot.
statusenumOne of completed or failed.
Handling failed status.

If a webhook arrives with status = failed, the end-user experienced a payment error while paying with credit card. They can retry later. When your backend receives this status, leave the order in pending state rather than marking it failed.

Retry policy

As of now, Flot Backend sends a webhook notification only once. Design your endpoint for high availability and acknowledge requests promptly with a 2xx response, queuing any heavy work asynchronously.

Need help?

Reach Flot Staff for
onboarding and support.

+232 80 800100  ·  +232 99 800100