NAV Navigation
shell php javascript java ruby python go

Introduction

Audience

This document is intended to be used by the merchant’s technical staff. For any information not explained in this user guide, contact Client Services.

Payment Service

The Payment Service is designed to allow merchants to communicate and process online transactions with the payment gateway’s transaction processing system. The API serves as a bridge between the merchant’s website and various financial institutions in processing real-time payment transactions.

HOST

The Live API is located at: https://api.paybybankful.com/
The Sandbox API is located at: https://api.dev2.bankfulportal.com/

Credit Card Payments

Location

The API is located at: https://api.paybybankful.com/api/transaction/api

Method

POST

Content-Type: application/x-www-form-urlencoded

Encoding

Payment Service API uses 8-bit Unicode Transformation Format as described in the ISO/ISE 10646. Merchants are required to send Service requests with content-type, application/x-www-form-urlencoded; and charset, iso-8859-1,*, utf-8 using HTTP Post method.

Authorize

To authorize, use this code:

require 'net/http'
require 'uri'

uri = URI.parse("https://api.paybybankful.com/api/transaction/api")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/x-www-form-urlencoded"
request["Cache-Control"] = "no-cache"
request.set_form_data(
"amount" => "1.12",
"bill_addr" => "Apt#135, Shemwood St",
"bill_addr_city" => "Denver",
"bill_addr_country" => "US",
"bill_addr_state" => "CO",
"bill_addr_zip" => "201005",
"cust_email" => "[email protected]",
"cust_fname" => "Test James",
"cust_lname" => "Bond",
"cust_phone" => "9999333321",
"pmt_expiry" => "12/2022",
"pmt_key" => "111",
"pmt_numb" => "4111111111111111",
"req_password" => "sandbox_password",
"req_username" => "sandbox_username",
"request_currency" => "USD",
"transaction_type" => "CAPTURE",
"xtl_order_id" => "000011112222",
)

req_options = {
use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end

# response.code
# response.body
import requests

headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache',
}

data = {
'req_username': 'sandbox_username',
'req_password': 'sandbox_password',
'amount': '1.12',
'request_currency': 'USD',
'bill_addr': 'Apt#135, Shemwood St',
'bill_addr_city': 'Denver',
'bill_addr_country': 'US',
'bill_addr_state': 'CO',
'bill_addr_zip': '201005',
'cust_email': '[email protected]',
'cust_fname': 'Test James',
'cust_lname': 'Bond',
'xtl_order_id': '000011112222',
'cust_phone': '9999333321',
'transaction_type': 'CAPTURE',
'pmt_key': '111',
'pmt_numb': '4111111111111111',
'pmt_expiry': '12/2022'
}

response = requests.post('https://api.paybybankful.com/api/transaction/api', headers=headers, data=data)
curl -X POST "https://api.paybybankful.com/api/transaction/api" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "cache-control: no-cache" \
-d "req_username=sandbox_username&req_password=sandbox_password&amount=1.12&request_currency=USD&bill_addr=Apt%23135%2C%20Shemwood%20St&bill_addr_city=Denver&bill_addr_country=US&bill_addr_state=CO&bill_addr_zip=201005&cust_email=test.jamesbond%40example.com&cust_fname=Test%20James&cust_lname=Bond&xtl_order_id=000011112222&cust_phone=9999333321&transaction_type=CAPTURE&pmt_key=111&pmt_numb=4111111111111111&pmt_expiry=12%2F2022"
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

public static void main(String[] args) throws IOException {
URL url = new URL("https://api.paybybankful.com/api/transaction/api");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");

httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setRequestProperty("cache-control", "no-cache");

httpConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
writer.write("req_username=sandbox_username&req_password=sandbox_password&amount=1.12&request_currency=USD&bill_addr=Apt%23135%2C%20Shemwood%20St&bill_addr_city=Denver&bill_addr_country=US&bill_addr_state=CO&bill_addr_zip=201005&cust_email=test.jamesbond%40example.com&cust_fname=Test%20James&cust_lname=Bond&xtl_order_id=000011112222&cust_phone=9999333321&transaction_type=CAPTURE&pmt_key=111&pmt_numb=4111111111111111&pmt_expiry=12%2F2022");
writer.flush();
writer.close();
httpConn.getOutputStream().close();

InputStream responseStream = httpConn.getResponseCode() / 100 == 2
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
System.out.println(response);
}
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
'Content-Type' => 'application/x-www-form-urlencoded',
'cache-control' => 'no-cache'
);
$data = array(
'req_username' => 'sandbox_username',
'req_password' => 'sandbox_password',
'amount' => '1.12',
'request_currency' => 'USD',
'bill_addr' => 'Apt#135, Shemwood St',
'bill_addr_city' => 'Denver',
'bill_addr_country' => 'US',
'bill_addr_state' => 'CO',
'bill_addr_zip' => '201005',
'cust_email' => '[email protected]',
'cust_fname' => 'Test James',
'cust_lname' => 'Bond',
'xtl_order_id' => '000011112222',
'cust_phone' => '9999333321',
'transaction_type' => 'CAPTURE',
'pmt_key' => '111',
'pmt_numb' => '4111111111111111',
'pmt_expiry' => '12/2022'
);
$response = Requests::post('https://api.paybybankful.com/api/transaction/api', $headers, $data);
var fetch = require('node-fetch');

fetch('https://api.paybybankful.com/api/transaction/api', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache'
},
body: 'req_username=sandbox_username&req_password=sandbox_password&amount=1.12&request_currency=USD&bill_addr=Apt%23135%2C%20Shemwood%20St&bill_addr_city=Denver&bill_addr_country=US&bill_addr_state=CO&bill_addr_zip=201005&cust_email=test.jamesbond%40example.com&cust_fname=Test%20James&cust_lname=Bond&xtl_order_id=000011112222&cust_phone=9999333321&transaction_type=CAPTURE&pmt_key=111&pmt_numb=4111111111111111&pmt_expiry=12%2F2022'
});
package main

import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)

func main() {
client := &http.Client{}
var data = strings.NewReader(`req_username=sandbox_username&req_password=sandbox_password&amount=1.12&request_currency=USD&bill_addr=Apt%23135%2C%20Shemwood%20St&bill_addr_city=Denver&bill_addr_country=US&bill_addr_state=CO&bill_addr_zip=201005&cust_email=test.jamesbond%40example.com&cust_fname=Test%20James&cust_lname=Bond&xtl_order_id=000011112222&cust_phone=9999333321&transaction_type=CAPTURE&pmt_key=111&pmt_numb=4111111111111111&pmt_expiry=12%2F2022`)
req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/transaction/api", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("cache-control", "no-cache")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}

The above command returns JSON structured like this:

{
"REQUEST_ACTION": "CAPTURE",
"TRANS_STATUS_NAME": "APPROVED",
"TRANS_VALUE": "1.1200",
"TRANS_REQUEST_ID": 1272,
"TRANS_RECORD_ID": 79154,
"TRANS_ORDER_ID": 0980982121,
"XTL_ORDER_ID": "000011112222",
"TRANS_CUR": "USD"
}

Make sure to replace req_username with your API key.

Sales Transaction Authorize Parameters

The table below only includes typical parameters sent in a simple Authorization transaction request

Parameter Required Description Data Type
req_username Required Username Alphanumeric
req_password Required Password Alphanumeric and Special Characters
transaction_type Required Service Request Action (Send “CAPTURE”) Alphanumeric
pmt_numb Required Credit Card Number Numeric

Sales Transaction Success Response Fields

These are the fields returned to the merchant when a transaction has been approved by the Payment Service.

Parameter Description
REQUEST_ACTION This will Return CAPTURE
TRANS_STATUS_NAME Transaction Status i.e APPROVED
TRANS_VALUE Transaction Amount
TRANS_REQUEST_ID Unique Transaction ID
TRANS_RECORD_ID Order ID
TRANS_ORDER_ID Extra Transaction ID
XTL_ORDER_ID Merchant Order ID
TRANS_CUR 3-Letter Currency Code

Refund Transaction

To REFUND, use this code:

require 'net/http'
require 'uri'

uri = URI.parse("https://api.paybybankful.com/api/transaction/api")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/x-www-form-urlencoded"
request["Cache-Control"] = "no-cache"
request.set_form_data(
"amount" => "0.1",
"req_password" => "sandbox_password",
"req_username" => "sandbox_username",
"request_action" => "CCCREDIT",
"request_ref_po_id" => "186434737",
)

req_options = {
use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end

# response.code
# response.body
import requests

headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache',
}

data = {
'request_ref_po_id': '186434737',
'request_action': 'CCCREDIT',
'amount': '0.1',
'req_username': 'sandbox_username',
'req_password': 'sandbox_password'
}

response = requests.post('https://api.paybybankful.com/api/transaction/api', headers=headers, data=data)
curl -X POST \
"https://api.paybybankful.com/api/transaction/api" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "cache-control: no-cache" \
-d "request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password"
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
'Content-Type' => 'application/x-www-form-urlencoded',
'cache-control' => 'no-cache'
);
$data = array(
'request_ref_po_id' => '186434737',
'request_action' => 'CCCREDIT',
'amount' => '0.1',
'req_username' => 'sandbox_username',
'req_password' => 'sandbox_password'
);
$response = Requests::post('https://api.paybybankful.com/api/transaction/api', $headers, $data);
var fetch = require('node-fetch');

