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.
| Environment | Base URL |
|---|---|
| Staging | https://<staging-host>/bankeasy-core-web |
| Production | https://<production-host>/bankeasy-core-web |
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.
| 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 |
client_id and password is client_secret, formatted as Authorization: Basic <Base64Encoded(client_id:client_secret)>
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'
{
"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.
| Field | Type | Description | Constraints |
|---|---|---|---|
firstName | String | First name of the customer | Cannot be blank |
lastName | String | Last name of the customer | Cannot be blank |
phoneNumber | String | Phone number of the customer | Cannot be blank |
email | String | Customer email | Must be valid and unique |
enableAccountNumber | Boolean | Predicate to determine if account is enabled | Default: false |
bvn | String | Bank Verification Number of the customer | Cannot be blank. Must be valid BVN |
dob | LocalDate | Date of birth of the customer | Must follow pattern dd-MM-yyyy |
gender | String | Gender | Male / Female |
address | String | Customer address | Cannot be blank |
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"
}'
{
"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.
curl -X GET '${root_path}/api/client/profile' \
--header 'Authorization: Bearer_Auth <token>'
{
"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.
| Field | Type | Description | Constraints |
|---|---|---|---|
pageNumber | Integer | Page number (1-based) | Default: 1 |
pageSize | Integer | Number of records per page | Default: 20 |
curl -X GET '${root_path}/api/client/customers?pageNumber=1&pageSize=20' \
--header 'Authorization: Bearer_Auth <token>'
{
"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.
Field Hydration Mapping
| Step 3 Transfer Field | Origin / Source Value |
|---|---|
customerId | From data.id in POST /api/client/add-customer (for customer endpoint only) |
amount | Transfer amount (decimal, max 2 decimals, > 0) |
accountNumber | Same beneficiary account sent to Step 2 (Name Enquiry) |
beneficiaryName | From data.accountName in Step 2 response |
bankCode | From data[].bankCode in Step 1 (or echoed in Step 2) |
transactionPin | Institution's 4-digit PIN (e.g. 1234 in test) |
transactionReference | Unique reference generated by your system |
remoteTransactionRef | From data.remoteReference in Step 2 response [REQUIRED] |
beneficiaryBvn | From data.bvn in Step 2 response |
beneficiaryKyc | From data.kyc in Step 2 response [REQUIRED] |
channelCode | Originating channel digits (e.g. "3") |
fee | Optional fee (defaults to 0, obtain from /get-fee) |
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.
curl -X GET '${root_path}/api/transfer/get-bank-codes/external' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Accept: application/json'
{
"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.
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.
| Field | Type | Description | Constraints |
|---|---|---|---|
accountNumber | String | Beneficiary's account number at destination bank | Required, not blank |
bankCode | String | Destination bank code (from Step 1) | Required, not blank |
channelCode | String | Originating channel code (digits only, e.g. "3") | Required, pattern [0-9]+ |
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"
}'
{
"success": true,
"responseCode": "200",
"responseMessage": "Success",
"data": {
"accountName": "JOHN DOE",
"bankCode": "044",
"remoteReference": "202605251234560001",
"bvn": "22222222222",
"kyc": "3"
}
}
"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.
curl -X POST '${root_path}/api/transfer/get-fee' \
--header 'Authorization: Bearer_Auth <token>' \
--header 'Content-Type: application/json' \
--data '{
"transactionAmount": 5000.00
}'
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.
| Field | Type | Description | Constraints |
|---|---|---|---|
customerId | Long | Customer ID (from add-customer) | Required |
amount | BigDecimal | Transfer amount (up to 2 decimals) | Required, > 0 |
accountNumber | String | Destination beneficiary account number | Required, not blank |
narration | String | Transaction narration | Optional |
beneficiaryName | String | From Step 2 (accountName) | Required |
bankCode | String | Destination bank code (from Step 1 / 2) | Required |
transactionPin | String | Institution 4-digit PIN | Exactly 4 digits |
transactionReference | String | Fresh unique reference generated by caller | Required |
remoteTransactionRef | String | From Step 2 (remoteReference) | Required |
beneficiaryBvn | String | From Step 2 (bvn) | Optional |
beneficiaryKyc | String | From Step 2 (kyc) | Required |
channelCode | String | Originating channel digits (e.g. "3") | Required |
fee | BigDecimal | Fee amount (defaults to 0) | Optional |
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
}'
{
"success": true,
"responseCode": "200",
"responseMessage": "Success",
"data": {
"amount": 5000.00,
"transactionRef": "TXN-9F3A21C7B4E85D06"
}
}
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.
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
}'
{
"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.
| Field | Type | Description | Constraints |
|---|---|---|---|
pageNumber | Integer | Page number (1-based) | Default: 1 |
pageSize | Integer | Records per page | Default: 20 |
startDateTime | LocalDateTime | Start of date range | Format: yyyy-MM-dd HH:mm:ss |
endDateTime | LocalDateTime | End of date range | Format: yyyy-MM-dd HH:mm:ss |
direction | String | Filter by direction | OUTWARD | INWARD |
Get Transaction by Reference
Fetches a single transaction by its provider reference or internal transaction reference.
Get Customer Transactions
Fetches all transactions for a specific customer belonging to the calling client.
Check Transaction Status
Query the status of a previously initiated transaction by providing its unique reference number.
Get Transaction History [Inward]
Retrieves the complete history of all inward transactions associated with the customer's wallet.
Change PIN
Allows customers to securely update their transaction PIN.
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.
| Field | Type | Description | Required |
|---|---|---|---|
accountNumber | string | Beneficiary account number | Yes |
amount | number (decimal) | Transfer amount | Yes |
transactionFee | number (decimal) | Fee amount (nullable) | No |
narration | string | Transfer narration | Yes |
transactionTime | string | e.g. 2026-03-04T10:15:30 | Yes |
originatingAccountName | string | Sender account name | Yes |
originatingAccountNumber | string | Sender account number | Yes |
signature | string (Base64) | Ed25519 signature generated by BankEasy | Yes |
transactionReference | string | Payment reference | Yes |
sessionId | string | Unique session ID for idempotency | Yes |
Signature Verification (Java)
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:
- Numeric-looking strings: Fields like
bankCode,channelCode,accountNumber,beneficiaryBvn,beneficiaryKyc, andtransactionPinare all STRINGS. Do not serialize them as JSON numbers, as significant leading zeros (e.g. "044" becoming 44) will be lost, resulting in failed or misrouted requests. - Amount precision: Send amounts in major units with at most 2 decimal places (e.g.
5000.00). Send as a JSON number or numeric string. Do not include currency symbols, thousands separators, or currency codes. - TransactionReference and retries: The
transactionReferenceis generated by you and must be unique per transfer. Reuse it only when deliberately retrying the SAME logical transfer. As duplicate submissions are not currently blocked at the API boundary, keep strict records and confirm the status of an uncertain transfer before resubmitting. - Name Enquiry freshness: The
remoteTransactionRefties the transfer to a specific Name Enquiry session. Perform the Name Enquiry immediately before the transfer. Do not cache references, and do not reuse one reference across multiple transfers. - Character encoding: UTF-8 must be used for all requests and responses.
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:
- Your institution code
- The
transactionReferenceandremoteTransactionRefinvolved - The UTC timestamp of the request
- The full response envelope you received