v1.0 Partner Integration Updated

Core Banking API Documentation

Comprehensive reference guide, lookup endpoints, transfer orchestration, and webhook specifications for BankEasy Core Banking API services.

Base URL & Authentication Overview

All endpoints are served under the application context path /bankeasy-core-web.

EnvironmentBase URL
Staginghttps://<staging-host>/bankeasy-core-web
Productionhttps://<production-host>/bankeasy-core-web
CRITICAL: The authorization scheme prefix for institution tokens on core endpoints is Bearer_Auth, NOT standard Bearer (e.g., Authorization: Bearer_Auth <access_token>). Note the single space.

Generate Authentication Token

All clients who successfully register on our platform are issued access credentials with which they can generate a token. The generated token must be included in the Authorization header of every API request.

POST ${root_path_auth_server}/oauth2/token
Field Type Description Constraints
grant_type String Specifies a server-to-server authentication type Required
scope String Specific permissions or access rights (e.g. READ, WRITE) Required
Note: This endpoint requires Basic Authentication. Username is client_id and password is client_secret, formatted as Authorization: Basic <Base64Encoded(client_id:client_secret)>
cURL Request
curl --location '${root_path}/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic <Base64Encoded(client_id:client_secret)>' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=read'
Response : [200 OK]
{
  "access_token": "eyJraWQiOiJhNWE3YzQ2YS0y...",
  "scope": "read",
  "token_type": "Bearer",
  "expires_in": 86399
}

Add Customer

This operation provisions a new customer within the system and associates them with the specified institution. Once successfully created, the customer is granted the ability to initiate outbound transfers, access their wallet, and perform a wide range of supported banking transactions.

POST ${root_path}/api/client/add-customer
Field Type Description Constraints
firstNameStringFirst name of the customerCannot be blank
lastNameStringLast name of the customerCannot be blank
phoneNumberStringPhone number of the customerCannot be blank
emailStringCustomer emailMust be valid and unique
enableAccountNumberBooleanPredicate to determine if account is enabledDefault: false
bvnStringBank Verification Number of the customerCannot be blank. Must be valid BVN
dobLocalDateDate of birth of the customerMust follow pattern dd-MM-yyyy
genderStringGenderMale / Female
addressStringCustomer addressCannot be blank
cURL Request
curl --location '${root_path}/api/client/add-customer' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data-raw '{
  "firstName": "Richard",
  "lastName": "Stanley",
  "phoneNumber": "08061670369",
  "email": "rich.stan@gmail.com",
  "enableAccountNumber": true,
  "bvn": "22345678910",
  "dob": "19-09-2000",
  "gender": "Male",
  "address": "Richard'\''s avenue Houston Texas"
}'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "id": 13,
    "accountNumber": "0007000011",
    "kycLevel": "ONE",
    "institutionCode": "REST1"
  }
}

Get Client Profile

Returns the calling client's own profile, resolved from the institutionCode in their access token.

GET ${root_path}/api/client/profile
cURL Request
curl -X GET '${root_path}/api/client/profile' \
--header 'Authorization: Bearer_Auth <token>'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "id": 1,
    "companyName": "Richard_Soft",
    "institutionCode": "REST1",
    "status": "ACTIVE",
    "kycStatus": "VERIFIED",
    "accountNumber": "4011000115",
    "email": "stanley@richards.com"
  }
}

Get Customers

Returns a paged list of all customers belonging to the calling client's institution.

GET ${root_path}/api/client/customers
FieldTypeDescriptionConstraints
pageNumberIntegerPage number (1-based)Default: 1
pageSizeIntegerNumber of records per pageDefault: 20
cURL Request
curl -X GET '${root_path}/api/client/customers?pageNumber=1&pageSize=20' \
--header 'Authorization: Bearer_Auth <token>'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "content": [ { "id": 13, "accountNumber": "0007000011" } ],
    "totalElements": 100,
    "totalPages": 5,
    "currentPage": 1
  }
}

Outbound Transfer (3-Step Integration Flow)

An outbound NIP transfer requires a 3-step sequence. Each call produces values required by the next step.

STEP 1: GET /api/transfer/get-bank-codes/external └── Take: data[].bankCode (destination bank code) │ ▼ STEP 2: POST /api/transfer/name-enquiry/external └── Take: accountName, remoteReference, bvn, kyc │ ▼ STEP 3: POST /api/transfer/process/customer (Debit customer wallet) OR POST /api/transfer/process/client (Debit institution wallet)