fetch('https://api.paybybankful.com/api/transaction/api', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'cache-control': 'no-cache'
},
body: 'request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password'
});
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

public static void main(String[] args) throws IOException {
URL url = new URL("https://api.paybybankful.com/api/transaction/api");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("POST");

httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setRequestProperty("cache-control", "no-cache");

httpConn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
writer.write("request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password");
writer.flush();
writer.close();
httpConn.getOutputStream().close();

InputStream responseStream = httpConn.getResponseCode() / 100 == 2
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
System.out.println(response);
}
}
package main

import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)

func main() {
client := &http.Client{}
var data = strings.NewReader(`request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password`)
req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/transaction/api", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("cache-control", "no-cache")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}

The above command returns JSON structured like this:

{
"REQUEST_ACTION": "REFUND",
"TRANS_STATUS_NAME": "APPROVED",
"TRANS_VALUE": "0.1000",
"TRANS_REQUEST_ID": 80282,
"TRANS_RECORD_ID": 78443,
"TRANS_ORDER_ID": 186434737,
"XTL_ORDER_ID": "000011112222",
"TRANS_CUR": "USD"
}

Make sure to replace req_username with your API key.

Merchants may request to refund the original sales transaction by sending CCCREDIT in the request_action parameter.

Refund Transaction Parameters

The table below only includes typical parameters sent in a simple Authorization transaction request

Parameter Required Description Data Type
req_username Required Username Alphanumeric
req_password Required Password Alphanumeric and Special Characters
transaction_type Required Service Request Action (Send “CAPTURE”) Alphanumeric
pmt_numb Required Credit Card Number Numeric

Refund Transaction Success Response Fields

These are the fields returned to the merchant when a transaction has been approved by the Payment Service.

Parameter Description
REQUEST_ACTION This will Return CAPTURE
TRANS_STATUS_NAME Transaction Status i.e APPROVED
TRANS_VALUE Transaction Amount
TRANS_REQUEST_ID Unique Transaction ID
TRANS_RECORD_ID Order ID
TRANS_ORDER_ID Extra Transaction ID
XTL_ORDER_ID Merchant Order ID
TRANS_CUR 3-Letter Currency Code

Invoices

Run in Postman

Create Invoice

To Create invoice, use this code:

require 'net/http'
require 'uri'
require 'json'

uri = URI.parse("https://api.paybybankful.com/api/invoice/create")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request["Cache-Control"] = "no-cache"
request["Authorization"] = "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT
BiNTRhMDI5"
request.body = JSON.dump({
    "email" => "[email protected]",
    "request_currency" => "USD",
    "invoiceItems" => [
        {
        "sku" => "",
        "item_name" => "API Testing999",
        "item_description" => "Description",
        "quantity" => 1,
        "rate" => 10,
        "tax_percentage" => 10
        }
    ],
    "billingDetails" => {
        "first_name" => "Mohd",
        "last_name" => "Viqar",
        "address_1" => "1205 street",
        "address_2" => "",
        "city" => "Los Angeles",
        "state" => "CA",
        "zip" => "90025",
        "country" => "US",
        "email" => "[email protected]"
    },
    "invoice_date" => "2021-10-30",
    "reference_number" => "PO-10100",
    "type_of_goods" => "service",
    "note_to_recipient" => "This is a test invoice",
    "term_conditions" => "Subject to our terms and conditions"
})

req_options = {
    use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end

# response.code
# response.body
import requests

headers = {
    'Content-Type': 'application/json',
    'cache-control': 'no-cache',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT',
}

data = '{"email":"[email protected]","request_currency":"USD","invoiceItems":[{"sku":"","item_name":"API Testing999","item_description":"","quantity":1,"rate":10,"tax_percentage":10}],"billingDetails":{"first_name":"Mohd","last_name":"Viqar","address_1":"1205 street","address_2":"","city":"Los Angeles","state":"CA","zip":"90025","country":"US","email":"[email protected]"},"invoice_date":"2021-10-30","reference_number":"PO-10100","type_of_goods":"service","note_to_recipient":"This is a test invoice","term_conditions":"Subject to our terms and conditions"}'

response = requests.post('https://api.paybybankful.com/api/invoice/create', headers=headers, data=data)
curl -X POST "https://api.paybybankful.com/api/invoice/create" \
-H 'Content-Type: application/json' \
-H "cache-control: no-cache" \
-H 'Authorization: Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT
BiNTRhMDI5' \
-d '{"email":"[email protected]","request_currency":"USD","invoiceItems":[{"sku":"","item_name":"API Testing999","item_description":"","quantity":1,"rate":10,"tax_percentage":10}],"billingDetails":{"first_name":"Mohd","last_name":"Viqar","address_1":"1205 street","address_2":"","city":"Los Angeles","state":"CA","zip":"90025","country":"US","email":"[email protected]"},"invoice_date":"2021-10-30","reference_number":"PO-10100","type_of_goods":"service","note_to_recipient":"This is a test invoice","term_conditions":"Subject to our terms and conditions"}'
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

    public static void main(String[] args) throws IOException {
        URL url = new URL("https://api.paybybankful.com/api/invoice/create");
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod("POST");

        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("cache-control", "no-cache");
        httpConn.setRequestProperty("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT");

        httpConn.setDoOutput(true);
        OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
        writer.write("{\"email\":\"[email protected]\",\"request_currency\":\"USD\",\"invoiceItems\":[{\"sku\":\"\",\"item_name\":\"API Testing999\",\"item_description\":\"\",\"quantity\":1,\"rate\":10,\"tax_percentage\":10}],\"billingDetails\":{\"first_name\":\"Mohd\",\"last_name\":\"Viqar\",\"address_1\":\"1205 street\",\"address_2\":\"\",\"city\":\"Los Angeles\",\"state\":\"CA\",\"zip\":\"90025\",\"country\":\"US\",\"email\":\"[email protected]\"},\"invoice_date\":\"2021-10-30\",\"reference_number\":\"PO-10100\",\"type_of_goods\":\"service\",\"note_to_recipient\":\"This is a test invoice\",\"term_conditions\":\"Subject to our terms and conditions\"}");
        writer.flush();
        writer.close();
        httpConn.getOutputStream().close();

        InputStream responseStream = httpConn.getResponseCode() / 100 == 2
                ? httpConn.getInputStream()
                : httpConn.getErrorStream();
        Scanner s = new Scanner(responseStream).useDelimiter("\\A");
        String response = s.hasNext() ? s.next() : "";
        System.out.println(response);
    }
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
    'Content-Type' => 'application/json',
    'cache-control' => 'no-cache',
    'Authorization' => 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
);
$data = array(
    'email' => '[email protected]',
    'request_currency' => 'USD',
    'invoiceItems[0][sku]' => '',
    'invoiceItems[0][item_name]' => 'API Testing999',
    'invoiceItems[0][item_description]' => '',
    'invoiceItems[0][quantity]' => '1',
    'invoiceItems[0][rate]' => '10',
    'invoiceItems[0][tax_percentage]' => '10',
    'billingDetails[first_name]' => 'Mohd',
    'billingDetails[last_name]' => 'Viqar',
    'billingDetails[address_1]' => '1205 street',
    'billingDetails[address_2]' => '',
    'billingDetails[city]' => 'Los Angeles',
    'billingDetails[state]' => 'CA',
    'billingDetails[zip]' => '90025',
    'billingDetails[country]' => 'US',
    'billingDetails[email]' => '[email protected]',
    'invoice_date' => '2021-10-30',
    'reference_number' => 'PO-10100',
    'type_of_goods' => 'service',
    'note_to_recipient' => 'This is a test invoice',
    'term_conditions' => 'Subject to our terms and conditions'
);
$response = Requests::post('https://api.paybybankful.com/api/invoice/create', $headers, $data);
var request = require('request');

var headers = {
    'Content-Type': 'application/json',
    'cache-control': 'no-cache',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
};

var dataString = '{"email":"[email protected]","request_currency":"USD","invoiceItems":[{"sku":"","item_name":"API Testing999","item_description":"","quantity":1,"rate":10,"tax_percentage":10}],"billingDetails":{"first_name":"Mohd","last_name":"Viqar","address_1":"1205 street","address_2":"","city":"Los Angeles","state":"CA","zip":"90025","country":"US","email":"[email protected]"},"invoice_date":"2021-10-30","reference_number":"PO-10100","type_of_goods":"service","note_to_recipient":"This is a test invoice","term_conditions":"Subject to our terms and conditions"}';

var options = {
    url: 'https://api.paybybankful.com/api/invoice/create',
    method: 'POST',
    headers: headers,
    body: dataString
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strings"
)

func main() {
    client := &http.Client{}
    var data = strings.NewReader(`{"email":"[email protected]","request_currency":"USD","invoiceItems":[{"sku":"","item_name":"API Testing999","item_description":"","quantity":1,"rate":10,"tax_percentage":10}],"billingDetails":{"first_name":"Mohd","last_name":"Viqar","address_1":"1205 street","address_2":"","city":"Los Angeles","state":"CA","zip":"90025","country":"US","email":"[email protected]"},"invoice_date":"2021-10-30","reference_number":"PO-10100","type_of_goods":"service","note_to_recipient":"This is a test invoice","term_conditions":"Subject to our terms and conditions"}`)
    req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/invoice/create", data)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("cache-control", "no-cache")
    req.Header.Set("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    bodyText, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", bodyText)
}

The above command returns SUCCESS JSON structured like this:

{
    "data": {
        "invoiceId": 10351,
        "paymentLink":"https://api.paybybankful.com/invoice/view?token=862b1a24cc45c51a2f44e444fabc1682172c5a30384a01932853529edb62bd0af403cfa217cd8140430906b0653b27c8",
        "shortLink": "https://api.paybybankful.com/pwp/B3QgrbUNdGzJG"
    },
    "status": "Success",
    "ts": "2021-11-01T21:43:53.247Z"
}

The above command returns FAILED JSON structured like this:

{
    "errorMessage": "Merchant not found!.",
    "status": "Failed",
    "ts": "2021-11-01T22:31:13.664Z"
}

Make sure to replace req_username with your API key.

Location

The API is located at: https://api.paybybankful.com/api/invoice/create

Method

POST

Content-Type:

application/json

Header Parameters

Field Description Data Type Required
Authorization Basic Auth username + apiKey Alphanumeric Y

Body Parameters

The table below only includes typical parameters sent in a create Invoice request

Field Description Data Type Required
req_username Bankful Merchant Username Alphanumeric N
req_password Bankful Merchant Password Alphanumeric and Special Characters N
merchant_id Bankful merchant id Numeric Y
email Customer’s Email Address Alphanumeric Y
request_currency 3-letter ISO-4217 Code Alphanumeric
Example: USD
Y
invoiceItems Invoice items (Object of array).
You can add multiple invoiceItems
Invoices Array Y
billingDetails Billing Details
Billing Info
Object N
shippingDetails Shipping Details
Shipping Info
Object N
invoice_date Invoice Date
Default to current date
Alphanumeric (YYYY-MM-DD)
Example: “2021-10-31”
N
reference_number Invoice reference number Alphanumeric N
type_of_goods Type of goods [‘service’, ’shippable_goods’]
Default to shippable_goods
Alphanumeric N
note_to_recipient Invoice Note Alphanumeric N
term_conditions Invoice Terms & conditions Alphanumeric N

Create Invoice SUCCESS Response Fields

These are the fields returned to the merchant when an invoice successfully created in Bankful.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
data Invoice Data Object

Create Invoice FAILED Response Fields

These are the fields returned to the merchant when there is an error in creating an invoice in Bankful.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
errorMessage Error Message

List Invoices

To List invoice, use this code:

require 'net/http'
require 'uri'
require 'json'

uri = URI.parse("https://api.paybybankful.com/api/invoice/list")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request["Authorization"] = "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OTBiNTRhMDI5"
request.body = JSON.dump({
    "merchant_id" => 11273,
    "offset" => 1,
    "limit" => 20,
    "filter" => {
        "start_date" => "2021-11-01",
        "end_date" => "2021-11-11"
    }
})

req_options = {
use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end

# response.code
# response.body
import requests

headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT',
}

data = '{"merchant_id": 11273,"offset": 1,"limit": 20,"filter": {"start_date": "2021-11-01","end_date": "2021-11-11"}}'

response = requests.post('https://api.paybybankful.com/api/invoice/list', headers=headers, data=data)
curl -X POST 'https://api.paybybankful.com/api/invoice/list' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT
BiNTRhMDI5' \
-d '{"merchant_id": 11273,"offset": 1,"limit": 20,"filter": {"start_date": "2021-11-01","end_date": "2021-11-11"}}'
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

    public static void main(String[] args) throws IOException {
        URL url = new URL("https://api.paybybankful.com/api/invoice/list");
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod("POST");

        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT");

        httpConn.setDoOutput(true);
        OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
        writer.write("{\"merchant_id\": 11273,\"offset\": 1,\"limit\": 20,\"filter\": {\"start_date\": \"2021-11-01\",\"end_date\": \"2021-11-11\"}}");
        writer.flush();
        writer.close();
        httpConn.getOutputStream().close();

        InputStream responseStream = httpConn.getResponseCode() / 100 == 2
                ? httpConn.getInputStream()
                : httpConn.getErrorStream();
        Scanner s = new Scanner(responseStream).useDelimiter("\\A");
        String response = s.hasNext() ? s.next() : "";
        System.out.println(response);
    }
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
    'Content-Type' => 'application/json',
    'Authorization' => 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
);
$data = array(
    'merchant_id' => '11273',
    'offset' => '1',
    'limit' => '20',
    'filter[start_date]' => '2021-11-01',
    'filter[end_date]' => '2021-11-11'
);
$response = Requests::post('https://api.paybybankful.com/api/invoice/list', $headers, $data);
var request = require('request');

var headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
};

var dataString = '{
    "merchant_id": 11273,
    "offset": 1,
    "limit": 20,
    "filter": {
        "start_date": "2021-11-01",
        "end_date": "2021-11-11"
    }
}';

var options = {
    url: 'https://api.paybybankful.com/api/invoice/list',
    method: 'POST',
    headers: headers,
    body: dataString
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strings"
)

func main() {
    client := &http.Client{}
    var data = strings.NewReader(`{"merchant_id": 11273,"offset": 1,"limit": 20,"filter": {"start_date": "2021-11-01","end_date": "2021-11-11"}}`)
    req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/invoice/list", data)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    bodyText, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", bodyText)
}

The above command returns SUCCESS JSON structured like this:

{
	"status": "Success",
	"ts": "2021-11-12T22:03:37.362Z",
	"data": {
		"invoices": [{
				"id": 10356,
				"invoice_date": "2021-11-01T00:00:00.000Z",
				"merchant_id": 11273,
				"due_date": "2021-11-05T15:56:11.000Z",
				"expire_on": "2021-11-12T15:56:11.000Z",
				"amount": "5.05",
				"reference_number": "PO-10100",
				"transaction_record_id": null,
				"currency": "USD",
				"tax": "0.05",
				"discount": "0.00",
				"status": "ATTEMPTED",
				"transaction_date": null,
				"shipping_charge": "0.00",
				"customer_first_name": "frantz",
				"customer_last_name": "romain",
				"customer_email": "[email protected]",
				"error_message": null,
				"paymentLink": "https://api.paybybankful.com/invoice/view?token=e0f53440399af78019a5414e3c5315f8a7cca241738e7669738cd06f264f9813cb031f22086694105563ca64c75253de"
			},
			{
				"id": 10355,
				"invoice_date": "2021-10-30T00:00:00.000Z",
				"merchant_id": 11273,
				"due_date": "2021-11-04T22:49:34.000Z",
				"expire_on": "2021-11-11T22:49:34.000Z",
				"amount": "11.00",
				"reference_number": "PO-10100",
				"transaction_record_id": null,
				"currency": "USD",
				"tax": "1.00",
				"discount": "0.00",
				"status": "OWED",
				"transaction_date": null,
				"shipping_charge": "0.00",
				"customer_first_name": "Mohd",
				"customer_last_name": "Viqar",
				"customer_email": "[email protected]",
				"error_message": null,
				"paymentLink": "https://api.paybybankful.com/invoice/view?token=e0f53440399af78019a5414e3c5315f8a7cca241738e7669738cd06f264f98135f0896726d97672612c3a238e14f78d6"
			}
		],
		"limit": 20,
		"offset": 0,
		"count": 2,
		"filter": {
			"start_date": "2021-11-01",
			"end_date": "2021-11-11"
		}
	}
}

