CoreWave API Channel Execution Guide (Operator Grade)
Version: v1
Date: 2026-03-01
Purpose: This is the fastest possible operational guide.
If you only have 10 seconds, use section 1.
Export API Reference (.json) for Postman
1. 10-Second Cheat Sheet
1.1 Do-This Mapping
| You Want To Do | Call This Endpoint First | Then | Notes |
|---|---|---|---|
| Get access token | POST /api/auth/v1/authenticate | Use token for all calls | Required first step |
| Create customer + account | POST /api/account/v1/createcustomeraccount | GET /api/account/v1/getbyaccountnumber | Supports documents |
| Create account only | POST /api/account/v1/createaccount | GET /api/account/v1/getbyaccountnumber | Existing customer required |
| Create virtual account | POST /api/account/v1/createvirtualaccount | GET /api/account/v1/searchaccount | Type 0/1/2 |
| Update account | PUT /api/account/v1/updatecustomeraccount | GET /api/account/v1/getbyaccountnumber | Partial update |
| Search accounts | GET /api/account/v1/searchaccount | - | Any filter subset |
| Balance inquiry | GET /api/account/v1/getaccountbalancebyaccountnumber | Optional extended balance | |
| Close account | POST /api/postings/v1/closeaccount | Verify by search | Balance must be zero |
| Local transfer (internal) | POST /api/transfer/v1/localfundtransfer | GET /api/transfer/v1/tsq/local | Account/GL combos allowed |
| Outward transfer | POST /api/transfer/v1/outwardtransfer | GET /api/transfer/v1/tsq | TSQ decides final state |
| Bills payment | POST /api/bills/v1/vend | POST /api/bills/v1/tsq | Reversal handled on failure |
| Get electricity token | GET /api/bills/v1/gettoken | - | By posting/payment ref |
| List cards | GET /api/card/v1/searchcards | - | |
| Add card to account | POST /api/card/v1/addcardtoaccount | Provider ops | Issuance charge may post |
| Block/Unblock Providus card | PUT /api/card/v1/providus/blockunblockcard | - | status 1/2 |
| Update Interswitch channel access | PUT /api/card/v1/interswitch/updatecardchannelaccess | - | atm/pos/web flags |
| Add loan | POST /api/loanaccount/v1/add | POST /api/loanaccount/v1/disburseloan | linkedNumber must match owner |
| Repay loan | POST /api/loanaccount/v1/repayloan | - | collectionsGL required |
| Add fixed deposit | POST /api/fixeddepositaccount/v1/add | topup/update/liquidate | |
| Place lien | POST /api/accountlien/v1/placelien | update/unplace | |
| Set account transfer limit | PUT /api/limit/v1/addupdateaccountlimit | GET /api/limit/v1/getaccountlimit | transfer limits only |
| Upload customer/account doc | POST /api/operations/v1/uploaddocument | optional delete | base64url, max 10MB |
| Send SMS / Email | POST /api/operations/v1/sendsms / sendemail | - | |
| Get statement/report | GET /api/report/v1/... | export/receipt |
1.2 Mandatory Request Headers
Authorization: Bearer {token}request-reference: {unique-string}Content-Type: application/json
1.3 Critical Global Rules
- Authenticate first.
- Amounts are Naira.
- API keys auto-disable after 14 days inactivity.
- Bills/Transfer/Card calls require institution integration config enabled.
3. First 3 Calls You Should Always Test
3.1 Authenticate
curl --location '{{baseurl}}/api/auth/v1/authenticate' \
--header 'Content-Type: application/json' \
--data '{
"clientId": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET"
}'
3.2 Simple Read Health Check
curl --location '{{baseurl}}/api/product/v1/searchproducts?PageNumber=1&PageSize=1' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'request-reference: health-001' \
--header 'Content-Type: application/json'
3.3 Account Search Smoke Test
curl --location '{{baseurl}}/api/account/v1/searchaccount?PageNumber=1&PageSize=1' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'request-reference: health-002' \
--header 'Content-Type: application/json'
4. End-to-End Workflows (Copy and Execute)
4.1 Workflow A: Customer + Account + Balance
Step A1: Create customer and account
POST /api/account/v1/createcustomeraccount
Minimum body:
{
"lastName": "Doe",
"firstName": "Jane",
"accountName": "Jane Doe",
"branchCode": "101",
"productCode": "301",
"accountOfficerStaffID": "0015245"
}
Expected success keys:
data.iddata.accountNumberdata.customerID
Step A2: Fetch account profile
GET /api/account/v1/getbyaccountnumber?AccountNumber={accountNumber}
Step A3: Fetch account balance
GET /api/account/v1/getaccountbalancebyaccountnumber?AccountNumber={accountNumber}
4.2 Workflow B: Create Virtual Account
Step B1: Create virtual account
POST /api/account/v1/createvirtualaccount
Minimum body:
{
"accountName": "Merchant VAS",
"lastName": "Merchant",
"firstName": "Main",
"phoneNumber": "08000000000",
"email": "merchant@example.com",
"productCode": "301",
"accountType": 0
}
accountType:
0=VirtualProxy1=VirtualWallet2=EnhancedVirtualProxy(requirespaymentAmount)
Step B2: Search/verify
GET /api/account/v1/searchaccount?AccountNumber={virtualAccountNumber}
4.3 Workflow C: Local Funds Transfer
Step C1: Execute transfer
POST /api/transfer/v1/localfundtransfer
{
"debitAccount": "1000000001",
"creditAccount": "1000000002",
"amount": 5000,
"narration": "Local transfer",
"postingsTransactionType": 3
}
postingsTransactionType:
1=GLCustomer2=GLGL3=CustomerCustomer
Step C2: Check TSQ (local)
GET /api/transfer/v1/tsq/local?referenceNumber={referenceNumber}
Success indicator:
data.isSuccessful = true
4.4 Workflow D: Outward Transfer + TSQ
Step D1: Name enquiry (interbank)
GET /api/transfer/v1/nameenquiry?...
Step D2: Outward transfer
POST /api/transfer/v1/outwardtransfer
{
"nameEnquiryRef": "NE-123",
"originatorAccountNumber": "1000000001",
"originatorAccountName": "John Doe",
"beneficiaryAccountNumber": "0000014575",
"beneficiaryAccountName": "Test Beneficiary",
"destinationInstitutionCode": "TSTBNK",
"beneficiaryBankName": "Test Bank",
"transactionReference": "TX-123-UNIQUE",
"amount": 1000,
"originatorNarration": "Transfer",
"beneficiaryNarration": "Transfer"
}
Step D3: TSQ
GET /api/transfer/v1/tsq?transactionRef={transactionReference}
Final state field:
data.processingStatus
Interpretation:
Processed-> successReversed-> failed and reversedPending/PendingTSQ/Processing-> retry TSQConfirmManually-> check settlement/manual report
4.5 Workflow E: Bills Payment + Token + TSQ
Step E1: Fetch billers
GET /api/bills/v1/billers
Step E2: Customer info validation
GET /api/bills/v1/getcustomerinformation?...
Step E3: Vend
POST /api/bills/v1/vend
{
"accountNumber": "1000001579",
"paymentReference": "BILL-UNIQUE-001",
"amount": 2000,
"packageIdentifier": "COMPACT_PLUS",
"billerIdentifier": "DSTV",
"customerId": "0101160313181"
}
Step E4: TSQ if not final
POST /api/bills/v1/tsq
Step E5: Token retrieval (electricity)
GET /api/bills/v1/gettoken?PaymentReference=BILL-UNIQUE-001
4.6 Workflow F: Card Management
Step F1: Link card to account
POST /api/card/v1/addcardtoaccount
Step F2: Search cards
GET /api/card/v1/searchcards?accountNumber=...
Step F3: Provider-specific actions
- Interswitch channel update:
PUT /api/card/v1/interswitch/updatecardchannelaccess
- Providus set pin:
PUT /api/card/v1/providus/setcardpin
- Providus block/unblock:
PUT /api/card/v1/providus/blockunblockcard
Step F4: Webhook callbacks (middleware)
/cba/cards/interswitch/transaction-feedback/cba/cards/interswitch/lifecycle-feedback/cba/cards/providus/transaction-feedback/cba/cards/providus/lifecycle-feedback
4.7 Workflow G: Loan Lifecycle
- Add loan:
POST /api/loanaccount/v1/add - Disburse:
POST /api/loanaccount/v1/disburseloan - Repay:
POST /api/loanaccount/v1/repayloan - Early repayment (optional):
POST /api/loanaccount/v1/earlyrepaymentloan - Search:
GET /api/loanaccount/v1/search - Schedule:
GET /api/loanaccount/v1/viewloanschedule
4.8 Workflow H: Fixed Deposit Lifecycle
- Add FD:
POST /api/fixeddepositaccount/v1/add - Top-up:
POST /api/fixeddepositaccount/v1/topup - Update:
PUT /api/fixeddepositaccount/v1/update - Liquidate:
POST /api/fixeddepositaccount/v1/liquidate - Search:
GET /api/fixeddepositaccount/v1/search
4.9 Workflow I: Reporting
- Statement:
GET /api/report/v1/requestcustomeraccountstatement - Export statement:
GET /api/report/v1/exportcustomerstatement - Transaction receipt:
GET /api/report/v1/gettransactionreceipt - Account history:
GET /api/report/v1/requestcustomeraccounthistoryreport - Transaction callover:
GET /api/report/v1/gettransactioncalloverreport - Loan expectation/tracking:
GET /api/report/v1/getloanexpectationreport,GET /api/report/v1/getloantrackingreport - Savings accrual:
GET /api/report/v1/getsavingsaccrualhistory
5. Integration Configuration Checklist (Must Pass)
5.1 Bills
Required minimum:
BILLS_PAYMENT_ENABLED=trueBILLS_PAYMENT_BASE_URL- At least one provider enabled (
..._ENABLED=true) - Provider auth/header json configured
- Provider ledger or default ledger configured
Bills provider keys
providuscoralpayflutterwaveninepsbnibss_psspnibss_banks
5.2 Transfer
Required minimum:
TRANSFER_ENABLED=trueTRANSFER_BASE_URL- At least one provider enabled (
easypay/providus) - Provider auth/header json configured
- Settlement ledger configured
5.3 Cards
Required minimum:
CARD_ENABLED=trueCARD_BASE_URL- Provider enabled (
interswitchorprovidus) - Provider headers configured
- Settlement/issuance ledger configured where needed
5.4 Shared Keys (appsettings fallback)
BILLS_PAYMENT_SHARED_GATEWAY_KEYTRANSFER_SHARED_GATEWAY_KEYCARD_SHARED_GATEWAY_KEY
7. Complete Endpoint List
{
"auth": [
{"method":"POST","path":"/api/auth/v1/authenticate"}
],
"account": [
{"method":"POST","path":"/api/account/v1/createcustomeraccount"},
{"method":"POST","path":"/api/account/v1/createaccount"},
{"method":"POST","path":"/api/account/v1/creategroupcustomerinformation"},
{"method":"PUT","path":"/api/account/v1/updatecustomeraccount"},
{"method":"PUT","path":"/api/account/v1/updatecustomerinformation"},
{"method":"PUT","path":"/api/account/v1/updategroupcustomerinformation"},
{"method":"PUT","path":"/api/account/v1/activate"},
{"method":"PUT","path":"/api/account/v1/deactivate"},
{"method":"PUT","path":"/api/account/v1/unfreeze"},
{"method":"GET","path":"/api/account/v1/searchaccount"},
{"method":"GET","path":"/api/account/v1/getaccountbalancebyaccountnumber"},
{"method":"GET","path":"/api/account/v1/getbyaccountnumber"},
{"method":"GET","path":"/api/account/v1/getextendedbalancebyaccountnumber"},
{"method":"GET","path":"/api/account/v1/searchaccountofficers"},
{"method":"GET","path":"/api/account/v1/searchgroupcustomers"},
{"method":"GET","path":"/api/account/v1/searchindividualcustomers"},
{"method":"GET","path":"/api/account/v1/listbranches"},
{"method":"GET","path":"/api/account/v1/searchbranches"},
{"method":"POST","path":"/api/account/v1/createvirtualaccount"}
],
"accountlien": [
{"method":"POST","path":"/api/accountlien/v1/placelien"},
{"method":"POST","path":"/api/accountlien/v1/updatelien"},
{"method":"POST","path":"/api/accountlien/v1/unplacelien"}
],
"accountoverdraft": [
{"method":"POST","path":"/api/accountoverdraft/v1/add"},
{"method":"PUT","path":"/api/accountoverdraft/v1/update"},
{"method":"PUT","path":"/api/accountoverdraft/v1/activate"},
{"method":"PUT","path":"/api/accountoverdraft/v1/deactivate"},
{"method":"GET","path":"/api/accountoverdraft/v1/search"}
],
"bills": [
{"method":"GET","path":"/api/bills/v1/billers"},
{"method":"GET","path":"/api/bills/v1/getcustomerinformation"},
{"method":"POST","path":"/api/bills/v1/vend"},
{"method":"POST","path":"/api/bills/v1/tsq"},
{"method":"GET","path":"/api/bills/v1/gettoken"},
{"method":"GET","path":"/api/bills/v1/search"}
],
"card": [
{"method":"GET","path":"/api/card/v1/searchcards"},
{"method":"POST","path":"/api/card/v1/addcardtoaccount"},
{"method":"PUT","path":"/api/card/v1/interswitch/updatecardchannelaccess"},
{"method":"GET","path":"/api/card/v1/providus/searchcards"},
{"method":"PUT","path":"/api/card/v1/providus/setcardpin"},
{"method":"PUT","path":"/api/card/v1/providus/blockunblockcard"},
{"method":"PUT","path":"/api/card/v1/block"},
{"method":"PUT","path":"/api/card/v1/unblock"},
{"method":"DELETE","path":"/api/card/v1/delete/{id}"},
{"method":"POST","path":"/cba/cards/interswitch/transaction-feedback"},
{"method":"POST","path":"/cba/cards/interswitch/lifecycle-feedback"},
{"method":"POST","path":"/cba/cards/providus/transaction-feedback"},
{"method":"POST","path":"/cba/cards/providus/lifecycle-feedback"}
],
"fixeddepositaccount": [
{"method":"POST","path":"/api/fixeddepositaccount/v1/add"},
{"method":"POST","path":"/api/fixeddepositaccount/v1/topup"},
{"method":"POST","path":"/api/fixeddepositaccount/v1/liquidate"},
{"method":"PUT","path":"/api/fixeddepositaccount/v1/update"},
{"method":"GET","path":"/api/fixeddepositaccount/v1/search"}
],
"limit": [
{"method":"PUT","path":"/api/limit/v1/addupdateaccountlimit"},
{"method":"GET","path":"/api/limit/v1/getaccountlimit"}
],
"loanaccount": [
{"method":"POST","path":"/api/loanaccount/v1/add"},
{"method":"POST","path":"/api/loanaccount/v1/disburseloan"},
{"method":"POST","path":"/api/loanaccount/v1/repayloan"},
{"method":"POST","path":"/api/loanaccount/v1/earlyrepaymentloan"},
{"method":"PUT","path":"/api/loanaccount/v1/update"},
{"method":"GET","path":"/api/loanaccount/v1/search"},
{"method":"GET","path":"/api/loanaccount/v1/viewloanschedule"}
],
"operations": [
{"method":"GET","path":"/api/operations/v1/searchtillaccounts"},
{"method":"GET","path":"/api/operations/v1/gettillbalancebyaccountnumber"},
{"method":"POST","path":"/api/operations/v1/uploaddocument"},
{"method":"PUT","path":"/api/operations/v1/deletedocument"},
{"method":"POST","path":"/api/operations/v1/sendsms"},
{"method":"POST","path":"/api/operations/v1/sendemail"}
],
"postings": [
{"method":"POST","path":"/api/postings/v1/closeaccount"},
{"method":"POST","path":"/api/postings/v1/posttransaction"},
{"method":"POST","path":"/api/postings/v1/post"},
{"method":"POST","path":"/api/postings/v1/reversetransaction"}
],
"product": [
{"method":"GET","path":"/api/product/v1/searchproducts"}
],
"report": [
{"method":"GET","path":"/api/report/v1/requestcustomeraccountstatement"},
{"method":"GET","path":"/api/report/v1/exportcustomerstatement"},
{"method":"GET","path":"/api/report/v1/gettransactionreceipt"},
{"method":"GET","path":"/api/report/v1/requestcustomeraccounthistoryreport"},
{"method":"GET","path":"/api/report/v1/gettransactioncalloverreport"},
{"method":"GET","path":"/api/report/v1/getloanexpectationreport"},
{"method":"GET","path":"/api/report/v1/getloantrackingreport"},
{"method":"GET","path":"/api/report/v1/getsavingsaccrualhistory"}
],
"transfer": [
{"method":"GET","path":"/api/transfer/v1/banks"},
{"method":"GET","path":"/api/transfer/v1/nameenquiry"},
{"method":"GET","path":"/api/transfer/v1/nameenquiry/local"},
{"method":"POST","path":"/api/transfer/v1/balanceenquiry"},
{"method":"POST","path":"/api/transfer/v1/localfundtransfer"},
{"method":"POST","path":"/api/transfer/v1/outwardtransfer"},
{"method":"POST","path":"/api/transfer/v1/fundstransfer"},
{"method":"GET","path":"/api/transfer/v1/tsq"},
{"method":"GET","path":"/api/transfer/v1/tsq/local"},
{"method":"GET","path":"/api/transfer/v1/search"}
]
}
8. Where to Get Exact Payload Contracts
Use this file for fast execution.
For exhaustive exact property-level contracts and enums from source:
9. Zero-Ambiguity Playbooks
This section is intentionally repetitive. Use it when you want exact call order.
9.1 Playbook: API Authentication and Access Validation
| Step | Action | Endpoint | Success Check |
|---|---|---|---|
| 1 | Authenticate with active API key pair | POST /api/auth/v1/authenticate | Response contains accessToken |
| 2 | Use token for a safe read call | GET /api/product/v1/searchproducts?PageNumber=1&PageSize=1 | status=true |
| 3 | Confirm request tracing header works | any secured endpoint + request-reference | Request is accepted |
Failure handling:
API key is inactive or not found: activate/regenerate API key in Operations.Unauthorized: token expired, re-authenticate.Invalid API token claims: token was not issued via API channel auth flow.
9.2 Playbook: Create Individual Customer and CASA Account
Preconditions:
BranchCodeexists and is active.ProductCodeexists and is active for account creation.AccountOfficerStaffIDexists and is active.
Call:
POST /api/account/v1/createcustomeraccount
Minimum viable payload:
{
"lastName": "Doe",
"firstName": "Jane",
"accountName": "Jane Doe",
"branchCode": "101",
"productCode": "301",
"accountOfficerStaffID": "09074"
}
Expected response keys:
data.id(GUID record id)data.accountNumberdata.customerID(business customer id)
Immediate validation calls:
GET /api/account/v1/getbyaccountnumber?AccountNumber={accountNumber}GET /api/account/v1/getaccountbalancebyaccountnumber?AccountNumber={accountNumber}
9.3 Playbook: Create Account Only (Existing Customer)
Call:
POST /api/account/v1/createaccount
Expected outcome:
- New account linked to existing customer.
- Account number returned in response data.
If documents were supplied, validate with:
POST /api/operations/v1/uploaddocumentwhen needed.
9.4 Playbook: Create Virtual Account (Proxy/Wallet/Enhanced Proxy)
Call:
POST /api/account/v1/createvirtualaccount
Rules:
accountType=0: Virtual Proxy.accountType=1: Virtual Wallet.accountType=2: Enhanced Virtual Proxy (requires payment amount context).- Parent account must be a business/corporate account.
Validation:
GET /api/account/v1/searchaccount?AccountNumber={generatedAccountNumber}
Restrictions expected by design:
- Virtual account should allow basic transactions.
- Virtual account should not access disallowed loan/fixed-deposit operations.
9.5 Playbook: Update Account / Activate / Deactivate / Unfreeze
Endpoints:
PUT /api/account/v1/updatecustomeraccountPUT /api/account/v1/activatePUT /api/account/v1/deactivatePUT /api/account/v1/unfreeze
Pattern:
- Submit action payload.
- Re-query via
searchaccountorgetbyaccountnumber. - Confirm
accountStatusreflects requested operation.
9.6 Playbook: Close Account
Call:
POST /api/postings/v1/closeaccount
Payload essentials:
accountNumberclosureReason
Post-check:
GET /api/account/v1/getbyaccountnumber?AccountNumber=...- Validate closed status and final balances.
9.7 Playbook: Local Funds Transfer (Internal)
Call:
POST /api/transfer/v1/localfundtransfer
Supports:
- Account -> Account
- Account -> Ledger
- Ledger -> Account
- Ledger -> Ledger
Core payload fields:
debitAccountcreditAccountamount(Naira)narrationpostingsTransactionType(1=GLCustomer,2=GLGL,3=CustomerCustomer)
Status check:
GET /api/transfer/v1/tsq/local?referenceNumber=...
9.8 Playbook: Interbank Transfer (Outward Transfer)
Strict sequence:
GET /api/transfer/v1/banksGET /api/transfer/v1/nameenquiryPOST /api/transfer/v1/outwardtransferGET /api/transfer/v1/tsq?transactionRef=...
TSQ decision model:
Processed: success.Pending,Processing,PendingTSQ: retry TSQ.Reversed: failed, funds reversed.Failed: failed, check reversal flag.ConfirmManually: reconcile from settlement report.
9.9 Playbook: Bills Payment (with TSQ and Token)
Strict sequence:
GET /api/bills/v1/billersGET /api/bills/v1/getcustomerinformationPOST /api/bills/v1/vendPOST /api/bills/v1/tsq(if gateway status is not final)GET /api/bills/v1/gettoken(electricity scenarios)
Money movement expectation:
- Debit from customer or virtual account.
- Credit to configured bills ledger.
- On provider failure, reversal should be triggered.
9.10 Playbook: Card Operations
Common flow:
POST /api/card/v1/addcardtoaccountGET /api/card/v1/searchcards- Provider operation:
- Interswitch:
PUT /api/card/v1/interswitch/updatecardchannelaccess - Providus:
PUT /api/card/v1/providus/setcardpin - Providus:
PUT /api/card/v1/providus/blockunblockcard
- Optional generic block/unblock/delete:
PUT /api/card/v1/blockPUT /api/card/v1/unblockDELETE /api/card/v1/delete/{id}
Middleware callback paths (must be exact):
/cba/cards/interswitch/transaction-feedback/cba/cards/interswitch/lifecycle-feedback/cba/cards/providus/transaction-feedback/cba/cards/providus/lifecycle-feedback
9.11 Playbook: Loan Lifecycle
Strict sequence:
POST /api/loanaccount/v1/addPOST /api/loanaccount/v1/disburseloanPOST /api/loanaccount/v1/repayloan(as needed)POST /api/loanaccount/v1/earlyrepaymentloan(optional)PUT /api/loanaccount/v1/update(optional)GET /api/loanaccount/v1/viewloanscheduleGET /api/loanaccount/v1/search
Business rule reminder:
linkedNumbermust be the linked account number belonging to the loan owner.
9.12 Playbook: Fixed Deposit Lifecycle
Strict sequence:
POST /api/fixeddepositaccount/v1/addPOST /api/fixeddepositaccount/v1/topupPUT /api/fixeddepositaccount/v1/updatePOST /api/fixeddepositaccount/v1/liquidateGET /api/fixeddepositaccount/v1/search
9.13 Playbook: Overdraft and Lien
Overdraft:
- Add:
POST /api/accountoverdraft/v1/add - Update:
PUT /api/accountoverdraft/v1/update - Activate/Deactivate:
PUT /api/accountoverdraft/v1/activate,PUT /api/accountoverdraft/v1/deactivate - Search:
GET /api/accountoverdraft/v1/search
Lien:
- Place:
POST /api/accountlien/v1/placelien - Update:
POST /api/accountlien/v1/updatelien - Unplace:
POST /api/accountlien/v1/unplacelien
9.14 Playbook: Statements and Reports
Primary endpoints:
GET /api/report/v1/requestcustomeraccountstatementGET /api/report/v1/exportcustomerstatementGET /api/report/v1/gettransactionreceiptGET /api/report/v1/requestcustomeraccounthistoryreportGET /api/report/v1/gettransactioncalloverreportGET /api/report/v1/getloanexpectationreportGET /api/report/v1/getloantrackingreportGET /api/report/v1/getsavingsaccrualhistory
10. Institution Configuration Blueprint (Onboarding Template)
Use this template when onboarding a new institution. Keep providers disabled by default.
{
"BILLS_PAYMENT_ENABLED": "false",
"BILLS_PAYMENT_BASE_URL": "https://bills-middleware.example.com",
"BILLS_PAYMENT_DEFAULT_PROVIDER": "providus",
"BILLS_PAYMENT_DEFAULT_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_PROVIDUS_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_PROVIDUS_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_PROVIDUS_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_PROVIDUS_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_PROVIDUS_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_CORALPAY_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_CORALPAY_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_CORALPAY_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_CORALPAY_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_CORALPAY_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_FLUTTERWAVE_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_FLUTTERWAVE_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_FLUTTERWAVE_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_FLUTTERWAVE_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_FLUTTERWAVE_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_NINEPSB_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_NINEPSB_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NINEPSB_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NINEPSB_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_NINEPSB_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_NIBSS_PSSP_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_NIBSS_PSSP_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NIBSS_PSSP_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NIBSS_PSSP_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_NIBSS_PSSP_LEDGER_CODE": "",
"BILLS_PAYMENT_PROVIDER_NIBSS_BANKS_ENABLED": "false",
"BILLS_PAYMENT_PROVIDER_NIBSS_BANKS_AUTH_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NIBSS_BANKS_HEADERS_JSON": "{}",
"BILLS_PAYMENT_PROVIDER_NIBSS_BANKS_AUTHORIZATION": "",
"BILLS_PAYMENT_PROVIDER_NIBSS_BANKS_LEDGER_CODE": "",
"BILLS_PAYMENT_NOTIFICATION_PHONE": "",
"BILLS_PAYMENT_NOTIFICATION_EMAIL": "",
"TRANSFER_ENABLED": "false",
"TRANSFER_BASE_URL": "https://transfer-middleware.example.com",
"TRANSFER_DEFAULT_PROVIDER": "easypay",
"TRANSFER_DEFAULT_LEDGER_CODE": "",
"TRANSFER_PROVIDER_EASYPAY_ENABLED": "false",
"TRANSFER_PROVIDER_EASYPAY_AUTH_JSON": "{}",
"TRANSFER_PROVIDER_EASYPAY_HEADERS_JSON": "{}",
"TRANSFER_PROVIDER_EASYPAY_LEDGER_CODE": "",
"TRANSFER_PROVIDER_PROVIDUS_ENABLED": "false",
"TRANSFER_PROVIDER_PROVIDUS_AUTH_JSON": "{}",
"TRANSFER_PROVIDER_PROVIDUS_HEADERS_JSON": "{}",
"TRANSFER_PROVIDER_PROVIDUS_LEDGER_CODE": "",
"CARD_ENABLED": "false",
"CARD_BASE_URL": "https://cards-middleware.example.com",
"CARD_DEFAULT_PROVIDER": "providus",
"CARD_ISSUANCE_CHARGE": "0",
"CARD_ISSUANCE_CHARGE_LEDGER_CODE": "",
"CARD_TRANSACTION_SETTLEMENT_LEDGER_CODE": "",
"CARD_PROVIDER_INTERSWITCH_ENABLED": "false",
"CARD_PROVIDER_INTERSWITCH_HEADERS_JSON": "{}",
"CARD_PROVIDER_PROVIDUS_ENABLED": "false",
"CARD_PROVIDER_PROVIDUS_HEADERS_JSON": "{}",
"API_BYPASS_APPROVALS": "false"
}
Provider auth guidance:
- Some providers expect
clientId/clientSecret. - Some expect
publicKey/secretKey. - Store provider-specific auth shape inside
*_AUTH_JSONexactly as middleware expects.
11. Transaction AdditionalMetadata Contract (Transfer + Bills)
Transaction history must carry contextual metadata in Transaction.AdditionalMetadata as JSON.
11.1 Transfer Metadata Example
{
"channel": "transfer",
"provider": "easypay",
"transfer_type": "outward",
"bank_code_to": "058",
"bank_to": "Guaranty Trust Bank",
"account_name_to": "John Beneficiary",
"account_number_to": "0123456789",
"account_name_from": "Jane Originator",
"account_number_from": "1000000001",
"originator_bvn": "",
"beneficiary_bvn": "",
"transaction_reference": "TX-123",
"name_enquiry_ref": "NE-123",
"session_id": "",
"processing_status": "Pending",
"narration_originator": "Transfer",
"narration_beneficiary": "Transfer"
}
11.2 Bills Metadata Example
{
"channel": "bills",
"provider": "providus",
"biller_identifier": "DSTV",
"biller_name": "DSTV",
"package_identifier": "COMPACT_PLUS",
"package_name": "Compact Plus",
"customer_id": "0101160313181",
"customer_name": "John Viewer",
"payment_reference": "BILL-123",
"posting_reference": "",
"transaction_id": "",
"vend_status": "Pending",
"token": "",
"token_units": 0
}
Notification usage guidance:
- SMS/Email templates should read from
AdditionalMetadata. - Transfer notifications should include destination bank/name/account from metadata.
- Bills notifications should include biller, package, customer id/name, and token (when available).
12. Approvals Behavior for API Channel
Controlled by configuration:
API_BYPASS_APPROVALS
Behavior:
true: API-initiated operations bypass approval workflow.false: API-initiated operations flow through standard approval logic.
Recommendation:
- Keep
falseby default for new institutions. - Enable
trueonly for institutions with signed risk acceptance.
13. Idempotency, Retry, and Reconciliation Rules
Idempotency keys to treat as unique:
- Header:
request-reference - Business refs:
paymentReference,transactionReference,referenceNumber
Retry strategy:
- On timeout, do not re-post blindly.
- Query search/TSQ endpoint first.
- Re-post only if no trace exists.
Reconciliation strategy:
- Transfer: use
TSQandprocessingStatus. - Bills: use
TSQ, thenSearchto inspectisReversedandrequireReversal. - Local posting: use
TSQ/localor transaction history search.
14. QA Acceptance Matrix (What Must Pass Before Go-Live)
| Area | Test | Pass Criteria |
|---|---|---|
| Auth | Authenticate with valid key | Token returned |
| Auth | Authenticate with inactive key | Rejected with clear message |
| Accounts | Create customer+account | Account number + customer id returned |
| Accounts | Upload document | Upload accepted and retrievable/deletable |
| Transfers | Local transfer | Debit/Credit posted and TSQ local successful |
| Transfers | Outward transfer success path | TSQ reaches Processed |
| Transfers | Outward transfer failure path | Reversal status is visible when failed |
| Bills | Vend success path | Successful status with traceable refs |
| Bills | Vend failure path | Reversal path works and searchable |
| Bills | Electricity token | Token retrievable and sent via notifications |
| Cards | Add/search/block/unblock/set pin | Provider actions reflected in state |
| Loans | Add/disburse/repay/search/schedule | All states consistent |
| FD | Add/topup/update/liquidate/search | All operations consistent |
| Reports | Statement + export + receipt | Data rendered and export streams correctly |
| Limits | Add/update/get account transfer limit | Values persist and are enforced |
| Security | API key inactivity auto-disable | Key disabled after 14 days of no usage |
15. Definitive Source of Truth
Use documents in this order:
- This file: execution flow and operational behavior.
API_CHANNEL_DOCUMENTATION.md: full endpoint matrix, DTOs, enums, validation extracts.- Controller source files under
API/: final behavior authority.