Field Hydration Mapping

Step 3 Transfer FieldOrigin / Source Value
customerIdFrom data.id in POST /api/client/add-customer (for customer endpoint only)
amountTransfer amount (decimal, max 2 decimals, > 0)
accountNumberSame beneficiary account sent to Step 2 (Name Enquiry)
beneficiaryNameFrom data.accountName in Step 2 response
bankCodeFrom data[].bankCode in Step 1 (or echoed in Step 2)
transactionPinInstitution's 4-digit PIN (e.g. 1234 in test)
transactionReferenceUnique reference generated by your system
remoteTransactionRefFrom data.remoteReference in Step 2 response [REQUIRED]
beneficiaryBvnFrom data.bvn in Step 2 response
beneficiaryKycFrom data.kyc in Step 2 response [REQUIRED]
channelCodeOriginating channel digits (e.g. "3")
feeOptional fee (defaults to 0, obtain from /get-fee)
Step 1

Get Bank Codes (External)

Returns the list of financial institutions that can be selected as a transfer destination, with the bankCode to use in subsequent calls.

GET ${root_path}/api/transfer/get-bank-codes/external
cURL Request
curl -X GET '${root_path}/api/transfer/get-bank-codes/external' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Accept: application/json'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": [
    {
      "bankCode": "044",
      "name": "ACCESS BANK",
      "code": "044"
    },
    {
      "bankCode": "058",
      "name": "GUARANTY TRUST BANK",
      "code": "058"
    },
    {
      "bankCode": "090789",
      "name": "BANKEASY MFB",
      "code": "090789"
    }
  ]
}

Note: BankEasy's internal code is 090789. Transfers with this destination are settled internally.

Step 2

Name Enquiry (External)

Validates a beneficiary account number at the destination bank and returns the verified account holder's name and session reference required for the transfer.

POST ${root_path}/api/transfer/name-enquiry/external
FieldTypeDescriptionConstraints
accountNumberStringBeneficiary's account number at destination bankRequired, not blank
bankCodeStringDestination bank code (from Step 1)Required, not blank
channelCodeStringOriginating channel code (digits only, e.g. "3")Required, pattern [0-9]+
cURL Request
curl -X POST '${root_path}/api/transfer/name-enquiry/external' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data '{
  "accountNumber": "4021000385",
  "bankCode": "044",
  "channelCode": "3"
}'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "accountName": "JOHN DOE",
    "bankCode": "044",
    "remoteReference": "202605251234560001",
    "bvn": "22222222222",
    "kyc": "3"
  }
}
Important: An unresolvable account returns HTTP 200 with "success": false, "responseCode": "404", "responseMessage": "Invalid Account". Always check success before accessing data.accountName.

Calculate Transfer Fee

Fetches the authoritative transfer fee configured for a specific transaction amount before submitting a transfer.

POST ${root_path}/api/transfer/get-fee
cURL Request
curl -X POST '${root_path}/api/transfer/get-fee' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data '{
  "transactionAmount": 5000.00
}'
Step 3a

Outbound Transfers (Customer)

Debits the wallet of a customer belonging to your institution and initiates an outward transfer using hydrated data from Steps 1 & 2.

POST ${root_path}/api/transfer/process/customer
FieldTypeDescriptionConstraints
customerIdLongCustomer ID (from add-customer)Required
amountBigDecimalTransfer amount (up to 2 decimals)Required, > 0
accountNumberStringDestination beneficiary account numberRequired, not blank
narrationStringTransaction narrationOptional
beneficiaryNameStringFrom Step 2 (accountName)Required
bankCodeStringDestination bank code (from Step 1 / 2)Required
transactionPinStringInstitution 4-digit PINExactly 4 digits
transactionReferenceStringFresh unique reference generated by callerRequired
remoteTransactionRefStringFrom Step 2 (remoteReference)Required
beneficiaryBvnStringFrom Step 2 (bvn)Optional
beneficiaryKycStringFrom Step 2 (kyc)Required
channelCodeStringOriginating channel digits (e.g. "3")Required
feeBigDecimalFee amount (defaults to 0)Optional
cURL Request
curl --location '${root_path}/api/transfer/process/customer' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data '{
  "customerId": 1042,
  "amount": 5000.00,
  "accountNumber": "4021000385",
  "narration": "Payment for invoice 8891",
  "beneficiaryName": "JOHN DOE",
  "bankCode": "044",
  "transactionPin": "1234",
  "transactionReference": "TXN-9F3A21C7B4E85D06",
  "remoteTransactionRef": "202605251234560001",
  "beneficiaryBvn": "22222222222",
  "beneficiaryKyc": "3",
  "channelCode": "3",
  "fee": 0
}'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "amount": 5000.00,
    "transactionRef": "TXN-9F3A21C7B4E85D06"
  }
}
Step 3b