The above command returns FAILED JSON structured like this:

{
    "errorMessage": "Merchant not found!.",
    "status": "Failed",
    "ts": "2021-11-01T22:31:13.664Z"
}

Make sure to replace req_username with your API key.

Location

The API is located at: https://api.paybybankful.com/api/invoice/list

Method

POST

Content-Type:

application/json

Header Parameters

Field Description Data Type Required
Authorization Basic Auth username + apiKey Alphanumeric Y

Body Parameters

The table below only includes typical parameters sent in a invoice list request

Field Description Data Type Required
req_username Bankful Merchant Username
Required if Basic Authorization is not used
Alphanumeric N
req_password Bankful Merchant Password
Required if Basic Authorization is not used
Alphanumeric and Special Characters N
merchant_id Bankful merchant id Numeric Y
offset Offset Numeric N
limit Page size limit Numeric N
filter Filter Object Object N

Invoice List SUCCESS Response Fields

These are the fields returned to the merchant when successfully getting invoices.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
data Invoice Data Object

List Invoice FAILED Response

These are the fields returned to the merchant when there is an error in invoice listing Bankful.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
errorMessage Error Message

Invoice By Id

To Get Invoice By Id, use this code:

require 'net/http'
require 'uri'
require 'json'

uri = URI.parse("https://api.paybybankful.com/api/invoice/status")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request["Authorization"] = "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT
BiNTRhMDI5"
request.body = JSON.dump({
    "invoice_id" => 10356,
    "merchant_id" => 11273
})

req_options = {
    use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end

# response.code
# response.body
import requests

headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT',
}

data = '{"invoice_id": 10356,"merchant_id": 11273}'

response = requests.post('https://api.paybybankful.com/api/invoice/status', headers=headers, data=data)
curl -X POST 'https://api.paybybankful.com/api/invoice/status' \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OTBiNTRhMDI5' \
-d '{"invoice_id": 10356,"merchant_id": 11273}'
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

    public static void main(String[] args) throws IOException {
        URL url = new URL("https://api.paybybankful.com/api/invoice/status");
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod("POST");

        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT");

        httpConn.setDoOutput(true);
        OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
        writer.write("{\"invoice_id\": 10356,\"merchant_id\": 11273}");
        writer.flush();
        writer.close();
        httpConn.getOutputStream().close();

        InputStream responseStream = httpConn.getResponseCode() / 100 == 2
                ? httpConn.getInputStream()
                : httpConn.getErrorStream();
        Scanner s = new Scanner(responseStream).useDelimiter("\\A");
        String response = s.hasNext() ? s.next() : "";
        System.out.println(response);
    }
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
    'Content-Type' => 'application/json',
    'Authorization' => 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
);
$data = array(
    'invoice_id' => '10356',
    'merchant_id' => '11273'
);
$response = Requests::post('https://api.paybybankful.com/api/invoice/status', $headers, $data);
var request = require('request');

var headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT'
};

var dataString = '{"invoice_id": 10356,"merchant_id": 11273}';

var options = {
    url: 'https://api.paybybankful.com/api/invoice/status',
    method: 'POST',
    headers: headers,
    body: dataString
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);
package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strings"
)

func main() {
    client := &http.Client{}
    var data = strings.NewReader(`{"invoice_id": 10356,"merchant_id": 11273}`)
    req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/invoice/status", data)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Basic cHJhZGVlcDo2MzNjOWQyNWNkNTUzOWYyMTY3ODQxMjQyOGE1NzY3MWEzODg2NwZhYTFmNzhkODg5NTU3NzA3OT")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    bodyText, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s\n", bodyText)
}

The above command returns SUCCESS JSON structured like this:

{
	"data": {
		"invoice": {
			"id": 10356,
			"invoice_date": "2021-11-01T00:00:00.000Z",
			"due_date": "2021-11-05T15:56:11.000Z",
			"merchant_id": 11273,
			"expire_on": "2021-11-12T15:56:11.000Z",
			"amount": "5.05",
			"reference_number": "PO-10100",
			"transaction_record_id": null,
			"currency": "USD",
			"tax": "0.05",
			"discount": "0.00",
			"status": "ATTEMPTED",
			"transaction_date": null,
			"shipping_charge": "0.00",
			"customer_first_name": "frantz",
			"customer_last_name": "romain",
			"customer_email": "[email protected]",
			"error_message": null,
			"transactionCustomer": {
				"first_name": "frantz",
				"last_name": "romain",
				"email": "[email protected]"
			}
		}
	},
	"status": "Success",
	"ts": "2021-11-12T22:18:36.926Z"
}

The above command returns FAILED JSON structured like this:

{
    "errorMessage": "Invoice not found with invoice ID 1035600",
    "status": "Failed",
    "ts": "2021-11-12T22:23:47.783Z"
}

Make sure to replace req_username with your API key.

Location

The API is located at: https://api.paybybankful.com/api/invoice/status

Method

POST

Content-Type:

application/json

Header Parameters

Field Description Data Type Required
Authorization Basic Auth username + apiKey Alphanumeric Y

Body Parameters

The table below only includes typical parameters sent in a invoice status request

Field Description Data Type Required
req_username Bankful Merchant Username
Required if Basic Authorization is not used
Alphanumeric N
req_password Bankful Merchant Password
Required if Basic Authorization is not used
Alphanumeric and Special Characters N
merchant_id Bankful merchant id Numeric Y
invoice_id Bankful invoice id Numeric Y

Invoice by Id SUCCESS Response Fields

These are the fields returned to the merchant when successfully getting invoices.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
data Invoice Data Object

Invoice by Id FAILED Response

These are the fields returned to the merchant when there is an error in invoice listing Bankful.

Field Name Description
status Api Request Status, Example : Success
ts UTC Timestamp
errorMessage Error Message

Webhook for Bankful Invoice

Bankful has an option to update the external system via webhooks. An integration partner can configure the webhook by contacting the admin and giving them the external URLs which are enabled to receive the payload.

● The external URL must accept POST requests.
● The external URL should give the response http status 200 OK or in the 2xx range.
● Bankful webhook will be retried 3 times, if it receives a http status code other than 2xx http status.

The webhook payload is hashed and a signature is generated and sent as an HTTP header for webhook verification.

