Comment on page

API Specifications

Specification For Virtual Accounts

API KEYS (Test Environment)

  1. 1.
    Create an account on our sandbox environment: sandbox.squadco.com
  2. 2.
    Retrieve keys from the bottom of the Get Started Page
Authorization Any request made without the authorization key will fail with a 401 (Service Not Authorized) response code.
Authorization would be done via Headers using Keys gotten from your dashboard.
Example: Authorization: Bearer sandbox_sk_94f2b798466408ef4d19e848ee1a4d1a3e93f104046f
This API specification helps you create a virtual account and also integrates payment reconciliation for your customers.
You can also trace payments to virtual accounts and link them up with customer details.
Reconciliation: For instant settlement when using our Virtual Account, All merchant and beneficiary accounts must be GTCO Bank Accounts.

Creating Virtual Account

You need to make a POST Request to a dedicated endpoint containing your customer information.

IMPORTANT NOTICE

Please note that there is a new compliance rule put in place to mitigate against fraud. As a result, all virtual accounts must carry a slug as a prefix to the name. The slug must be a portion of your business name or abbreviations of your business name as one word. Please note that slash (/) is not allowed and only hyphen (-) can be used. Please be informed that all accounts without the prefix will be flagged by our compliance team and might ultimately be closed.

Sample Request of create endpoint with Slug

If my business name is TechZilla Solutions, then I will have to create my account with the format below:
Business Model
{
"customer_identifier": "CCC",
"business_name": "Techzilla-Joseph Okoye",
"mobile_num": "08139011943",
"bvn": "12343211654",
"beneficiary_account": "4920299492"
}
Customer Model
{
"customer_identifier": "CCC",
"first_name": "Techzilla- Joesph",
"last_name": "Okoye",
"mobile_num": "08139011943",
"email": "[email protected]",
"bvn": "12343211654",
"dob": "30/10/1990",
"address": "22 Kota street, UK",
"gender": "1",
"beneficiary_account": "4920299492"
}

Customer Model

IMPORTANT NOTICE

Please note that there is a new compliance rule put in place to mitigate against fraud. As a result, all virtual accounts must carry a slug as a prefix to the name. The slug must be a portion of your business name or abbreviations of your business name as one word. Please note that slash (/) is not allowed and only hyphen can be used. Please be informed that all accounts without the prefix will be flagged by our compliance and fraud team and might ultimately be closed.
post
https://sandbox-api-d.squadco.com
/virtual-account
Creating Virtual Accounts for Customers
Response expected from the API to signify if the request received was successful

Sample Request

{
"customer_identifier": "CCC",
"first_name": "BusinessName-Joesph",
"last_name": "Ayodele",
"mobile_num": "08139011943",
"email": "[email protected]",
"bvn": "12343211654",
"dob": "30/10/1990",
"address": "22 Kota street, UK",
"gender": "1",
"beneficiary_account": "4920299492"
}
200: Successful
400: Validation Failure
401: Restricted
404: Not Found
{
"success": true,
"message": "Success",
"data": {
"first_name": "Joesph",
"last_name": "Ayodele",
"bank_code": "058",
"virtual_account_number": "7834927713",
"beneficiary_account": "4920299492",
"customer_identifier": "CCC",
"created_at": "2022-03-29T13:17:52.832Z",
"updated_at": "2022-03-29T13:17:52.832Z"
}
}
{
"status": 400,
"success": false,
"message": "Validation Failure, Customer identifier is required",
"data": {}
}
{ "status": 401, "success": false, "message": "Merchant has been restricted, please contact Habaripay support", "data": {} }
{
"success": false,
"message": "",
"data": {}
}

Business Model

This allows you to create virtual accounts for people whose customers are actually businesses (B2B) or other merchants and might not be able to provide all the necessary details that a customer should have.

IMPORTANT NOTICE

Please note that there is a new compliance rule put in place to mitigate against fraud. As a result, all virtual accounts must carry a slug as a prefix to the name. The slug must be a portion of your business name or abbreviations of your business name as one word. Please note that slash (/) is not allowed and only hyphen can be used. Please be informed that all accounts without the prefix will be flagged by our compliance and fraud team and might ultimately be closed.

Sample Request

{
"customer_identifier": "CCC",
"business_name": "Joesph- Ayodele",
"mobile_num": "08139011943",
"bvn": "12343211654",
"beneficiary_account": "4920299492"
}
post
https://sandbox-api-d.squadco.com
/virtual-account/business
Creating Virtual Account for businesses

Transaction Notification Service

Upon registration and verification as a merchant, you are to create a Webhook and add on your Squad Dashboard to receive notification on payments.
WEBHOOK: If a webhook is not provided, notifications won't be sent.
KINDLY ENSURE YOU HAVE A TRANSACTION REFERENCE CHECKER WHEN IMPLEMENTING WEBHOOKS TO AVOID GIVING DOUBLE VALUE ON TRANSACTIONS.

Webhook Validation

Method 1 (Hash Comparison)

The webhook notification sent carry the x-squad-signature in the header. The hash value (x-squad-signature) is an HMAC SHA512 signature of the webhook payload signed using your secret key. You are expected to create a hash and compare the value of the hash created with the hash sent in the header of the POST request sent to your webhook URL. To create the hash, you use the entire payload sent via the webhook.

Sample Implementations

C#
Javascript (Node)
PHP
Java
using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json.Linq;
namespace HMacExample
{
class Program {
static void Main(string[] args) {
String key = "YOUR_SECRET_KEY"; //replace with your squad secret_key
//Replace with the body of the notification received
String webhookPayload = "THE_BODY_OF_THE_WEBHOOK_PAYLOAD YOU RECEIVED";
String jsonInput = JsonConvert.SerializeObject(webhookPayload);
String result = "";
byte[] secretkeyBytes = Encoding.UTF8.GetBytes(key);
byte[] inputBytes = Encoding.UTF8.GetBytes(jsonInput);
using (var hmac = new HMACSHA512(secretkeyBytes))
{
byte[] hashValue = hmac.ComputeHash(inputBytes);
result = BitConverter.ToString(hashValue).Replace("-", string.Empty);;
}
Console.WriteLine(result);
String x-squad-signature = "Request's header value for x-squad-signature" //replace with the request's header value for x-squad-signature here
if(result.Equals(x-squad-signature)) {
// you can trust the event came from squad and so you can give value to customer
} else {
// this request didn't come from Squad, ignore it
}
}
}
}
const crypto = require('crypto');
const secret = "Your Squad Secret Key";
// Using Express
app.post("/MY-WEBHOOK-URL", function(req, res) {
//validate event
const hash = crypto.createHmac('sha512', secret).update(JSON.stringify(req.body)).digest('hex');
if (hash == req.headers['x-squad-signature']) {
// you can trust the event came from squad and so you can give value to customer
} else {
// this request didn't come from Squad, ignore it
}
res.send(200);
<?php
if ((strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) || !array_key_exists('x-squad-signature', $_SERVER) )
exit();
// Retrieve the request's body
$input = @file_get_contents("php://input");
$body = json_decode($input);
define('SQUAD_SECRET_KEY','YOUR_SECRET_KEY'); //ENTER YOUR SECRET KEY HERE
if($_SERVER['x-squad-signature'] !== hash_hmac('sha512', json_encode($body, JSON_UNESCAPED_SLASHES), SQUAD_SECRET_KEY))
// The Webhook request is not from SQUAD
exit();
http_response_code(200);
// The Webhook request is from SQUAD
exit();
?>
package hmacexample;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.json.JSONException;
import org.json.JSONObject;
public class HMacExample {
public static void main(String[] args) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, JSONException {
//This verifies that the request is from Squad
String key = "YOUR_SECRET_KEY"; //replace with your squad secret_key
String body = "BODY_OF_THE_WEBHOOK_PAYLOAD"; //Replace with body of the webhook payload
String result = "";
String HMAC_SHA512 = "HmacSHA512";
String x-squad-signature = ""; //put in the request's header value for x-squad-signature
byte [] byteKey = key.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, HMAC_SHA512);
Mac sha512_HMAC = Mac.getInstance(HMAC_SHA512);
sha512_HMAC.init(keySpec);
byte [] mac_data = sha512_HMAC.
doFinal(body.toString().getBytes("UTF-8"));
result = String.format("%040x", new BigInteger(1, mac_data));
if(result.equals(x-squad-signature)) {
// you can trust that this is from squad
}else{
// this isn't from Squad, ignore it
}
}
}

Method 2 (Decryption of Encrypted Body)

To validate the webhook sent to you, you are expected to decrypt the hashed body (encrypted_body) of data sent via the webhook using the Public and Secret Key found on your squad dashboard. The result of this decryption is to be compared against the body of data sent from the webhook, if they match then you can trust that the notification is from squad and if they don't then you know the notification didn't originate from squad and you are expected to ignore such notifications. To decrypt the hashed body, kindly visit our encryption and decryption page for sample decryption functions in different languages.

Sample Webhook Notification

{
"transaction_reference": "REF2023022815174720339_1",
"virtual_account_number": "0733848693",
"principal_amount": "0.20",
"settled_amount": "0.20",
"fee_charged": "0.00",
"transaction_date": "2023-02-28T00:00:00.000Z",
"customer_identifier": "5UMKKK3R",
"transaction_indicator": "C",
"remarks": "Transfer FROM WILLIAM JAMES | [5UM2B63R] TO CHIZOBA ANTHONY OKOYE",
"currency": "NGN",
"channel": "virtual-account",
"sender_name": "WILLIAM JAMES",
"meta": {
"freeze_transaction_ref": null,
"reason_for_frozen_transaction": null
},
"encrypted_body": "DiPEa8Z4Cbfiqulhs3Q8lVJXGjMIFzbWwI2g7utVGbiI96TjcbjW+64iQrDR+kbZBwisMLMfB5l+Bn0/9kchGjB+xj6bLc6SnyCaku3pCMKmiVSkr/US1lsk+dBBI53nkGcUFkhige35wBYtXC7IpB/N2DCrzXTW5kEGnr9lCvpEFvDhZzDIUVeUCxV14V92vYYP/8O8Zjj3WR9keUc7Qq0H+fl/jmm7VwCtKMSp0OXNGMVPk5TJkLR52hQ8Rap+oorORLoNau1FRLzA24AW0d+nQfqbI+B4hf5+RztP7F1PpiRlo5qR7EthNpaHW6EMYp9fFUQdJRzsQNLbU/IfnH5oK9zFjHaOfKAa5rnoWP3N5IQjz6wobLq9T2KHei3UpCioFMcKYoigtJxple26auq0vCDkDoalPF6+YaqpuKFWdjX0mLz9+Xh5OCq4AI4u3GhioYFbpAvkrzk/Eyh5OdrEvDDLsbSu8lnXymOoiYXuS1Y4Y5jVZpzAArJ7wX7rdi1KLawHu8/m6fBkQLq/82olUuGLtGdPKF1JZnbv3eAXa7+IMhF4QUvsd52uMRnBdEHXfij+WHp7mz4jMP4Gxsx19Xzt7gyWqBhyswEJobDMSZhk/9GRcETwnT0dlSlWxVOL2pVSzKhc73ASxEQCZCO3/5/i1Nq6qSTjsbplLKuwP2Qr/15rP6TvVWAIpxa8"
}
Note: You are expected to send us a response confirming receipt of the request
200: Successful
400: Validation Failure
500: System Malfunction
{
response_code:200,
transaction_reference: 'unique reference sent through the post',
response_description: 'Success'
}
{
response_code:400,
transaction_reference: 'unique reference sent through the post',
response_description: 'Validation failure'
}
{
response_code:500,
transaction_reference: 'unique reference sent through the post',
response_description: 'System malfunction'
}

WEBHOOK ERROR LOG

This API allows you retrieve all your missed webhook transactions and use it to update your record without manual input.
  • The top 100 missed webhook will always be returned by default and it
  • This flow involves integration of two(2) APIs
  • Once you have updated the record of a particular transaction, you are expected to use the second API to delete the record from the error log. If this is not done, the transaction will continuously be returned to you in the first 100 transactions until you delete it.
  • This will only work for those who respond correctly to our webhook calls.
  • Also, ensure you have a transaction duplicate checker to ensure you don't update a record twice or update a record you have updated using the webhook or the transaction API.
Authorization Any request made without the authorization key (secret key) will fail with a 401 (Unauthorized) response code.
The authorization key is sent via the request header as Bearer Token Authorization
Example: Authorization: Bearer sandbox_sk_94f2b798466408ef4d19e848ee1a4d1a3e93f104046f

Get Webhook Error Log

get
https://sandbox-api-d.squadco.com
/virtual-account/webhook/logs
This API returns an array of transactions from the webhook error log

Delete Webhook Error Log

delete
https://sandbox-api-d.squadco.com
/virtual-account/webhook/logs/:transaction_ref
This API enables you delete a processed transaction from the webhook error log

Query Customer Transaction by Customer Identifier

This is an endpoint to query the transactions a customer has made. This is done using the customer's identifier which was passed when creating the virtual account.
get
https://sandbox-api-d.squadco.com
/virtual-account/customer/transactions/{{customer_identifier}}
Query Customer Transactions
Response expected from the API to show queried Virtual Accounts.
200: Successful
400: Validation Failure
401: Restricted
404: Not Found
{
"status": 200,
"success": true,
"message": "Success",
"data": [
{
"transaction_reference": "74902084jjjfksoi93004891_1",
"virtual_account_number": "2224449991",
"principal_amount": "30000.00",
"settled_amount": "0.00",
"fee_charged": "0.00",
"transaction_date": "2022-04-21T09:00:00.000Z",
"transaction_indicator": "C",
"remarks": "Payment from 10A2 to 2224449991",
"currency": "NGN",
"frozen_transaction": {
"freeze_transaction_ref": "afbd9b7f-fb98-41c3-bfe8-dc351cfb45c7",
"reason": "Amount above 20000 when BVN not set"
},
"customer": {
"customer_identifier": "SBN1EBZEQ8"
}
},
{
"transaction_reference": "676767_1",
"virtual_account_number": "2224449991",
"principal_amount": "1050.00",
"settled_amount": "1037.00",
"fee_charged": "13.00",
"transaction_date": "2022-03-21T09:00:00.000Z",
"transaction_indicator": "C",
"remarks": "Payment from 10A2 to 2224449991",
"currency": "NGN",
"froze_transaction": null,
"customer": {
"customer_identifier": "SBN1EBZEQ8"
}
}
]
}
{ "status": 400, "success": false, "message": "Customer identifier or merchant identifier is required", "data": {} }
{ "status": 401, "success": false, "message": "Merchant has been restricted, please contact Habaripay support", "data": {} }

Query All Merchant's Transactions

This is an endpoint to query all the merchant transactions over a period of time.
get
https://sandbox-api-d.squadco.com
/virtual-account/merchant/transactions
Query All Transactions
200: Successful
400: Validation Failure
401: Restricted
404: Not Profiled
{
"status": 200,
"success": true,
"message": "Success",
"data": [
{
"transaction_reference": "4894fe1_1",
"virtual_account_number": "2244441333",
"principal_amount": "5000.00",
"settled_amount": "0.00",
"fee_charged": "0.00",
"transaction_date": "2022-04-21T09:00:00.000Z",
"transaction_indicator": "C",
"remarks": "Payment from 15B8 to 2244441333",
"currency": "NGN",
"frozen_transaction": {
"freeze_transaction_ref": "afbd9b7f-fb98-41c3-bfe8-dc351cfb45c7",
"reason": "Amount above 20000 when BVN not set"
},
"customer": {
"customer_identifier": "SBN1EBZEQ8"
}
},
{
"transaction_reference": "676767_1",
"virtual_account_number": "2224449991",
"principal_amount": "30000.00",
"settled_amount": "1037.00",
"fee_charged": "13.00",
"transaction_date": "2022-03-21T09:00:00.000Z",
"transaction_indicator": "C",
"remarks": "Payment from 10A2 to 2224449991",
"currency": "NGN",
"froze_transaction": null,
"customer": {
"customer_identifier": "SBN1EBZEQ8"
}
}
]
}
{ "status": 400, "success": false, "message": "Merchant identifier is required", "data": {} }
{ "status": 401, "success": false, "message": "Merchant has been restricted, please contact Habaripay support", "data": {} }
{ "status": 404, "success": false, "message": "Merchant is not profiled for this service, please contact Habaripay support", "data": {} }

Query All Merchant Transactions with Multiple Filters

This endpoint allows you query all transactions and filter using multiple parameters like virtual account number, start and end dates, customer Identifier etc
get
https://sandbox-api-d.squadco.com
/virtual-account/merchant/transactions/all
Query All Transactions with Multiple Filters

Get Customer Details by Virtual Account Number

This is an endpoint to retrieve the details of a customer using the Virtual Account Number
get
https://sandbox-api-d.squadco.com
/virtual-account/customer/{{virtual_account_number}}
Retrieve Virtual Account Details

Get Customer Details Using Customer Identifier

This is an endpoint to retrieve the details of a customer'svirtual account using the Customer Identifier
get
https://sandbox-api-d.squadco.com
/virtual-account/{{customer_identifier}}
Retrieve Virtual Account Details
200: Successful
400: Validation Failure
404: Not Profiled
{
"status": 200,
"success": true,
"message": "Success",
"data": {
"first_name": "Wisdom",
"last_name": "Trudea",
"bank_code": "737",
"virtual_account_number": "555666777",
"customer_identifier": "10D2",
"created_at": "2022-01-13T11:03:54.252Z",
"updated_at": "2022-01-13T11:09:51.657Z"
}
}
{
"status": 400,
"success": false,
"message": "Merchant identifier is required",
"data": {},
}
{
"status": 404,
"success": false,
"message": "No virtual account is associated",
"data": {}
}

Update Customer's BVN and Unfreeze Transaction

patch
https://sandbox-api-d.squadco.com
/virtual-account/update/bvn
Update customer's BVN and unfreeze transaction
200: Successful
400: Validation Failure
424: Update Error
409: Conflict
{
"status": 200,
"success": true,
"message": "Success",
"data": {}
}
{
"status": 400,
"success": false,
"message": "BVN verification failed",
"data": {}
}
{
"status": 424,
"success": false,
"message": "An error occurred while trying to update customer's bvn",
"data": {}
}
{
"status": 409,
"success": false,
"message": "Customer's first_name & last_name didn't match or phone_number didn't match.",
"data": {}
}

Query All Merchant's Virtual Accounts

This is an endpoint to look-up the virtual account numbers related to a merchant.
get
https://sandbox-api-d.squadco.com
/virtual-account/merchant/accounts
Find All Virtual Account Number by Merchant
200: Successful
404: Not Profiled
{
"status": 200,
"success": true,
"message": "Success",
"data": [
{
"bank_code": "058",
"virtual_account_number": "2224449991",
"beneficiary_account": "4829023412",
"created_at": "2022-02-09T16:02:39.170Z",
"updated_at": "2022-02-09T16:02:39.170Z",
"customer": {
"first_name": "Ifeanyi",
"last_name": "Igweh",
"customer_identifier": "10A2"
}
},
{
"bank_code": "058",
"virtual_account_number": "111444999",
"beneficiary_account": "9829023411",
"created_at": "2022-02-09T16:02:39.170Z",
"updated_at": "2022-02-09T16:02:39.170Z",
"customer": {
"first_name": "Paul",
"last_name": "Aroso",
"customer_identifier": "10B2"
}
}
]
}
{
"status": 400,
"success": false,
"message": "Merchant identifier is required",
"data": {},
}

Update Beneficiary Account

Sample Request

{
"beneficiary_account":"1111111111",
"virtual_account_number": "4683366555"
}
patch
https://sandbox-api-d.squadco.com
/virtual-account/update/beneficiary/account
This is used to update beneficiary account

Simulate Payment

This is an endpoint to simulate payments
post
https://sandbox-api-d.squadco.com
/virtual-account/simulate/payment
Simulate Payment

Go Live

To go live, simply:
1. Change the base URL for your endpoints from sandbox-api-d.squadco.com to api-d.squadco.com
3. Complete your KYC
4. Share the Merchant ID with the Technical Account Manager for Profiling
5. Use the secret keys provided on the dashboard to authenticate your live transactions