Outbound Transfers (Client)

Debits the institution's own registered wallet to execute outward transfers. The payload is identical to Customer Outbound Transfer with customerId omitted.

POST ${root_path}/api/transfer/process/client
cURL Request
curl --location '${root_path}/api/transfer/process/client' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data '{
  "amount": 5000.00,
  "accountNumber": "4021000385",
  "narration": "Settlement 2026-07-30",
  "beneficiaryName": "JOHN DOE",
  "bankCode": "044",
  "transactionPin": "1234",
  "transactionReference": "TXN-4B7E19D3F0A26C58",
  "remoteTransactionRef": "202605251234560001",
  "beneficiaryBvn": "22222222222",
  "beneficiaryKyc": "3",
  "channelCode": "3",
  "fee": 0
}'
Response : [200 OK]
{
  "success": true,
  "responseCode": "200",
  "responseMessage": "Success",
  "data": {
    "amount": 5000.00,
    "transactionRef": "TXN-4B7E19D3F0A26C58"
  }
}

Get Transactions

Returns all transactions for the calling client, paged and optionally filtered by date range and direction.

GET ${root_path}/api/client/transactions
FieldTypeDescriptionConstraints
pageNumberIntegerPage number (1-based)Default: 1
pageSizeIntegerRecords per pageDefault: 20
startDateTimeLocalDateTimeStart of date rangeFormat: yyyy-MM-dd HH:mm:ss
endDateTimeLocalDateTimeEnd of date rangeFormat: yyyy-MM-dd HH:mm:ss
directionStringFilter by directionOUTWARD | INWARD

Get Transaction by Reference

Fetches a single transaction by its provider reference or internal transaction reference.

GET ${root_path}/api/client/transactions/{ref}

Get Customer Transactions

Fetches all transactions for a specific customer belonging to the calling client.

GET ${root_path}/api/client/customers/{customerId}/transactions

Check Transaction Status

Query the status of a previously initiated transaction by providing its unique reference number.

GET ${root_path}/api/transfer/transaction?transactionId={ref}

Get Transaction History [Inward]

Retrieves the complete history of all inward transactions associated with the customer's wallet.

GET ${root_path}/api/transfer/

Change PIN

Allows customers to securely update their transaction PIN.

POST ${root_path}/api/customer/set-transaction-pin
cURL Request
curl --location '${root_path}/api/customer/set-transaction-pin' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "transactionPin": "123456", "customerId": 12 }'

Partner Webhook Specification (Inward Transfer)

Specifies the webhook API that a partner must implement to receive inward transfer notifications from BankEasy Fulfillment Service.

POST {baseUrl}/inward-transfer
FieldTypeDescriptionRequired
accountNumberstringBeneficiary account numberYes
amountnumber (decimal)Transfer amountYes
transactionFeenumber (decimal)Fee amount (nullable)No
narrationstringTransfer narrationYes
transactionTimestringe.g. 2026-03-04T10:15:30Yes
originatingAccountNamestringSender account nameYes
originatingAccountNumberstringSender account numberYes
signaturestring (Base64)Ed25519 signature generated by BankEasyYes
transactionReferencestringPayment referenceYes
sessionIdstringUnique session ID for idempotencyYes

Signature Verification (Java)

Java Example
String payload = String.format("%s-%s-%s-%s",
  accountNumber, originatingAccountNumber, amount, sessionId);
byte[] keyBytes = Base64.getDecoder().decode(publicKeyBase64);
PublicKey publicKey = KeyFactory.getInstance("Ed25519")
  .generatePublic(new X509EncodedKeySpec(keyBytes));
Signature verifier = Signature.getInstance("Ed25519");
verifier.initVerify(publicKey);
verifier.update(payload.getBytes(StandardCharsets.UTF_8));
byte[] sig = Base64.getDecoder().decode(signatureBase64);
return verifier.verify(sig);

Integration Best Practices & Constraints

To ensure a smooth integration with the BankEasy Core API, please observe the following constraints:

Support & Troubleshooting

For access tokens, institution onboarding, sandbox credentials, or transaction status enquiries, please contact the BankEasy integrations team.

When reporting an issue, ensure you include the following information: