FinAPI Switch
v2.4 Sovereign Spec

FinAPI Engine Documentation

Complete technical specification for STK pushes, real-time cryptographic webhooks, failover routing, and embed widgets.

1 Configure Providers & Fallback Priority

FinAPI unifies your disparate payment credentials into a single gateway pool. You can define your primary gateway and multiple failover providers.

Step 1

Add Credentials

Save API keys in Gateway Vault for PayHero, Makamesco, Hashback, etc.

Step 2

Bind to Platform

In Platforms, create an app and check off your fallback providers.

Step 3

Deploy Integration

Point your application to our single unified endpoint using your Master API key.

2 Authentication & Origin Validation

Requests are authenticated using your Platform API key. Keys can be passed as a standard HTTP Bearer token or within the JSON body.

Strict Origin Policy

If configured on your platform, requests originating from unauthorized domains or CORS mismatches are rejected automatically with 403 Forbidden.

// Required Request Headers
{
  "Content-Type": "application/json",
  "Authorization": "Bearer sk_live_your_platform_api_key_here"
}

3 Initiate STK Push Prompt

POST /api/stk-push/

Fires an M-Pesa STK Push prompt to the customer's phone number. If Gateway #1 fails, FinAPI transparently reroutes the dispatch to your configured backup gateway.

Field Type Required Description
phone_number string Yes Customer phone (e.g. 254712345678 or 0712345678)
amount number Yes Amount in KES (e.g. 100.00)
reference string Yes Your internal unique order reference (e.g. ORDER_9918)
callback_url string No Optional dynamic webhook URL to override platform default

Example Request

fetch('https://finapi.e-ss.co.ke/api/stk-push/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer sk_live_your_platform_api_key'
    },
    body: JSON.stringify({
        phone_number: '254712345678',
        amount: 150.00,
        reference: 'ORDER_102394'
    })
})
.then(res => res.json())
.then(data => console.log('Initiated:', data));

Example Response (200 OK)

{
  "success": true,
  "transaction_id": "ws_CO_2710202612345",
  "checkout_request_id": "ws_CO_2710202612345",
  "merchant_request_id": "ORDER_102394",
  "message": "Payment request initiated successfully",
  "provider_used": "payhero",
  "was_switched": false,
  "used_fallback": false
}

4 Real-Time Webhooks & HMAC Verification

When a customer confirms the prompt, FinAPI sends an instantaneous HTTP POST webhook with a normalized JSON payload and cryptographic signature header X-FinAPI-Signature.

Normalized Webhook Payload Dispatched to You

{
  "event": "payment.completed",
  "delivery_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "timestamp": "2026-10-27T14:30:00Z",
  "data": {
    "reference": "ORDER_102394",
    "merchant_reference": "ws_CO_2710202612345",
    "transaction_id": "TL1234XYZ9",
    "status": "completed",
    "amount": 150.00,
    "currency": "KES",
    "phone_number": "254712345678",
    "provider": "payhero",
    "message": "Payment completed successfully"
  }
}

Verifying HMAC-SHA256 Signature (Node.js / Express)

const crypto = require('crypto');

app.post('/api/finapi-webhook', express.raw({ type: 'application/json' }), (req, res) => {
    const signature = req.headers['x-finapi-signature']; // "sha256=abcdef..."
    const expectedSig = 'sha256=' + crypto
        .createHmac('sha256', process.env.FINAPI_API_KEY)
        .update(req.body)
        .digest('hex');

    if (signature !== expectedSig) {
        return res.status(401).send('Invalid signature');
    }

    const event = JSON.parse(req.body.toString());
    if (event.event === 'payment.completed') {
        console.log('Order verified:', event.data.reference, event.data.transaction_id);
    }
    res.status(200).send('OK');
});

5 Turnkey Drop-In Checkout Widget

Embed an interactive M-Pesa STK push checkout modal on any webpage in 2 lines of HTML:

<!-- 1. Include the lightweight script -->
<script src="https://finapi.e-ss.co.ke/static/js/finapi-widget.min.js"></script>

<!-- 2. Drop in the container -->
<div class="finapi-widget" 
     data-api-key="sk_live_your_platform_key" 
     data-amount="150" 
     data-color="#6366f1">
</div>

<!-- 3. Listen for completion -->
<script>
  const widget = document.querySelector('.finapi-widget');
  widget.addEventListener('finapi:payment_success', (e) => {
      console.log('Payment Successful! Receipt:', e.detail.data.transaction_id);
  });
</script>

6 Integrated Provider Matrix & Webhook Routing

Gateway Provider Webhook Setup Location Credentials Required Status Detection
PayHero Kenya Passed dynamically or in PayHero Dashboard > Account Menu api_key, username, channel_id Status: Success
Hashback Settings > Webhooks / IPN token (Bearer), webhook_secret status: SUCCESS
Makamescopay Merchant Settings > Webhooks api_key, account_id event: payment.completed
SwiftWallet Passed dynamically in callbackUrl parameter client_id, client_secret, channel_id ResultCode: 0
MegaPay / TinyPesa Linked Accounts > Webhook Settings api_key, vendor_id ResponseCode: 0