Merchant API
Overview
Via merchant API you can fetch individual or a list of pay widget orders associated with your account.
API servers
Environment | Server URL [SERVER_URL] |
---|---|
Sandbox | https://sandbox-api.fonbnk.com |
Production | https://aten.fonbnk-services.com |
Request Authentication
All requests should be signed using a HMAC256 algorithm and provided clientId
and clientSecret
.
How to get the signature of the request?
- Generate a timestamp (Epoch Unix Timestamp)
- Concatenate the timestamp and the endpoint that is called
{timestamp}:{endpoint}
- Decode the base64 encoded clientSecret
- Compute the SHA256 hash of the concatenated string. Use decoded clientSecret as a key. Convert the result to base64
- Add the clientId, signature, and timestamp to HTTP headers
The following pseudocode example demonstrates and explains how to sign a request
timestamp = CurrentTimestamp();
stringToSign = timestamp + ":" + endpoint;
signature = Base64 ( HMAC-SHA256 ( Base64-Decode ( clientSecret ), UTF8 ( concatenatedString ) ) );
Typescript example
import crypto from "crypto";
const generateSignature = ({
clientSecret,
timestamp,
endpoint,
}: {
clientSecret: string;
timestamp: string;
endpoint: string;
}) => {
let hmac = crypto.createHmac("sha256", Buffer.from(clientSecret, "base64"));
let stringToSign = `${timestamp}:${endpoint}`;
hmac.update(stringToSign);
return hmac.digest("base64");
};
Each request should include the following headers
Header | Description | Example |
---|---|---|
x-client-id | clientId which can be found at the merchant dashboard settings page | 645a20cbaf1d31dbd52c0fda |
x-timestamp | A UNIX timestamp you generate before sending a request to us. Please generate this timestamp right before sending a request to us and re-generate it for every request. | 1663240633 |
x-signature | Computed signature using clientSecret provided to you. | Y90dweZduRFNEF8MsmEUExBg8b8ha= |
API Methods
Get a single pay widget order
Returns a single pay widget order by its ID or orderParams query parameter.
Parameters
Parameter | Description |
---|---|
orderId | id of the order which you could receive via a webhook or iframe events |
orderParams | Value which you provided in the orderParams parameter of the pay widget URL |
Request Example
Request URL
[GET] [SERVER_URL]/api/pay-widget-merchant/order?orderId=6495a7427c8d2a730d97dc6b
Endpoint for signature
/api/pay-widget-merchant/order?orderId=6495a7427c8d2a730d97dc6b
Request Headers
x-client-id: 645a20cbaf1d31dbd52c0fda
x-timestamp: 1663240633
x-signature: Y90dweZduRFNEF8MsmEUExBg8b8ha5SLYHz5uoYO8wA=
Response
A successful request will return the following JSON encoded response
const response = {
"_id": "651e764399a4b360c7eb0178",
"walletType": "SOLANA",
"walletAddress": "53L9ahwHcNnD4F11TqNHQgVUa75WgaCL2WGeiKiK2gCc",
"feePercent": 2.5, // total fee percent (fonbnk fee + partner fee)
"fonbnkFeePercent": 1.5,
"partnerFeePercent": 1,
"gasUsdAmount": 0,
"merchantId": "645a20cbaf1d31dbd52c0fda",
"createdAt": "2023-10-05T08:39:31.691Z",
"buySwap": {
"_id": "651e764399a4b360c7eb016d",
"buyerUserPhone": "380962669394",
"sellerUserPhone": "380960000000",
"amount": 210,
"airtimeAmount": 2100,
"status": "seller_confirmed", // possible values: "initiated", "expired", "buyer_confirmed", "buyer_rejected", "seller_confirmation_pending", "seller_confirmation_failed", "seller_confirmed", "seller_rejected"
"provider": "bank_transfer",
"expiresAt": "2023-10-05T09:39:31.492Z",
"createdAt": "2023-10-05T08:39:31.500Z",
"buyerConfirmedAt": "2023-10-05T08:39:37.027Z"
},
"withdrawal": {
"_id": "651e7653db37ee6b74883fe1",
"status": "complete", // possible values: "pending", "complete", "failed"
"withdrawAmount": 2,
"transactionHash": "F19TfyGxBgebZt4q8h5bgf9Luabpypm3zSSzWR5ZUp8CKGNvL2r58zqGvWXvKftppiWKszV11jNQtsMUoFppmyb"
},
"feeAmount": 0.05, // total fee amount (fonbnk fee + partner fee)
"localCurrencyFeeAmount": 50, // total fee amount in local currency (fonbnk fee + partner fee)
"fonbnkFeeAmount": 0.03,
"localCurrencyFonbnkFeeAmount": 30,
"partnerFeeAmount": 0.02,
"localCurrencyPartnerFeeAmount": 20,
"networkFeeAmount": 0,
"localCurrencyNetworkFeeAmount": 0
};
Get a list of pay widget orders
Returns a paginated list of pay widget orders. Filters can be applied to the list by providing query parameters.
Parameters
Strategy | Description |
---|---|
cursor | this parameter should be provided in order to get a next page from the pagination, it should be taken from "nextCursor" response value |
limit | (required) number from 1 to 100, describes how many records should be in each pagination page |
walletType | wallet type of orders, possible values: POLYGON, ETHEREUM, STELLAR, AVALANCHE, SOLANA, ALGORAND, TRON, CELO, BASE, OPTIMISM, NEAR |
walletAddress | address of wallet |
userPhoneNumber | phone number of the client, should include country code |
swapProvider | provider of a swap, possible values: carrier, mpesa, mobile_money, bank_transfer |
buySwapStatus | status of a swap, possible values: initiated, expired, buyer_confirmed, buyer_rejected, seller_confirmation_pending, seller_confirmation_failed, seller_confirmed, seller_rejected |
withdrawalStatus | status of the USDC/cUSD transfer, possible values: pending, failed, complete |
Request
Request URL
[GET] [SERVER_URL]/api/pay-widget-merchant/orders?limit=1&walletType=POLYGON
Endpoint for signature
/api/pay-widget-merchant/orders?limit=1&walletType=POLYGON
Response
A successful request will return the following JSON encoded response
const response = {
list: [
{
"_id": "651e764399a4b360c7eb0178",
"walletType": "SOLANA",
"walletAddress": "53L9ahwHcNnD4F11TqNHQgVUa75WgaCL2WGeiKiK2gCc",
"feePercent": 2.5, // total fee percent (fonbnk fee + partner fee)
"fonbnkFeePercent": 1.5,
"partnerFeePercent": 1,
"merchantId": "645a20cbaf1d31dbd52c0fda",
"createdAt": "2023-10-05T08:39:31.691Z",
"buySwap": {
"_id": "651e764399a4b360c7eb016d",
"buyerUserPhone": "380962669391",
"sellerUserPhone": "380960000000",
"amount": 210,
"airtimeAmount": 2100,
"status": "seller_confirmed", // possible values: "initiated", "expired", "buyer_confirmed", "buyer_rejected", "seller_confirmation_pending", "seller_confirmation_failed", "seller_confirmed", "seller_rejected"
"provider": "bank_transfer",
"expiresAt": "2023-10-05T09:39:31.492Z",
"createdAt": "2023-10-05T08:39:31.500Z",
"buyerConfirmedAt": "2023-10-05T08:39:37.027Z"
},
"withdrawal": {
"_id": "651e7653db37ee6b74883fe1",
"status": "complete", // possible values: "pending", "complete", "failed"
"withdrawAmount": 2,
"transactionHash": "F19TfyGxBgebZt4q8h5bgf9Luabpypm3zSSzWR5ZUp8CKGNvL2r58zqGvWXvKftppiWKszV11jNQtsMUoFppmyb"
},
"feeAmount": 0.05, // total fee amount (fonbnk fee + partner fee)
"localCurrencyFeeAmount": 50, // total fee amount in local currency (fonbnk fee + partner fee)
"fonbnkFeeAmount": 0.03,
"localCurrencyFonbnkFeeAmount": 30,
"partnerFeeAmount": 0.02,
"localCurrencyPartnerFeeAmount": 20,
"networkFeeAmount": 0,
"localCurrencyNetworkFeeAmount": 0
},
],
nextCursor: "646c7e3ce2597a00921e2c53", // cursor for the next page, if there is no next page, this value will be null
};
Get expected price
Returns expected price in USDC/cUSD for a given amount of mobile money and vice versa.
Parameters
Parameter | Description |
---|---|
network | USDC/cUSD network name, possible values: POLYGON, ETHEREUM, STELLAR, AVALANCHE, SOLANA, ALGORAND, TRON, CELO, BASE, OPTIMISM, NEAR |
currency | possible values: usdc, local. If usdc is povided, amount of mobile money required to get this USDC/cUSD amount will be calculated. If local is provided, amount of USDC for provided mobile money will be calculated |
amount | amount of mobile money or USDC/cUSD |
country | country iso code, example: KE for Kenya, NG for Nigeria |
provider | funds source provider, possible values: carrier, mpesa, mobile_money, bank_transfer |
carrierId | carrier id, required if provider is not the bank_transfer |
Request Example
Request URL
[GET] [SERVER_URL]/api/pay-widget-merchant/price?network=SOLANA¤cy=usdc&amount=5&country=NG&provider=bank_transfer
Endpoint for signature
/api/pay-widget-merchant/price?network=SOLANA¤cy=usdc&amount=5&country=NG&provider=bank_transfer
Request Headers
x-client-id: 645a20cbaf1d31dbd52c0fda
x-timestamp: 1663240633
x-signature: Y90dweZduRFNEF8MsmEUExBg8b8ha5SLYHz5uoYO8wA=
Response
A successful request will return the following JSON encoded response
const response = {
"localCurrencyAmount": 5120, // amount of localc currency user should pay
"feePercent": 2.5, // total fee percent (fonbnk fee + partner fee)
"fonbnkFeePercent": 1.5,
"partnerFeePercent": 1,
"totalAmount": 5.12, // amount of funds user will receive before fees
"withdrawAmount": 5, // amount of funds user will receive after fees
"feeAmount": 0.12, // total fee amount (fonbnk fee + partner fee)
"localCurrencyFeeAmount": 120, // total fee amount in local currency (fonbnk fee + partner fee)
"fonbnkFeeAmount": 0.07,
"localCurrencyFonbnkFeeAmount": 70,
"partnerFeeAmount": 0.05,
"localCurrencyPartnerFeeAmount": 50,
"networkFeeAmount": 0,
"localCurrencyNetworkFeeAmount": 0,
// deprecated fields below, use fields above instead
"usdcTotalAmount": 5.12, // amount of USDC user will receive before fees
"usdcWithdrawAmount": 5, // amount of USDC user will receive after fees
"usdcFeeAmount": 0.12, // fonbnk service fee
"usdcGasAmount": 0, // network fee
}
Get providers list
Returns a list of countries and their supported providers, each provider has a list of supported mobile carriers(if provider requires it)
Request Example
Request URL
[GET] [SERVER_URL]/api/pay-widget-merchant/providers
Endpoint for signature
/api/pay-widget-merchant/providers
Request Headers
x-client-id: 645a20cbaf1d31dbd52c0fda
x-timestamp: 1663240633
x-signature: Y90dweZduRFNEF8MsmEUExBg8b8ha5SLYHz5uoYO8wA=
Response
A successful request will return the following JSON encoded response
enum WalletType {
POLYGON = "POLYGON",
ETHEREUM = "ETHEREUM",
STELLAR = "STELLAR",
AVALANCHE = "AVALANCHE",
SOLANA = "SOLANA",
ALGORAND = "ALGORAND",
TRON = "TRON",
CELO = "CELO",
}
type ProviderLimitations = {
[key in WalletType]: {
cryptoLimits: {
// usdc limits
min: number;
max: number;
};
fees: {
feePercent: number; // total fee percent (fonbnk fee + partner fee)
fonbnkFeePercent: number,
partnerFeePercent: number,
gasAmount: number; // gas price of selected network
minFee: number; // minimum fee
};
localCurrency?:
| {
type: "open_range";
max: number;
min: number;
step: number; // step size of currency, for example, if step is 5, then amount can be 5, 10, 15 etc.
withCents?: boolean; // can local currency include cents
}
| {
type: "fixed_list";
values: number[]; // list of supported amounts
withCents?: boolean;
};
};
};
type ProvidersResponse = {
countryIsoCode: "NG";
currencyIsoCode: "NGN";
providers: {
name: "carrier" | "mpesa" | "mobile_money" | "bank_transfer";
description: string;
requiresCarrier: boolean;
limits?: ProviderLimitations; //provider limits if carrier is not required
carriers: {
name: string;
id: string;
limits: ProviderLimitations;
}[];
}[];
}[];
Get order limitations
Returns minimum and maximum amount of order in USDC/cUSD and local currency and applied fees
Parameters
Parameter | Description |
---|---|
network | USDC/cUSD network name, possible values: POLYGON, ETHEREUM, STELLAR, AVALANCHE, SOLANA, ALGORAND, TRON, CELO, BASE, OPTIMISM, NEAR |
country | country iso code, example: KE for Kenya, NG for Nigeria |
provider | funds source provider, possible values: carrier, mpesa, mobile_money, bank_transfer |
carrierId | carrier id, required if provider is not the bank_transfer |
Request Example
Request URL
[GET] [SERVER_URL]/api/pay-widget-merchant/limits?network=SOLANA&country=NG&provider=bank_transfer
Endpoint for signature
/api/pay-widget-merchant/limits?network=SOLANA&country=NG&provider=bank_transfer
Request Headers
x-client-id: 645a20cbaf1d31dbd52c0fda
x-timestamp: 1663240633
x-signature: Y90dweZduRFNEF8MsmEUExBg8b8ha5SLYHz5uoYO8wA=
Response
A successful request will return the following JSON encoded response
type Response = {
"cryptoLimits": { // usdc limits
"min": number,
"max": number
},
"fees": {
"feePercent": number, // total fee percent (fonbnk fee + partner fee)
"fonbnkFeePercent": number,
"partnerFeePercent": number,
"gasAmount": number, // gas price of selected network
"minFee": number // minimum fee
},
localCurrency?: // local currency limits
| {
type: 'open_range';
max: number;
min: number;
step: number; // step size of currency, for example, if step is 5, then amount can be 5, 10, 15 etc.
withCents?: boolean; // can local currency include cents
}
| {
type: 'fixed_list';
values: number[]; // list of supported amounts
withCents?: boolean;
}
}