Verify the webhook

Webhooks can be verified by calculating a digital signature. Each webhook request includes a base64-encoded X-Bankful-Hmac-SHA256 header, which is generated using the Integration Partner’s API Key along with the data sent in the request.

Verify webhook source

To verify that the request came from Bankful, compute the HMAC digest according to the following algorithm and compare it to the value in the x-bankful-hmac-sha256 header. If they match, then you can be sure that the webhook was sent from Bankful. The HMAC digest must be verified before the webhook’s payload is used.

Ensure that the webhook’s payload is sorted by it’s key before hashing and encoding it for comparison.

Steps to compare and verify the webhook

● Ignore non-empty parameters i.e. keys with empty/null values.
● Sort the payload object by its keys.
● Stringify the object.
● Create a SHA256 hash using stringified output from above and “Api Key” as secret.
● Encode Base64 the hashed output.
● Compare it to the signature from the HMAC header (“x-bankful-hmac-sha256”).

Invoice Payload (JSON)

Invoice Payload Example:


Headers:
{
    "x-bankful-hmac-sha256": "90744b7ffa9cd4b12d05f90344d1f4972c44b8439000fbdd78157019b57c8be1"
}

body:
{
    "invoice_id": 10411,
    "merchant_id": 11548,
    "amount": "4.11",
    "transaction_record_id": 2329280,
    "currency": "USD",
    "status": "PAID"
}

The table below only includes typical parameters sent in a invoice status request

Field Description Data Type
invoice_id Bankful invoice id Numeric
merchant_id Bankful merchant id Numeric
amount Invoice amount Alphanumeric
transaction_record_id Bankful transaction ID Numeric
currency 3-letter ISO-4217 Code Alphanumeric
Example: USD

Appendix Invoice Objects

Invoice Item Array

Invoice Item Object

Field Description Data Type Required
sku Product SKU Alphanumeric N
item_name Invoice Item Name Alphanumeric and Special Characters Y
item_description Invoice Item Description Alphanumeric Y
quantity Invoice Item Quantity Numeric
Example: 3
Y
rate Item Amount Numeric
Example: 13.50
Y
tax_percentage Tax Amount Numeric
Example: 5.00
N

Billing Details

Customer Billing Information

Field Description Data Type Required
first_name First Name Alphanumeric N
last_name Last Name Alphanumeric N
address_1 Billing Street Address Alphanumeric Y
address_2 Billing Street Address 2 Alphanumeric N
city Billing City Alphanumeric Y
state Billing State 2-letter State or Territory Code Y
zip Billing Postal/ZIP code Alphanumeric Y
country Billing Country 2-letter Country Code ISO 3166-1 alpha-2 Y
email Email Alphanumeric
Example: [email protected]
N
phone Phone Number Numeric N

Shipping Details

Customer Shipping Information

Field Description Data Type Required
first_name First Name Alphanumeric N
last_name Last Name Alphanumeric N
address_1 Shipping Street Address Alphanumeric Y
address_2 Shipping Street Address 2 Alphanumeric N
city Shipping City Alphanumeric Y
state Shipping State 2-letter State or Territory Code Y
zip Shipping Postal/ZIP code Alphanumeric Y
country Shipping Country 2-letter Country Code ISO 3166-1 alpha-2 Y
email Email Alphanumeric
Example: [email protected]
N
phone Phone Number Numeric N

Invoice Data Object

Invoice Data Returned with API call

Field Description
invoiceId Bankful Invoice Id
paymentLink Bankful Invoice Payment Link
shortLink Bankful Invoice Payment Short Link

Invoice list filter

Invoice list filter object

Field Description Data Type Required
start_date Start date Alphanumeric(YYYY-MM-DD)
Example:“2021-10-31”
N
end_date End date Alphanumeric(YYYY-MM-DD)
Example:“2021-10-31”
N
customer_first_name Customer First Name Alphanumeric N
customer_last_name Customer Last Name Alphanumeric N
customer_email Customer email Alphanumeric N
invoice_id Bankful Invoice Id Numeric N

Invoice list response data

Invoice Data Returned with API call

Field Description
invoices Object of array
limit Page size limit
offset Page number
count Record count
filter Filter

Invoices Object

Field Description
id Bankful invoice id
invoice_date Invoice date
merchant_id Bankful merchant id
due_date Invoice due date
expire_on Invoice expire on
amount Invoice amount
reference_number Invoice reference number
transaction_record_id Bankful transaction record id
currency Currency
tax Tax amount
discount Discount amount
status Invoice status
transaction_date Invoice payment date
shipping_charge Shipping charge amount
customer_first_name Customer first name
customer_last_name Customer last name
customer_email Customer email
error_message Transaction error message
paymentLink Bankful Invoice Payment Link

Filter

Field Description
start_date Start date
end_date End date
customer_first_name Customer First Name
customer_last_name Customer Last Name
customer_email Customer email
invoice_id Bankful Invoice Id

Invoice Status response data

Field Description
invoice Invoice Object

Invoice Status object

Field Description
id Bankful invoice id
invoice_date Invoice date
merchant_id Bankful merchant id
due_date Invoice due date
expire_on Invoice expire on
amount Invoice amount
reference_number Invoice reference number
transaction_record_id Bankful transaction record id
currency Currency
tax Tax amount
discount Discount amount
status Invoice status
transaction_date Invoice payment date
shipping_charge Shipping charge amount
customer_first_name Customer first name
customer_last_name Customer last name
customer_email Customer email
error_message Transaction error message
transactionCustomer Customer object

Customer object

Field Description
first_name Customer first name
last_name Customer last name
email Customer email

Hosted Payment Page

The Hosted Payment Page integrates your shopping cart with Bankful Hosted page Shopping cart must redirect customers to Bankful hosted page to complete the payment.

Run in Postman

Getting Started

To begin integration with Bankful, you would need to get the Bankful sandbox credentials The checkout process, including what the customer sees and doesn’t see, has six stages:

  1. The customer places an order with a Shopping Cart. They enter their email, shipping address and delivery method, and then select Bankful gateway as their payment option.

  2. On the last step of Cart Checkout the customer is redirected to Bankful gateway’s URL using a POST request along with Request Values. Bankful gateway verifies the signature value and presents its own hosted payments page to the customer (see Signing Mechanism).

  3. The customer pays for the order on the Bankful hosted payment page.

  4. It is best practice for your payment gateway to also POST a callback asynchronously to url_callback with the same Response Values. This ensures that orders can be completed even in cases where the customer’s connection to Cart’s is terminated prematurely. Callbacks are in HTTP POST x-www-form-urlencoded format.

  5. The order is complete, and a thank-you page is shown to customer:
    • HTTP 200 indicates successful receipt of a callback by Bankful. If url_callback url_callback is provided in the request
    • Shopping Cart should handle callback request carefully so that duplicate callback requests for the same transaction are ignored

Location

Live Hosted Page is located at: https://api.paybybankful.com/front-calls/go-in/hosted-page-pay Sandbox Hosted Page is located at : https://api.dev1.bankfulportal.com/front-calls/go-in/hosted-page-pay

Method

Post

Content-Type

application/x-www-form-urlencoded

Encoding

Payment Service API uses 8-bit Unicode Transformation Format as described in the ISO/ISE 10646. Merchants are required to send Service requests with content-type, “application/x-www-form-urlencoded”; and charset, “iso-8859-1,*, utf-8” using HTTP Post method.

Gateway signing mechanism

All requests and responses must be signed/verified using HMAC-SHA256 where: • Key : is a value known to both the Shopping Cart/merchant and Bankful. This is typically the Bankful Gateway “Password" field for the merchant. • Message: is a string of all key-value pairs being sent to Bankful in the hosted payment request , sorted alphabetically, and concatenated without separators. Resulting codes must be hex-encoded and passed as the value of the signature field in the payment request payload.

Sales Transaction

To initiate request, use this code:

