Download OpenAPI specification:
This API is part of the our ecosystem. It allows you to make payments, find out the status of transactions and much more. Here you will find the latest documentation on setting up your solution.
Merchant’s request and callback have to be signed to verify sent data. To generate the signature all sent parameters from the payload are included in the order they were sent. The parameter signature should be excluded, of course,! and added to the payload after generating
Note: to generate a correct signature you need a secretKey received with other credentials.
function calculateSignature(array $data, string $secretKey, string $currentParamPrefix = '', int $depth = 16, int $currentRecursionLevel = 0 ): string
{
if ($currentRecursionLevel >= $depth) {
throw new Exception('Recursion level exceeded');
}
$stringForSignature = '';
foreach ($data as $key => $value) {
if (is_array($value)) {
$stringForSignature .= calculateSignature(
$value,
$secretKey,
"$currentParamPrefix$key.",
$depth,
$currentRecursionLevel + 1
);
} else if ($key !== 'signature') {
$stringForSignature .= "$currentParamPrefix$key" . $value;
}
}
if ($currentRecursionLevel == 0) {
return strtolower(hash_hmac('sha512', $stringForSignature, $secretKey));
} else {
return $StringForSignature;
}
}
$postData = [
'merchant_id' => 'fffed61be9780b97c5e4c65e4e07bb6b',
'provider_id' => 10,
'client_id' => '080000000',
'country' => 'KE',
'order_id' => 'order_3444298767545',
'amount' => 1000,
'currency' => 'CDF',
'callback_url' => 'https://my.callback.url'
];
$secretKey = "cf11635572c1e8d77297207152dc0791ad91f22b32d23c758ce3ba2637202ad8f7290ba41f2243cccf32edde1dfb8bf0f5dea62525309e293b3adb2c76eed6a5";
$signature = calculateSignature($postData, $secretKey);
$postData['signature'] = $signature;
Examples in other languages are available on request
| Code | Name | Description |
|---|---|---|
| -1 | undefined | Operation status is undefined (for example in an error situation) |
| 0 | initiated | Operation is initiated |
| 1 | in progress | Operation is in progress |
| 2 | success | Operation is successful |
| 3 | failed | Operation is failed |
| 4 | cancelled | Operation is cancelled |
| 5 | cancelled partially | Operation is cancelled partially (this status is related to POS payments) |
| 6 | in_transit | Operation is in transition (for example for withdrawal operation it means that cash was held but wasn’t received by the customer, this status also is related to POS payments) |
Depending on the type of request you may see the following code
| Code | Operation |
|---|---|
| 16 | payment_b2c |
| 17 | payment_c2b |
| Code | Name | Locations |
|---|---|---|
| GHS | Ghanaian cedi | Ghana |
| KES | Kenyan shilling | the Republic of Kenya |
| MWK | Malawian kwacha | Malawi |
| NGN | Naira | Nigeria |
| RWF | Rwandan franc | Rwanda |
| TZS | Tanzanian shilling | Tanzania |
| UGX | Ugandan shilling | Uganda |
| XAF | CFA franc BEAC | Cameroon, Central African Republic, Republic of the Congo, Chad, Equatorial Guinea, Gabon |
| XOF | CFA franc BCEAO | Benin, Burkina Faso, Ivory Coast, Guinea-Bissau, Mali, Niger, Senegal, Togo |
Responses for confirmation requests have the same format as original operation responses.
C2b transaction status is sent via callback because it needs a confirmation by client done asynchronously. Usually the callback should be sent in 2-3 minutes maximum. In case of missing callback there is a way to get the transaction status using API method status. It needs the order ID as an parameter and returns a status of the performed transaction.
Payment gateway considers the Merchant system response as successful if HTTP 200 was received.
| Provider ID | Provider Name | Notes |
|---|---|---|
| 14 | Simulator | For testing purposes |
During tests runs, using 14 provider ID (simulator) the callback is not returned and the transaction remains in the "in progress" status and if successful you will see in the response
{
"order_id": "54321",
"transaction_id": "12345",
"transaction_ref": "",
"status": 1,
"result": {
"code": 0,
"message": "OK"
},
"provider_result": {
"code": -8888,
"message": "Good"
},
"service_id": 1,
"service_version": "1.03/1.14|1.0/1.26|1.0/1.0|1.01/1.01|1.01/1.01||1.01/1.27",
"service_date_time": "2023-05-15 10:00:00.000000",
"confirm_type": 0
}
| Provider ID | Provider Name | Notes |
|---|---|---|
| 2174 | Orange | Client's phone should start from 0: 0800000000 |
| 2175 | Airtel | Client's phone shouldn't start from 0: 999000000 |
| 2173 | Vodacom | 243000000000 - This is the format of the phone number sent in the request |
| 2176 | Africel | Client's phone should start from 0: 0900000000 |
The flow is standard, no need to pass extra parameters
| c2b minimum | b2c minimum | Maximum transaction limit |
|---|---|---|
| CDF 100 | CDF 100 | CDF 1500000 |
| Provider ID | Provider Name | Notes |
|---|---|---|
| 2163 | MTN | |
| 2164 | Airtel | |
| 2165 | Vodafone |
233000000000 - This is the format of the phone number you have to send in the payment requests.
For C2B and B2C payments you should send a customer full name and customer email in the payment requests. Parameters extra->customer_name and extra->customer_email. Please see the example in the API Methods section.
| c2b minimum | b2c minimum | Maximum transaction limit |
|---|---|---|
| GHS 10.00 | GHS 10.00 | GHS 25000.00 |
| Provider ID | Provider Name | Notes |
|---|---|---|
| 536 | MTN | |
| 537 | Orange | |
| 538 | Moov | |
| 539 | Wave |
2250000000000 - This is the format of the phone number you have to send in the payment requests.
For C2B payments you should send a customer redirect url in the payment requests. Parameters extra->return_url. Please see the example in the API Methods section.
For B2C payments please see the example in the API Methods section.
Customer initiates the payment on Merchant side
Merchant sends request to the platform (POST payment_c2b)
Merchant sends request to the platform (POST status) and get redirect_url
Merchant redirect Customer to provider payment page
Customer submit form on provider payment page
Customer gets push from operator and confirm the operation
Merchant gets a callback (or requests the status) with the final state of the operation
Customer initiates the payment on Merchant side
Merchant sends request to the platform (POST payment_b2c)
Customer receives funds to his mobile number
Merchant gets a callback (or requests the status) with the final state of the operation
| c2b minimum | b2c minimum | Maximum transaction limit |
|---|---|---|
| XOF 200.00 | XOF 500.00 | XOF 500000.00 |
| Provider ID | Provider Name | Notes |
|---|---|---|
| 2162 | M-Pesa Safaricom |
254000000000 - This is the format of the phone number you have to send in the payment requests.
For C2B and B2C payments you should send a customer full name and customer email in the payment requests. Parameters extra->customer_name and extra->customer_email. Please see the example in the API Methods section.
| c2b minimum | b2c minimum | Maximum transaction limit |
|---|---|---|
| KES 1.00 | KES 500.00 | KES 150000.00 |
| Provider ID | Provider Name | |
|---|---|---|
| 2166, 2170 | BankTransfer | Check provider id with your manager |
| 2167, 2171 | BankTransfer Pay Attitude | Check provider id with your manager |
| 2168 | BankTransfer OPay | |
| 2169, 2172 | BankTransfer Palmpay | Check provider id with your manager |
Bank Transfer / Pay Attitude / OPay / Palmpay / Card payment C2B (deposit) scenario: * Customer initiates the payment via Bank Transfer/Pay Attitude/OPay/Palmpay/Card method on the Merchant’s side. * Merchant requests Customer’s Name, Email and Amount. This step is optional, as this data may be stored in the merchant's system
```
{
"provider_id": 2170,
"merchant_id": "cd4645yh720cc83gh5443d2bd6424b",
"customer_id": "2349061239999",
"order_id": "1234567890",
"country": "NG",
"amount": "10000",
"currency": "NGN",
"callback_url": "https://example.com",
"email": "[email protected]",
"name": "John Christopher",
"signature": "3bca46363467e8683d73dbd8e564fa93596f5d4fede1f252d2c875597bf6945730fbbc8da66a4100fe60d"
}
Customer_message example:
{
"order_id": "1234567890",
"transaction_id": "0987654321",
"transaction_ref": "",
"status": 1,
"result": {
"code": 0,
"message": "OK"
},
"provider_result": {
"code": -8888,
"message": ""
},
"service_id": 1,
"service_version": "1.03/1.14|1.0/2.0|1.0/1.0|1.01/1.0|1.01/2.0||1.02/1.27",
"service_date_time": "2025-05-25 15:15:55.050505",
"extra": {
"account_name": "EXAMPLE TECH – LTD",
"account_number": "1597534560",
"bank_name": "GLOBUS BANK",
"transfer_amount": "10000"
},
"confirm_type": 0
}
For 2170 provider_id instead of the bank details a link will be returned in the customer_redirect parameter to which the user should be redirected
Please note that on channels 2166, 2167, 2168, 2169 users have the opportunity to pay the wrong amount using the details, as well as make payments several times. To avoid discrepancies in amounts, long processing of transactions on these channels and other difficulties, we recommend that you create an information board for users. In the text, please warn that the details are used only once and only for the stated amount. In other cases, the transaction processing time may take a very long time. For example, to be convincing, you can warn about the high probability of losing funds
Bank Transfer B2C (withdrawal) scenario:
Passing bank_code in the request is relevant only for 2166 and 2170 provider_id
B2C Bank Transfer request example:
{
"merchant_id":"cd4645yh720cc83gh5443d2bd6424b",
"order_id":"1234567890",
"customer_id":"16280954971628095497",
"amount":"1000",
"currency":"NGN",
"provider_id":2166,
"extra":{
"customer_name":"John Christopher",
"customer_email": "[email protected]",
"bank_code":"000001"
},
"signature":"d7d6d76b0e22c6f9d36f107053d12bfd248t498ghoshgos93f9379c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}
| Provider ID | Provider Name | Notes |
|---|---|---|
| 540 | Orange | |
| 542 | Wave | |
| 541 | FreeMoney |
2250000000000 - This is the format of the phone number you have to send in the payment requests.
For C2B payments you should send a customer redirect url in the payment requests. Parameters extra->return_url. Please see the example in the API Methods section.
For B2C payments please see the example in the API Methods section.
Customer initiates the payment on Merchant side
Merchant sends request to the platform (POST payment_c2b)
Merchant sends request to the platform (POST status) and get redirect_url
Merchant redirect Customer to provider payment page
Customer submit form on provider payment page
Customer gets push from operator and confirm the operation
Merchant gets a callback (or requests the status) with the final state of the operation
Customer initiates the payment on Merchant side
Merchant sends request to the platform (POST payment_b2c)
Customer receives funds to his mobile number
Merchant gets a callback (or requests the status) with the final state of the operation
| c2b minimum | b2c minimum | Maximum transaction limit |
|---|---|---|
| XOF 200.00 | XOF 500.00 | XOF 500000.00 |
Payment Page allows to avoid the user interface and payment forms developing on the merchant’s side for each payment method. The Merchant only needs to redirect the Customer to the payment page, where they can enter their specific data for the selected payment method. The payment page can be opened in a pop-up window, an iframe or a separate browser tab.
Merchant needs to append some required parameters to the query url, and some optional ones. The optional parameters allow merchant to pre-fill some data in the url, or let the customer enter it on the payment page themselves.
URL example with the pre-filled customer’s data https://hpp.pixel-innov.com/example.php
After the redirect merchant needs to request the status of the initiated payment and also wait the callback with the final status. Status request and callbacks formats are described on the API Methods page.
Signature generating for the redirect URL example:
function calculateSignature($data, $secret)
{
$signed = '';
foreach ($data as $key => $value)
{
$signed .= $key.$value;
}
return strtolower(hash_hmac('sha512', $signed, $secret));
}
$data = [
'merchant_id' => 'fffed61be9780b97c5e4c65e4e07bb6b',
'order_id' => 'order_3444298767545',
'customer_id' => '0000000000', //For card payments only
'country' => 'NGA', // For bank transfer only
'amount' => 101, //For card payments only
'currency' => 'NGN',
'provider_id' => 5026,
'operation' => 'c2b',
'type' => 'bank_transfer',
'callback_url' => 'https://my.callback.url'
];
$secretKey = "cf11635572c1e8d77297207152dc0791ad91f22b32d23c758ce3ba2637202ad8f7290ba41f2243cccf32edde1dfb8bf0f5dea62525309e293b3adb2c76eed6a5";
$signature = calculateSignature($data, $secretKey);
echo $signature;
// signature: 9826c5e89ff6386e7bbb5263a4fbd41ed35eb2fc7c58650be487db14f066b0a650b1980762575ad296b0cbac1745f6a5faeb64cacd2756ccff95b52ba08259d7
// result query: https://hpp.pixel-innov.com/?merchant_id=fffed61be9780b97c5e4c65e4e07bb6b&order_id=order_3444298767545&country=NGA¤cy=NGN&provider_id=5000&operation=c2b&type=bank_transfer&callback_url=https://my.callback.url&signature=9826c5e89ff6386e7bbb5263a4fbd41ed35eb2fc7c58650be487db14f066b0a650b1980762575ad296b0cbac1745f6a5faeb64cacd2756ccff95b52ba08259d7
This payment page https://hpp.pixel-innov.com/example.php is only a test example, it should be implemented on the merchant side with only the data that the user must enter. For example, it can only be email, name and amount.
If the data is entered incompletely or incorrectly, the user will see the form:
After entering all the data correctly, the request will be sent to the system, and the user will be redirected to the web-page, where it is necessary to specify card details or get bank details for payment
| public_id required | string Example: f54ec96649be11ebb3780242ac130002 Merchant public ID |
Parameters to initiate a customer to the merchant payment
| merchant_id required | string (merchantIdDef) Unique Merchant ID received during the merchant registration |
| customer_id required | string (customerIdDef) Customer ID (usually mobile phone number of the customer) |
| order_id required | string (orderIdDef) The unique value is generated by the transaction initiator for each Operation. Max length is 128 symbols. Allowed symbols: [a-z], [A-Z], [0-9], “_” (underscore character), “-” (hyphen), “:” (colon), “.” (dot). For example, GUID or TIMESTAMP can be used as an order_id. This parameter provides API idempotency. It means that requests with identical nonce from the same transaction initiator will have identical responses and The corresponding operation won’t be repeated. |
| amount required | string Amount to pay, should be in format with two digits after point |
| currency required | string (currencyDef) Currency code in ISO 4217 format from the list of availabe currencies |
| country | string (countryDef) Country code in ISO 3166-1 alpha-2 format as defined in the payment providers. |
| callback_url | string URL to notify the merchant via callback. Recommended |
| provider_id required | integer (providerDef) Provider ID. Can be one of the option from this list. |
object Extra parameters | |
| signature required | string (signatureDef) Merchant’s request and callback have to be signed to verify sent data. To generate the signature all sent parameters are included in the order they were sent. The parameter signature should be excluded, of course. Example can be found here |
{- "merchant_id": "e0fecd91fcb24f348048193b3fb34875ba3722b4",
- "customer_id": "0900000001",
- "order_id": "16280954971628095497",
- "amount": "100.00",
- "currency": "CDF",
- "country": "KE",
- "provider_id": 14,
- "extra": {
- "customer_name": "Name Surname"
}, - "signature": "d7d6d76b0e22c6f9d369fa6c24f107053d12bfd24d3b154f2deb6676bf179c123134e1f20879c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}{- "order_id": "16280954971628095497",
- "transaction_id": "732007046722",
- "transaction_ref": "MP.33234.342.CP33",
- "status": 1,
- "result": {
- "code": 0,
- "message": "OK"
}, - "provider_result": {
- "code": 0,
- "message": "OK"
}, - "service_id": 1,
- "service_version": 11.1,
- "service_date_time": "2020-11-25 10:08:32.832969"
}{- "merchant_id": "e0fecd91fcb24f348048193b3fb34875ba3722b4",
- "operation_type": 17,
- "customer_id": "0900000001",
- "amount": 100,
- "order_id": "16280954971628095497",
- "transaction_id": "1234567",
- "transaction_ref": "QR555RQ",
- "status": 2,
- "provider_id": 14,
- "destination_id": "",
- "result": {
- "code": 0,
- "message": "OK"
}, - "provider_result": {
- "code": 0,
- "message": "OK"
}, - "service_id": 1,
- "service_version": "1.03/1.0|1.0/1.26|1.0/1.0|1.01/1.0|1.01/1.0||1.01/1.27",
- "service_date_time": "2020-11-25 10:08:32.832969",
- "signature": "d7d6d76b0e22c6f9d369fa6c24f107053d12bfd24d3b154f2deb6676bf179c123134e1f20879c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}Cashless payment from the merchant to the customer. If the confirm_type response parameter is a non-zero merchant, send the second payment_b2c request with confirmation data according to the section Confirmation Types.
| public_id required | string Example: f54ec96649be11ebb3780242ac130002 Merchant public ID |
Parameters to initiate the merchant to the customer payment
| merchant_id required | string (merchantIdDef) Unique Merchant ID received during the merchant registration |
| customer_id required | string (customerIdDef) Customer ID (usually mobile phone number of the customer) |
| order_id required | string (orderIdDef) The unique value is generated by the transaction initiator for each Operation. Max length is 128 symbols. Allowed symbols: [a-z], [A-Z], [0-9], “_” (underscore character), “-” (hyphen), “:” (colon), “.” (dot). For example, GUID or TIMESTAMP can be used as an order_id. This parameter provides API idempotency. It means that requests with identical nonce from the same transaction initiator will have identical responses and The corresponding operation won’t be repeated. |
| amount required | string Amount to pay, with two digits after point |
| currency required | string (currencyDef) Currency code in ISO 4217 format from the list of availabe currencies |
| country | string (countryDef) Country code in ISO 3166-1 alpha-2 format as defined in the payment providers. |
| callback_url | string URL to notify the merchant via callback |
| provider_id required | integer (providerDef) Provider ID. Can be one of the option from this list. |
object Extra parameters | |
| signature required | string (signatureDef) Merchant’s request and callback have to be signed to verify sent data. To generate the signature all sent parameters are included in the order they were sent. The parameter signature should be excluded, of course. Example can be found here |
{- "merchant_id": "e0fecd91fcb24f348048193b3fb34875ba3722b4",
- "customer_id": "0900000001",
- "order_id": "16280954971628095497",
- "amount": "100.00",
- "currency": "CDF",
- "country": "KE",
- "provider_id": 14,
- "extra": {
- "customer_name": "Name Surname"
}, - "signature": "d7d6d76b0e22c6f9d369fa6c24f107053d12bfd24d3b154f2deb6676bf179c123134e1f20879c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}{- "order_id": "16280954971628095497",
- "transaction_id": "732007046722",
- "transaction_ref": "MP.33234.342.CP33",
- "status": 1,
- "result": {
- "code": 0,
- "message": "OK"
}, - "provider_result": {
- "code": 0,
- "message": "OK"
}, - "service_id": 1,
- "service_version": 11.1,
- "service_date_time": "2020-11-25 10:08:32.832969"
}| public_id required | string Example: f54ec96649be11ebb3780242ac130002 Merchant public ID |
Get the status of the performed transaction
| merchant_id required | string (merchantIdDef) Unique Merchant ID received during the merchant registration |
| order_id required | string (orderIdDef) The unique value is generated by the transaction initiator for each Operation. Max length is 128 symbols. Allowed symbols: [a-z], [A-Z], [0-9], “_” (underscore character), “-” (hyphen), “:” (colon), “.” (dot). For example, GUID or TIMESTAMP can be used as an order_id. This parameter provides API idempotency. It means that requests with identical nonce from the same transaction initiator will have identical responses and The corresponding operation won’t be repeated. |
| signature required | string (signatureDef) Merchant’s request and callback have to be signed to verify sent data. To generate the signature all sent parameters are included in the order they were sent. The parameter signature should be excluded, of course. Example can be found here |
{- "merchant_id": "e0fecd91fcb24f348048193b3fb34875ba3722b4",
- "order_id": "16280954971628095497",
- "signature": "d7d6d76b0e22c6f9d369fa6c24f107053d12bfd24d3b154f2deb6676bf179c123134e1f20879c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}{- "order_id": "16280954971628095497",
- "transaction_id": "532007056722",
- "transaction_ref": "",
- "status": 1,
- "result": {
- "code": 0,
- "message": "OK"
}, - "provider_result": {
- "code": 0,
- "message": "OK"
}, - "extra": {
- "customer_message": "Complete the payment by following the instructions received by USSD"
}, - "service_id": 11,
- "service_version": 11.1,
- "service_date_time": "2020-11-25 10:08:32.832969",
- "confirm_type": 0
}| public_id required | string Example: f54ec96649be11ebb3780242ac130002 Merchant public ID |
Get available banks
| merchant_id required | string (merchantIdDef) Unique Merchant ID received during the merchant registration |
| provider_id required | integer (providerDef) Provider ID. Can be one of the option from this list. |
| signature required | string (signatureDef) Merchant’s request and callback have to be signed to verify sent data. To generate the signature all sent parameters are included in the order they were sent. The parameter signature should be excluded, of course. Example can be found here |
{- "merchant_id": "e0fecd91fcb24f348048193b3fb34875ba3722b4",
- "provider_id": 14,
- "signature": "d7d6d76b0e22c6f9d369fa6c24f107053d12bfd24d3b154f2deb6676bf179c123134e1f20879c803be455d81cfe792f00cd8892c26ce7cf5a05beebb9c80843e"
}{- "banks": [
- {
- "code": "000001",
- "name": "OK"
}
], - "result": {
- "code": 0,
- "message": "OK"
}
}