curl -X POST "http://localhost:50001/front-calls/go-in/hosted-page-pay" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'amount=1&bill_addr=4%2F22&bill_addr_2=Add&bill_addr_city=California&bill_addr_country=US&bill_addr_state=CA&bill_addr_zip=90025&url_callback=http%3A%2F%2Flocalhost%3A3000%2Fcall-back-success-url&cust_email=test%40test.com&cust_fname=Test&cust_lname=Test&cust_phone=01234567890&req_username=sandbox_username&request_currency=USD&url_cancel=http%3A%2F%2Flocalhost%3A3000%2Fdecline-payment&url_complete=http%3A%2F%2Flocalhost%3A3000%2Fsuccess-payment&url_failed=http%3A%2F%2Flocalhost%3A3000%2Ffailed-payment&url_pending=http%3A%2F%2Flocalhost%3A3000%2Fpending-payment&xtl_order_id=123456&signature=794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8'
require "uri"
require "net/http"

url = URI("http://localhost:50001/front-calls/go-in/hosted-page-pay")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request["Cookie"] = "SESS_P_ID=s%3AMamaexm7uDRwnAjErj_-uzjkJIDd26xw.JAe8A6Nqz%2BvdAo9Q1sl%2F1jiFlfGALiENFw6Z8R1pJ7I"
request.body = "amount=1&bill_addr=4%2F22&bill_addr_2=Add&bill_addr_city=California&bill_addr_country=US&bill_addr_state=CA&bill_addr_zip=90025&url_callback=http%3A%2F%2Flocalhost%3A3000%2Fcall-back-success-url&cust_email=test%40test.com&cust_fname=Test&cust_lname=Test&cust_phone=01234567890&req_username=sandbox_username&request_currency=USD&url_cancel=http%3A%2F%2Flocalhost%3A3000%2Fdecline-payment&url_complete=http%3A%2F%2Flocalhost%3A3000%2Fsuccess-payment&url_failed=http%3A%2F%2Flocalhost%3A3000%2Ffailed-payment&url_pending=http%3A%2F%2Flocalhost%3A3000%2Fpending-payment&xtl_order_id=123456&signature=794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8"

response = http.request(request)
puts response.read_body
import requests

headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
}

data = {
  'amount': '1',
  'bill_addr': '4/22',
  'bill_addr_2': 'Add',
  'bill_addr_city': 'California',
  'bill_addr_country': 'US',
  'bill_addr_state': 'CA',
  'bill_addr_zip': '90025',
  'url_callback': 'http://localhost:3000/call-back-success-url',
  'cust_email': '[email protected]',
  'cust_fname': 'Test',
  'cust_lname': 'Test',
  'cust_phone': '01234567890',
  'req_username': 'sandbox_username',
  'request_currency': 'USD',
  'url_cancel': 'http://localhost:3000/decline-payment',
  'url_complete': 'http://localhost:3000/success-payment',
  'url_failed': 'http://localhost:3000/failed-payment',
  'url_pending': 'http://localhost:3000/pending-payment',
  'xtl_order_id': '123456',
  'signature': '794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8'
}

response = requests.post('http://localhost:50001/front-calls/go-in/hosted-page-pay', headers=headers, data=data)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

	public static void main(String[] args) throws IOException {
		URL url = new URL("http://localhost:50001/front-calls/go-in/hosted-page-pay");
		HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
		httpConn.setRequestMethod("POST");

		httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

		httpConn.setDoOutput(true);
		OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
		writer.write("amount=1&bill_addr=4%2F22&bill_addr_2=Add&bill_addr_city=California&bill_addr_country=US&bill_addr_state=CA&bill_addr_zip=90025&url_callback=http%3A%2F%2Flocalhost%3A3000%2Fcall-back-success-url&cust_email=test%40test.com&cust_fname=Test&cust_lname=Test&cust_phone=01234567890&req_username=sandbox_username&request_currency=USD&url_cancel=http%3A%2F%2Flocalhost%3A3000%2Fdecline-payment&url_complete=http%3A%2F%2Flocalhost%3A3000%2Fsuccess-payment&url_failed=http%3A%2F%2Flocalhost%3A3000%2Ffailed-payment&url_pending=http%3A%2F%2Flocalhost%3A3000%2Fpending-payment&xtl_order_id=123456&signature=794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8");
		writer.flush();
		writer.close();
		httpConn.getOutputStream().close();

		InputStream responseStream = httpConn.getResponseCode() / 100 == 2
				? httpConn.getInputStream()
				: httpConn.getErrorStream();
		Scanner s = new Scanner(responseStream).useDelimiter("\\A");
		String response = s.hasNext() ? s.next() : "";
		System.out.println(response);
	}
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
    'Content-Type' => 'application/x-www-form-urlencoded'
);
$data = array(
    'amount' => '1',
    'bill_addr' => '4/22',
    'bill_addr_2' => 'Add',
    'bill_addr_city' => 'California',
    'bill_addr_country' => 'US',
    'bill_addr_state' => 'CA',
    'bill_addr_zip' => '90025',
    'url_callback' => 'http://localhost:3000/call-back-success-url',
    'cust_email' => '[email protected]',
    'cust_fname' => 'Test',
    'cust_lname' => 'Test',
    'cust_phone' => '01234567890',
    'req_username' => 'sandbox_username',
    'request_currency' => 'USD',
    'url_cancel' => 'http://localhost:3000/decline-payment',
    'url_complete' => 'http://localhost:3000/success-payment',
    'url_failed' => 'http://localhost:3000/failed-payment',
    'url_pending' => 'http://localhost:3000/pending-payment',
    'xtl_order_id' => '123456',
    'signature' => '794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8'
);
$response = Requests::post('http://localhost:50001/front-calls/go-in/hosted-page-pay', $headers, $data);
var request = require('request');

var headers = {
    'Content-Type': 'application/x-www-form-urlencoded'
};

var dataString = 'amount=1&bill_addr=4%2F22&bill_addr_2=Add&bill_addr_city=California&bill_addr_country=US&bill_addr_state=CA&bill_addr_zip=90025&url_callback=http%3A%2F%2Flocalhost%3A3000%2Fcall-back-success-url&cust_email=test%40test.com&cust_fname=Test&cust_lname=Test&cust_phone=01234567890&req_username=sandbox_username&request_currency=USD&url_cancel=http%3A%2F%2Flocalhost%3A3000%2Fdecline-payment&url_complete=http%3A%2F%2Flocalhost%3A3000%2Fsuccess-payment&url_failed=http%3A%2F%2Flocalhost%3A3000%2Ffailed-payment&url_pending=http%3A%2F%2Flocalhost%3A3000%2Fpending-payment&xtl_order_id=123456&signature=794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8';

var options = {
    url: 'http://localhost:50001/front-calls/go-in/hosted-page-pay',
    method: 'POST',
    headers: headers,
    body: dataString
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func main() {
	client := &http.Client{}
	var data = strings.NewReader(`amount=1&bill_addr=4%2F22&bill_addr_2=Add&bill_addr_city=California&bill_addr_country=US&bill_addr_state=CA&bill_addr_zip=90025&url_callback=http%3A%2F%2Flocalhost%3A3000%2Fcall-back-success-url&cust_email=test%40test.com&cust_fname=Test&cust_lname=Test&cust_phone=01234567890&req_username=sandbox_username&request_currency=USD&url_cancel=http%3A%2F%2Flocalhost%3A3000%2Fdecline-payment&url_complete=http%3A%2F%2Flocalhost%3A3000%2Fsuccess-payment&url_failed=http%3A%2F%2Flocalhost%3A3000%2Ffailed-payment&url_pending=http%3A%2F%2Flocalhost%3A3000%2Fpending-payment&xtl_order_id=123456&signature=794870cb9d7eb1e62b034041a4f02521485a7a984bbb62031c70f87433892fe8`)
	req, err := http.NewRequest("POST", "http://localhost:50001/front-calls/go-in/hosted-page-pay", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	bodyText, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", bodyText)
}

Make sure to replace req_username with your API key.

The table below only includes typical parameters sent in a simple Sales transaction request

Parameter Required Description Data Type
req_username Required Bankful Gateway Username Alphanumeric
transaction_type Required Service Request Action (Send “CAPTURE”) Alphanumeric
amount Required Transaction Amount Numeric
request_currency Required 3-letter Currency Code Alphanumeric
Example: USD
cust_fname Optional** Cardholder’s First Name Alphanumeric
cust_lname Optional** Cardholder’s Last Name Alphanumeric
cust_email Optional** Cardholder’s Email Address Alphanumeric
cust_phone Optional** Cardholder’s Phone Number Numeric
bill_addr Optional** Cardholder Billing Street Address Alphanumeric
bill_addr_2 Optional** Cardholder Billing Street Address 2 Alphanumeric
bill_addr_city Optional** Cardholder’s Billing City Alphanumeric
bill_addr_state Optional** Cardholder’s Billing State 2-letter State or Territory Code
bill_addr_zip Optional** Cardholder’s Billing Postal/ZIP code Alphanumeric
bill_addr_country Optional** Cardholder’s Billing Country 2-letter Country Code ISO 3166-1 alpha-2
xtl_order_id Optional** Cart Order/reference ID Alphanumeric
url_cancel Required URL to which customer must be redirected when they wish to quit payment flow and return to the Cart. URL
url_complete Required URL to which customer must be redirected upon successfully completing payment flow. URL
url_failed Required URL to which customer must be redirected upon failing the payment flow. URL
url_callback Required Callback webhook URL to which a callback notification should be sent asynchronously. URL
url_pending Required Pending url URL
signature Required Signature Alphanumeric
cart_name Required Cat Name (Send “Hosted-Page”) String

Generate Signature

  1. Sort non empty request payload alphabetically and create string
  2. Create signature using SHA256
  3. Example:

    String:
    amount1bill_addr4/22bill_addr_2Addbill_addr_cityCaliforniabill_addr_countryUSbill_addr_stateCAbill_addr_zip90025url_callbackhttp://localhost:3000/[email protected]_fnameTestcust_lnameTestcust_phone01234567890req_usernamesandbox_usernamerequest_currencyUSDurl_cancelhttp://localhost:3000/decline-paymenturl_completehttp://localhost:3000/success-paymenturl_failedhttp://localhost:3000/failed-paymenturl_pendinghttp://localhost:3000/pending-paymentxtl_order_id123456

    Generated Signature:
    5bdb5b954b0291cfdb0de2a277142140fd11d93298ba614f3486ee5d92d0a094

Sales Transaction Success Response Fields

The above command returns APPROVED JSON structured like this:

{
   "REQUEST_ACTION": "CAPTURE",
   "TRANS_STATUS_NAME": "APPROVED",
   "TRANS_VALUE": "1.0000",
   "TRANS_REQUEST_ID": 1272,
   "TRANS_RECORD_ID": 79154,
   "TRANS_ORDER_ID": 0980982121,
   "XTL_ORDER_ID": "000011112222",
   "TRANS_CUR": "USD",
   "TIMESTAMP": "2021-05-06T11:16:50Z",
   "SIGNATURE":"0e3c70ceef918cee019dd261a058bd111b7f85ca35dca01bb3c75327af06d284"
}

These are the fields returned to url_complete as query params to the merchant when a transaction has been approved by the Payment Service.

Field Name Description
REQUEST_ACTION This will return CAPTURE
TRANS_STATUS_NAME Transaction Status
APPROVED : Transaction has been approved.
TRANS_VALUE Transaction amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
TIMESTAMP Timestamp
SIGNATURE SIgnature***

Sales Transaction DECLINED Response Fields

The above command returns DECLINED JSON structured like this:

{
   "REQUEST_ACTION": "CAPTURE",
   "TRANS_STATUS_NAME": "DECLINED",
   "TRANS_VALUE": "1.0000",
   "TRANS_REQUEST_ID": 1272,
   "TRANS_RECORD_ID": 79154,
   "TRANS_ORDER_ID": 0980982121,
   "XTL_ORDER_ID": "000011112222",
   "TRANS_CUR": "USD",
   "API_ADVICE": "DECLINED",
   "SERVICE_ADVICE": "DECLINED",
   "PROCESSOR_ADVICE": "DECLINED",
   "ERROR_MESSAGE": "DECLINED",
   "TIMESTAMP": "2021-05-06T11:16:50Z",
   "SIGNATURE":"0e3c70ceef918cee019dd261a058bd111b7f85ca35dca01bb3c75327af06d284"
}

These are the fields returned to the merchant when a transaction has been declined by the Payment Service.

Field Name Description
REQUEST_ACTION This will return CAPTURE
TRANS_STATUS_NAME Transaction Status
DECLINED : Transaction has been declined.
TRANS_VALUE Transaction amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
TIMESTAMP Timestamp
SIGNATURE SIgnature***
API_ADVICE API advice message
SERVICE_ADVICE Service advice message
PROCESSOR_ADVICE Processor advice message
ERROR_MESSAGE Error message

Sales Transaction Pending Response Fields

The above command returns PENDING JSON structured like this:

{
   "REQUEST_ACTION": "CAPTURE",
   "TRANS_STATUS_NAME": "PENDING",
   "TRANS_VALUE": "1.0000",
   "TRANS_REQUEST_ID": 1272,
   "TRANS_RECORD_ID": 79154,
   "TRANS_ORDER_ID": 0980982o121,
   "XTL_ORDER_ID": "000011112222",
   "TRANS_CUR": "USD",
   "TIMESTAMP": "2021-05-06T11:16:50Z",
   "SIGNATURE": "0e3c70ceef918cee019dd261a058bd111b7f85ca35dca01bb3c75327af06d284"

}

These are the fields returned to the merchant when a transaction has been pending by the Payment Service.

Field Name Description
REQUEST_ACTION This will return CAPTURE
TRANS_STATUS_NAME Transaction Status
PENDING : Transaction is in PENDING State.
TRANS_VALUE Transaction amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
TIMESTAMP Timestamp
SIGNATURE SIgnature***

*** Signature Verify

  1. Remove “SIGNATURE” from response
  2. Sort payload alphabetically and create string
  3. Create signature using SHA256
  4. Example:

    String:

    API_ADVICEDECLINEERROR_MESSAGEDECLINEPROCESSOR_ADVICEDECLINEREQUEST_ACTIONCAPTURESERVICE_ADVICEDECLINETIMESTAMP2021-05-10T12:30:10ZTRANS_CURUSDTRANS_ORDER_ID187697436TRANS_RECORD_ID1442805TRANS_REQUEST_ID1364252TRANS_STATUS_NAMEDECLINEDTRANS_VALUE0.0100XTL_ORDER_ID1212

    Generated Signature:

    83de3c4a27f597f3412414e6665d4f517c4cb97a6698628bf599fade4e1a22c4

Refund Hosted

Merchants may request to refund the original sales transaction by sending CCCREDIT in the request_action parameter.

Refund Transaction Parameters

Refund Transaction Request:

curl -X POST "https://api.paybybankful.com/api/transaction/api" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password'

require 'net/http'
require 'uri'

uri = URI.parse("https://api.paybybankful.com/api/transaction/api")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/x-www-form-urlencoded"
request.set_form_data(
  "amount" => "0.1",
  "req_password" => "sandbox_password",
  "req_username" => "sandbox_username",
  "request_action" => "CCCREDIT",
  "request_ref_po_id" => "186434737",
)

req_options = {
  use_ssl: uri.scheme == "https",
}

response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(request)
end

# response.code
# response.body
import requests

headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
}

data = {
  'request_ref_po_id': '186434737',
  'request_action': 'CCCREDIT',
  'amount': '0.1',
  'req_username': 'sandbox_username',
  'req_password': 'sandbox_password'
}

response = requests.post('https://api.paybybankful.com/api/transaction/api', headers=headers, data=data)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {

	public static void main(String[] args) throws IOException {
		URL url = new URL("https://api.paybybankful.com/api/transaction/api");
		HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
		httpConn.setRequestMethod("POST");

		httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

		httpConn.setDoOutput(true);
		OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
		writer.write("request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password");
		writer.flush();
		writer.close();
		httpConn.getOutputStream().close();

		InputStream responseStream = httpConn.getResponseCode() / 100 == 2
				? httpConn.getInputStream()
				: httpConn.getErrorStream();
		Scanner s = new Scanner(responseStream).useDelimiter("\\A");
		String response = s.hasNext() ? s.next() : "";
		System.out.println(response);
	}
}
<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
    'Content-Type' => 'application/x-www-form-urlencoded'
);
$data = array(
    'request_ref_po_id' => '186434737',
    'request_action' => 'CCCREDIT',
    'amount' => '0.1',
    'req_username' => 'sandbox_username',
    'req_password' => 'sandbox_password'
);
$response = Requests::post('https://api.paybybankful.com/api/transaction/api', $headers, $data);
var request = require('request');

var headers = {
    'Content-Type': 'application/x-www-form-urlencoded'
};

var dataString = 'request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password';

var options = {
    url: 'https://api.paybybankful.com/api/transaction/api',
    method: 'POST',
    headers: headers,
    body: dataString
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func main() {
	client := &http.Client{}
	var data = strings.NewReader(`request_ref_po_id=186434737&request_action=CCCREDIT&amount=0.1&req_username=sandbox_username&req_password=sandbox_password`)
	req, err := http.NewRequest("POST", "https://api.paybybankful.com/api/transaction/api", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	bodyText, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", bodyText)
}
Parameter Required Description Data Type
req_username Required Bankful Gateway Username Alphanumeric
req_password Required Bankful Gateway Password Alphanumeric
request_action Required Service Request Action (Send “CCCREDIT”) Alphanumeric
amount Required Transaction Amount to Refund Numeric
request_ref_po_id Required To do a refund request, send the Order ID
(TRANS_ORDER_ID) of the original transaction in the
request_ref_po_id parameter.
Alphanumeric
url_callback Optional Callback webhook url String
signature Required Cardholder’s Last Name Alphanumeric

Refund Transaction Success Response Fields

Refund Transaction Success Response

{
   "REQUEST_ACTION": "REFUND",
   "TRANS_STATUS_NAME": "APPROVED",
   "TRANS_VALUE": "0.1000",
   "TRANS_REQUEST_ID": 80282,
   "TRANS_RECORD_ID": 78443,
   "TRANS_ORDER_ID": 186434737,
   "XTL_ORDER_ID": "000011112222",
   "TRANS_CUR": "USD",
   "TIMESTAMP": "USD",        
   "SIGNATURE":"adaed58f5c99a3a219e3b85cf88409970134abfed018d1d884eef64491beece3"
}

These are the fields returned to the merchant when a transaction has been approved by the Payment Service.

Field Name Description
REQUEST_ACTION This will return REFUND
TRANS_STATUS_NAME Transaction Status
APPROVED : Refund has been approved.
TRANS_VALUE Refunded amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID Order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
TIMESTAMP Timestamp
SIGNATURE SIgnature***

Refund Transaction Failed Response Fields

Refund Transaction Failed Response

{
    "REQUEST_ACTION": "REFUND",
    "TRANS_STATUS_NAME": "DECLINED",
    "TRANS_VALUE": "1.0000",
    "TRANS_REQUEST_ID": 1364267,
    "TRANS_RECORD_ID": 1442813,
    "TRANS_ORDER_ID": 187697446,
    "XTL_ORDER_ID": "111",
    "API_ADVICE": "Refund amount may not exceed the transaction balance REFID:3138129324",
    "SERVICE_ADVICE": "Refund amount may not exceed the transaction balance REFID:3138129324",
    "PROCESSOR_ADVICE": "Refund amount may not exceed the transaction balance REFID:3138129324",
    "ERROR_MESSAGE": "Refund amount may not exceed the transaction balance REFID:3138129324",
    "TRANS_CUR": "USD",
    "TIMESTAMP": "2021-05-10T13:37:47Z",
    "SIGNATURE": "c2a95b88467a5e3d5b0c06ec57797f7999b6bc069cdb3bfbef61b84c483e5198"
}

These are the fields returned to the merchant when a transaction has been approved by the Payment Service.

Field Name Description
REQUEST_ACTION This will return REFUND
TRANS_STATUS_NAME Transaction Status
DECLINED : Refund has been declined.
TRANS_VALUE Refund amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID order ID. This ID should be used in the refund transaction call
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
TIMESTAMP Timestamp
SIGNATURE SIgnature***
API_ADVICE API advice message
SERVICE_ADVICE Service advice message
PROCESSOR_ADVICE Processor advice message
ERROR_MESSAGE Error message

Declined Transaction Response Fields

Declined Transaction Response

{
   "REQUEST_ACTION": "CAPTURE",
   "TRANS_STATUS_NAME": "DECLINED",
   "TRANS_VALUE": "5.0200",
   "TRANS_REQUEST_ID": 81271,
   "TRANS_RECORD_ID": 79153,
   "TRANS_ORDER_ID": 186435723,
   "XTL_ORDER_ID": "000011112222",
   "API_ADVICE": "",
   "SERVICE_ADVICE": "",
   "PROCESSOR_ADVICE": "",
   "ERROR_MESSAGE": "Expired Card",
   "TRANS_CUR": "USD"
}

These are the fields returned to the merchant when the transaction request has been declined on the Merchant Account Processor (bank) level: Send 5.02 as amount to test decline transaction

Field Name Description
REQUEST_ACTION This will return CAPTURE
TRANS_STATUS_NAME Transaction Status
DECLINED : Transaction has been declined.
TRANS_VALUE Transaction amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID Order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
API_ADVICE Payment Service API Response details.
SERVICE_ADVICE Service Response details
PROCESSOR_ADVICE Merchant Account Service Response details
ERROR_MESSAGE Error Message. or transaction decline reason

Refund Declined Response Fields

Declined Transaction Response

{
   "REQUEST_ACTION": "REFUND",
   "TRANS_STATUS_NAME": "DECLINED",
   "TRANS_VALUE": "2.0000",
   "TRANS_REQUEST_ID": 81489,
   "TRANS_ORDER_ID": 186435936,
   "XTL_ORDER_ID": "000011112222",
   "API_ADVICE": "Requested refund amount is greater than Order amount balance! [OrderAmountBalance:1.02, RequestedRefundAmount:2]",
   "SERVICE_ADVICE": "Requested refund amount is greater than Order amount balance! [OrderAmountBalance:1.02, RequestedRefundAmount:2]",
   "PROCESSOR_ADVICE": "Requested refund amount is greater than Order amount balance! [OrderAmountBalance:1.02, RequestedRefundAmount:2]",
   "ERROR_MESSAGE": "Requested refund amount is greater than Order amount balance! [OrderAmountBalance:1.02, RequestedRefundAmount:2]",
   "TRANS_CUR": "USD"
}

These are the fields returned to the merchant when the transaction request has been declined on the Merchant Account Processor (bank) level: Send 5.02 as amount to test decline transaction

Field Name Description
REQUEST_ACTION This will return REFUND
TRANS_STATUS_NAME Transaction Status
DECLINED : Refund has been declined.
TRANS_VALUE Refund amount.
TRANS_REQUEST_ID Unique transaction ID
TRANS_ORDER_ID Order ID. This ID should be used in the refund transaction call
TRANS_RECORD_ID Extra transaction Tracking ID
XTL_ORDER_ID Merchant order ID as sent by merchant in the sale transaction API call
TRANS_CUR 3-letter Currency Code
API_ADVICE Payment Service API Response details.
SERVICE_ADVICE Service Response details
PROCESSOR_ADVICE Merchant Account Service Response details
ERROR_MESSAGE Error Message. or transaction decline reason

Errors

The Bankful API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is invalid.
401 Unauthorized – Your API key is wrong.
403 Forbidden – The kitten requested is hidden for administrators only.
404 Not Found – The specified kitten could not be found.
405 Method Not Allowed – You tried to access a kitten with an invalid method.
406 Not Acceptable – You requested a format that isn’t json.
410 Gone – The kitten requested has been removed from our servers.
418 I’m a teapot.
429 Too Many Requests – You’re requesting too many kittens! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarily offline for maintenance. Please try again later.