Skip to main content

CoreWave API Channel Execution Guide (Operator Grade)

Version: v1
Date: 2026-05-31

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 DoCall This Endpoint FirstThenNotes
Get access tokenPOST /api/auth/v1/authenticateUse token for all callsRequired first step
Create customer + accountPOST /api/account/v1/createcustomeraccountGET /api/account/v1/getbyaccountnumberSupports documents
Create account onlyPOST /api/account/v1/createaccountGET /api/account/v1/getbyaccountnumberExisting customer required
Create virtual accountPOST /api/account/v1/createvirtualaccountGET /api/account/v1/getbyaccountnumberCorporate collection alias for NIP/NPS funding only
Update accountPUT /api/account/v1/updatecustomeraccountGET /api/account/v1/getbyaccountnumberVirtual-account IDs are rejected; update settlement account
Search accountsGET /api/account/v1/searchaccount-Any filter subset
Add agentPOST /api/agent/v1/addGET /api/agent/v1/searchAgent is separate from account officer
Balance inquiryGET /api/account/v1/getaccountbalancebyaccountnumberOptional extended balance
Close accountPOST /api/postings/v1/closeaccountVerify by searchBalance must be zero
Local transfer (internal)POST /api/transfer/v1/localfundtransferGET /api/transfer/v1/tsq/localAccount/GL combos allowed
Outward transferPOST /api/transfer/v1/outwardtransferGET /api/transfer/v1/tsqTSQ decides final state
Bills paymentPOST /api/bills/v1/vendPOST /api/bills/v1/tsqReversal handled on failure
Get electricity tokenGET /api/bills/v1/gettoken-By posting/payment ref
List cardsGET /api/card/v1/searchcards-
Add card to accountPOST /api/card/v1/addcardtoaccountProvider opsIssuance charge may post
Block/Unblock Providus cardPUT /api/card/v1/providus/blockunblockcard-status 1/2
Update Interswitch channel accessPUT /api/card/v1/interswitch/updatecardchannelaccess-atm/pos/web flags
Add loanPOST /api/loanaccount/v1/addCredit bureau review, AI review, approval, then disbursementlinkedNumber must match owner; agentCode is optional
Loan bureau reviewGET /api/loanaccount/v1/loancreditbureauGET /api/loanaccount/v1/loanaireviewrequires loanAccountNumber; run before approval when enabled
Loan certificate / offer letterGET /api/loanaccount/v1/view-certificate/{ID}-use loan id from search; returns Base64 PDF data URL
Add group loanPOST /api/loanaccount/v1/addgrouploanPOST /api/loanaccount/v1/disbursegrouploanuses group loan product + participant loan requests
Repay loanPOST /api/loanaccount/v1/repayloan-collectionsGL required
Repay group loanPOST /api/loanaccount/v1/repaygrouploanGET /api/loanaccount/v1/searchgrouploanparticipant-level repayment payload
Group loan bureau reviewGET /api/loanaccount/v1/grouploancreditbureauGET /api/loanaccount/v1/grouploanaireviewrequires groupLoanID
Add fixed depositPOST /api/fixeddepositaccount/v1/addtopup/update/liquidate
Fixed deposit certificateGET /api/fixeddepositaccount/v1/view-certificate/{ID}/{type}-use fixed deposit id from search; type is PDF or Excel
Place lienPOST /api/accountlien/v1/placelienupdate/unplace
Set account transfer limitPUT /api/limit/v1/addupdateaccountlimitGET /api/limit/v1/getaccountlimittransfer limits only
Upload customer/account docPOST /api/operations/v1/uploaddocumentoptional deletebase64url, max 10MB
Add or update record extra dataPUT /api/entity-additional-metadata/v1/{entityType}/{entityId}Fetch with GET first when merging keysJSON object or array, max 64 KB
Send SMS / EmailPOST /api/operations/v1/sendsms / sendemail-
Get statement/reportGET /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.
  • Agent is different from account officer. Agent attribution uses agentCode, not accountOfficerCode.
  • Virtual accounts are inbound collection aliases only. They fund the linked settlement account and cannot be used as standalone debit/balance accounts.
  • Entity extra data accepts institution-specific nested JSON objects or arrays. PUT replaces the stored value and DELETE clears it.

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.id
  • data.accountNumber
  • data.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}

Agent Lifecycle Quick Flow

Use this when the institution wants to attribute loan origination to a field agent:

  1. POST /api/agent/v1/add
  2. GET /api/agent/v1/search?AgentCode={agentCode}
  3. Pass optional agentCode on POST /api/loanaccount/v1/add or PUT /api/loanaccount/v1/update
  4. Read back agentCode, agentName, and agentID from GET /api/loanaccount/v1/search

4.2 Workflow B: Create Virtual Account

Step B1: Create virtual account

POST /api/account/v1/createvirtualaccount

Recommended body:

{
"parentAccountNumber": "1000000009",
"accountName": "Merchant VAS",
"referenceNumber": "VAS-REF-001",
"lastName": "Merchant",
"firstName": "Main",
"otherNames": "Store 1",
"phoneNumber": "08000000000",
"email": "merchant@example.com"
}

Core backend rules:

  • parentAccountNumber must resolve to a valid corporate parent account, unless the API key is already bound to a parent account.
  • Virtual account creation is for inbound NIBSS NIP/NPS collection only.
  • Only the base collection type is supported for new integrations. Do not send wallet/enhanced-proxy variants.
  • ProductID/productCode is not part of virtual account creation.
  • referenceNumber must be unique when supplied.
  • accountNumber in response is now the generated VirtualAccountNumber.

Step B2: Search/verify

GET /api/account/v1/getbyaccountnumber?AccountNumber={virtualAccountNumber}

Virtual-account success indicators:

  • data.isVirtualAccount = true
  • data.virtualAccountID is returned
  • data.settlementAccountNumber is parent settlement account number
  • data.accountName is returned as {virtual account name}/{corporate customer name}
  • data.canHoldBalance = false
  • data.canDebit = false
  • data.historyMode = credits-only

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=GLCustomer
  • 2=GLGL
  • 3=CustomerCustomer

Virtual-account rule:

  • creditAccount may be a virtual account for inbound collection into its settlement account.
  • debitAccount cannot be a virtual account.

Step C2: Check TSQ (local)

GET /api/transfer/v1/tsq/local?referenceNumber={referenceNumber}

Success indicator:

  • data.isSuccessful = true

Step C3: Handle a Fraud Copilot AML hold

When Fraud Copilot returns 202 Accepted with data.statusCode = "AML_HOLD", no funds moved. Wait for staff approval, then retry the unchanged request with:

{
"amlApprovalReference": "AML-26caaadad76043d596bd"
}

See Fraud Copilot AML Holds.


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"
}

Rule:

  • originatorAccountNumber must be a real settlement/customer account. Virtual accounts cannot originate outward transfers.

Step D3: TSQ

GET /api/transfer/v1/tsq?transactionRef={transactionReference}

Final state field:

  • data.processingStatus

Interpretation:

  • Processed -> success
  • Reversed -> failed and reversed
  • Pending/PendingTSQ/Processing -> retry TSQ
  • ConfirmManually -> check settlement/manual report

If the initial outward request returns 202 Accepted with data.statusCode = "AML_HOLD", the gateway has not been called. Wait for staff approval and retry the unchanged payload with amlApprovalReference.


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

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

  1. Add loan: POST /api/loanaccount/v1/add
  2. Loan credit bureau review when CRC is enabled and configured: GET /api/loanaccount/v1/loancreditbureau?loanAccountNumber={accountNumber}
  3. Loan AI review when Credit Brain is enabled and an AI provider is configured: GET /api/loanaccount/v1/loanaireview?loanAccountNumber={accountNumber}
  4. Mandate initiation in the institution workflow when Mono or Recuva mandate integration is enabled and configured.
  5. Approve loan through the institution workflow.
  6. Generate loan certificate / offer letter when needed: GET /api/loanaccount/v1/view-certificate/{id}
  7. Disburse: POST /api/loanaccount/v1/disburseloan
  8. Repay: POST /api/loanaccount/v1/repayloan
  9. Early repayment (optional): POST /api/loanaccount/v1/earlyrepaymentloan
  10. Search: GET /api/loanaccount/v1/search
  11. Schedule: GET /api/loanaccount/v1/viewloanschedule
  12. Add group loan: POST /api/loanaccount/v1/addgrouploan
  13. Group credit bureau review: GET /api/loanaccount/v1/grouploancreditbureau?groupLoanID={id}
  14. Group AI review: GET /api/loanaccount/v1/grouploanaireview?groupLoanID={id}
  15. Disburse group loan: POST /api/loanaccount/v1/disbursegrouploan
  16. Repay group loan: POST /api/loanaccount/v1/repaygrouploan
  17. Search group loans: GET /api/loanaccount/v1/searchgrouploan

Group Loan Payloads

Add group loan: POST /api/loanaccount/v1/addgrouploan

{
"groupLoanProductID": 1,
"name": "Women Cooperative Group A",
"referenceNumber": "GL-REF-001",
"participants": [
{
"loanRequest": {
"accountID": 101,
"productID": 12,
"accountOfficerID": 5,
"referenceNumber": "LN-REF-001",
"oracleNumber": "ORC-001",
"lendingModel": 1,
"economicSector": 0,
"failedRepaymentGracePeriod": 3,
"principalAmount": 250000,
"startDate": "2026-03-03",
"interestAccrualStartDate": "2026-03-03",
"firstRepaymentDate": "2026-04-03",
"principalRepaymentType": 3,
"principalRepaymentEvery": 1,
"principalRepaymentFrequency": 2,
"principalRepaymentTenure": 12,
"overrideProductInterestRate": false,
"applicableInterestID": 1,
"defaultInterestRate": 2.5,
"rateBasis": 0,
"interestComputationModel": 1,
"interestPaymentType": 3,
"interestPaymentEvery": 1,
"interestPaymentEveryFrequency": 2,
"interestPaymentDuration": 12,
"allowLoanFee": true,
"loanFeeID": 1,
"ignoreProductDefaultMoratorium": true,
"moratorium": 0,
"requiredSecurityDepositAmount": 5000,
"collateralPledge": false,
"collateralType": 0,
"collateralValuation": 0,
"collateralDescription": "N/A",
"allowDisbursementToGL": false,
"disbursementGLID": null,
"repaymentTrackers": 30,
"loanGuarantors": [11, 12],
"loanDocuments": [],
"notes": "Participant 1 loan request"
},
"preferredMonoReference": "MONO-PARTICIPANT-001"
}
],
"notes": "API add group loan account"
}

Disburse group loan: POST /api/loanaccount/v1/disbursegrouploan

{
"groupLoanID": 1,
"referenceNumber": "GL-REF-001",
"notes": "API disburse group loan"
}

Repay group loan: POST /api/loanaccount/v1/repaygrouploan

{
"groupLoanID": 1,
"participantRepayments": [
{
"id": 1001,
"schedules": [
{
"id": 2001,
"payInterest": true,
"payFee": true,
"payPrincipal": true,
"payDefault": false,
"payPenalty": false
}
],
"interestToPay": 1000,
"feeToPay": 500,
"principalToPay": 10000,
"defaultToPay": 0,
"penaltyToPay": 0,
"notes": "Participant repayment"
}
],
"notes": "API group loan repayment"
}

Search group loan: GET /api/loanaccount/v1/searchgrouploan

  • Optional query params: groupLoanID, referenceNumber, groupLoanStatus, pageNumber, pageSize
  • Example: /api/loanaccount/v1/searchgrouploan?groupLoanStatus=Active&pageNumber=1&pageSize=20

Group review endpoints:

  • GET /api/loanaccount/v1/grouploancreditbureau?groupLoanID=1
  • GET /api/loanaccount/v1/grouploanaireview?groupLoanID=1

Normal loan review endpoints:

  • GET /api/loanaccount/v1/loancreditbureau?loanAccountNumber=1000000001
  • GET /api/loanaccount/v1/loanaireview?loanAccountNumber=1000000001

Review Endpoint Response Payloads (Full Analysis Body)

Loan credit bureau (GET /api/loanaccount/v1/loancreditbureau)

{
"status": true,
"message": "Request successful",
"data": {
"analysisType": "LoanCreditBureauAnalysis",
"generatedAtUtc": "2026-03-03T11:40:00Z",
"loanSnapshot": {},
"creditBureau": {}
}
}

Loan AI review (GET /api/loanaccount/v1/loanaireview)

{
"status": true,
"message": "Request successful",
"data": {
"analysisType": "LoanAiCreditReviewAnalysis",
"generatedAtUtc": "2026-03-03T11:40:00Z",
"subjectSnapshot": {},
"creditBureau": {},
"review": "Full AI credit analysis text"
}
}

Loan certificate / offer letter (GET /api/loanaccount/v1/view-certificate/{ID})

{
"status": true,
"message": "Request successful",
"data": {
"id": "12",
"loanAccountNumber": "1000000001",
"isRestructure": false,
"mimeType": "application/pdf",
"fileName": "loan-certificate-1000000001.pdf",
"document": "data:application/pdf;base64,JVBERi0xLjc..."
}
}

Notes:

  • Use the loan id returned by GET /api/loanaccount/v1/search.
  • Add ?isRestructure=true when the {ID} belongs to a loan restructure record instead of a booked loan.

Group loan credit bureau (GET /api/loanaccount/v1/grouploancreditbureau)

{
"status": true,
"message": "Request successful",
"data": {
"analysisType": "GroupLoanCreditBureauAnalysis",
"generatedAtUtc": "2026-03-03T11:40:00Z",
"groupLoanSnapshot": {},
"creditBureau": {}
}
}

Group loan AI review (GET /api/loanaccount/v1/grouploanaireview)

{
"status": true,
"message": "Request successful",
"data": {
"analysisType": "GroupLoanAiCreditReviewAnalysis",
"generatedAtUtc": "2026-03-03T11:40:00Z",
"subjectSnapshot": {},
"creditBureau": {},
"review": "Full AI credit analysis text"
}
}

Group Loan Enums

  • groupLoanStatus (searchgrouploan): PendingApproval, Approved, Rejected, Active, Delinquent, Closed, WrittenOff, Restructured, InRecovery, Canceled, Matured
  • lendingModel: 0=CreditUnions, 1=Individual, 2=NeighbourhoodAndSmallGroupRevolvingFunds, 3=Other, 4=SolidarityGroup, 5=Staff, 6=VillageBanking, 7=WholesaleLending
  • principalRepaymentType / interestPaymentType: 0=EndOfContract, 1=ProRated, 2=Upfront, 3=EqualMonthlyInstallment
  • principalRepaymentFrequency / interestPaymentEveryFrequency: 0=Days, 1=Weeks, 2=Months, 3=Years
  • interestComputationModel: 0=FixedMethod, 1=ReducingBalanceMethod, 2=ReducingBalanceButEqualMethod
  • rateBasis: 0=Annual, 1=PerPeriod
  • moratorium: 0=False, 1=True_PrincipalOnly, 2=True_InterestOnly, 3=True_PrincipalEtInterest
  • collateralType: 0=RealEstate_LandAndBuilding, 1=Automobile, 2=PlantAndEquipment, 3=NaturalReserves, 4=MarketableSecurities, 5=AccountReceivablesAndInventories, 6=Cash, 7=PersonalGuarantees, 8=PostDatedCheques, 9=Domicilliation

4.8 Workflow H: Fixed Deposit Lifecycle

  1. Add FD: POST /api/fixeddepositaccount/v1/add
  2. Top-up: POST /api/fixeddepositaccount/v1/topup
  3. Update: PUT /api/fixeddepositaccount/v1/update
  4. Liquidate: POST /api/fixeddepositaccount/v1/liquidate
  5. Search: GET /api/fixeddepositaccount/v1/search
  6. Generate certificate when needed: GET /api/fixeddepositaccount/v1/view-certificate/{id}/{type}

Fixed deposit certificate (GET /api/fixeddepositaccount/v1/view-certificate/{ID}/{type})

{
"status": true,
"message": "Request successful",
"data": {
"id": "41",
"contractNo": "23000119482",
"accountName": "12 Months Fixed Deposit",
"type": "PDF",
"mimeType": "application/pdf",
"fileName": "fixed-deposit-certificate-41.pdf",
"document": "data:application/pdf;base64,JVBERi0xLjc..."
}
}

Notes:

  • Use the fixed deposit id returned by GET /api/fixeddepositaccount/v1/search.
  • {type} accepts PDF or Excel.

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

Virtual-account reporting rule:

  • requestcustomeraccounthistoryreport accepts a virtual account number and returns credits-only history for that alias.
  • requestcustomeraccountstatement and exportcustomerstatement reject virtual account numbers because the balance lives only on the settlement account.

5. Integration Configuration Checklist (Must Pass)

5.1 Bills

Required minimum:

  • BILLS_PAYMENT_ENABLED=true
  • BILLS_PAYMENT_BASE_URL
  • At least one provider enabled (..._ENABLED=true)
  • Provider auth/header json configured
  • Provider ledger or default ledger configured

Bills provider keys

  • providus
  • coralpay
  • flutterwave
  • ninepsb
  • nibss_pssp
  • nibss_banks

5.2 Transfer

Required minimum:

  • TRANSFER_ENABLED=true
  • TRANSFER_BASE_URL
  • At least one provider enabled (easypay/providus)
  • Provider auth/header json configured
  • Settlement ledger configured

5.3 Cards

Required minimum:

  • CARD_ENABLED=true
  • CARD_BASE_URL
  • Provider enabled (interswitch or providus)
  • Provider headers configured
  • Settlement/issuance ledger configured where needed

5.4 Required Shared Gateway Keys

  • BILLS_PAYMENT_SHARED_GATEWAY_KEY
  • TRANSFER_SHARED_GATEWAY_KEY
  • CARD_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" }
],
"agent": [
{ "method": "POST", "path": "/api/agent/v1/add" },
{ "method": "PUT", "path": "/api/agent/v1/update" },
{ "method": "PUT", "path": "/api/agent/v1/change-status" },
{ "method": "DELETE", "path": "/api/agent/v1/delete/{ID}" },
{ "method": "GET", "path": "/api/agent/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" },
{
"method": "GET",
"path": "/api/fixeddepositaccount/v1/view-certificate/{ID}/{type}"
}
],
"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": "POST", "path": "/api/loanaccount/v1/addgrouploan" },
{ "method": "POST", "path": "/api/loanaccount/v1/disbursegrouploan" },
{ "method": "POST", "path": "/api/loanaccount/v1/repaygrouploan" },
{ "method": "PUT", "path": "/api/loanaccount/v1/update" },
{ "method": "GET", "path": "/api/loanaccount/v1/search" },
{ "method": "GET", "path": "/api/loanaccount/v1/view-certificate/{ID}" },
{ "method": "GET", "path": "/api/loanaccount/v1/viewloanschedule" },
{ "method": "GET", "path": "/api/loanaccount/v1/searchgrouploan" },
{ "method": "GET", "path": "/api/loanaccount/v1/grouploancreditbureau" },
{ "method": "GET", "path": "/api/loanaccount/v1/grouploanaireview" },
{ "method": "GET", "path": "/api/loanaccount/v1/loancreditbureau" },
{ "method": "GET", "path": "/api/loanaccount/v1/loanaireview" }
],
"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" }
],
"utility": [
{ "method": "GET", "path": "/api/utility/v1/countries" },
{ "method": "GET", "path": "/api/utility/v1/regions" },
{ "method": "GET", "path": "/api/utility/v1/cities" }
]
}

Geography Lookup

Use the utility endpoints when an integrator needs country, state/region, or city/LGA master data:

  1. GET /api/utility/v1/countries
  2. GET /api/utility/v1/regions?CountryCode2=NG
  3. GET /api/utility/v1/cities?RegionShortCode=LA&CountryCode2=NG

The geography endpoints are authenticated API-channel reads. They return flat lists plus recordCount.


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

StepActionEndpointSuccess Check
1Authenticate with active API key pairPOST /api/auth/v1/authenticateResponse contains accessToken
2Use token for a safe read callGET /api/product/v1/searchproducts?PageNumber=1&PageSize=1status=true
3Confirm request tracing header worksany secured endpoint + request-referenceRequest 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:

  • BranchCode exists and is active.
  • ProductCode exists and is active for account creation.
  • AccountOfficerStaffID exists 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.accountNumber
  • data.customerID (business customer id)

Immediate validation calls:

  1. GET /api/account/v1/getbyaccountnumber?AccountNumber={accountNumber}
  2. 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/uploaddocument when needed.

9.4 Playbook: Create Virtual Account (Collection Alias)

Call:

  • POST /api/account/v1/createvirtualaccount

Rules:

  • Parent account must be a business/corporate account (or pre-bound on API key).
  • Virtual accounts are collection aliases for inbound NIP/NPS funding only.
  • Only the base collection virtual-account type is supported for new integrations.
  • referenceNumber must be unique when supplied.

Validation:

  • GET /api/account/v1/getbyaccountnumber?AccountNumber={generatedAccountNumber}
  • GET /api/account/v1/searchaccount?AccountNumber={generatedAccountNumber}

Restrictions expected by design:

  • Virtual account should not be used as a debit-capable account.
  • Virtual account should not expose balance through the virtual account number.
  • Virtual account should not access disallowed loan/fixed-deposit operations.

Virtual-account response model notes:

  • getbyaccountnumber returns:
    • id = virtual-account ID for virtual queries.
    • virtualAccountID = virtual-account ID.
    • settlementAccountNumber = parent account number.
    • accountName = {virtual account name}/{corporate customer name}.
    • isVirtualAccount = true.
  • getaccountbalancebyaccountnumber rejects virtual account numbers.
  • searchaccount can return virtual rows (fallback when AccountNumber matches virtual account):
    • id = virtual-account ID.
    • accountNumber = virtual account number.
    • settlementAccountNumber = parent account number.
    • isVirtualAccount = true.

9.5 Playbook: Update Account / Activate / Deactivate / Unfreeze

Endpoints:

  • PUT /api/account/v1/updatecustomeraccount
  • PUT /api/account/v1/activate
  • PUT /api/account/v1/deactivate
  • PUT /api/account/v1/unfreeze

Pattern:

  1. Submit action payload.
  2. Re-query via searchaccount or getbyaccountnumber.
  3. Confirm accountStatus reflects requested operation.

Virtual-account specifics:

  • updatecustomeraccount.id must be the settlement account ID. Virtual-account IDs are rejected.
  • activate/deactivate/unfreeze reject virtual account numbers. Use the settlement account number directly.

9.6 Playbook: Close Account

Call:

  • POST /api/postings/v1/closeaccount

Payload essentials:

  • accountNumber
  • closureReason

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:

  • debitAccount
  • creditAccount
  • amount (Naira)
  • narration
  • postingsTransactionType (1=GLCustomer,2=GLGL,3=CustomerCustomer)

Status check:

  • GET /api/transfer/v1/tsq/local?referenceNumber=...

9.8 Playbook: Interbank Transfer (Outward Transfer)

Strict sequence:

  1. GET /api/transfer/v1/banks
  2. GET /api/transfer/v1/nameenquiry
  3. POST /api/transfer/v1/outwardtransfer
  4. GET /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:

  1. GET /api/bills/v1/billers
  2. GET /api/bills/v1/getcustomerinformation
  3. POST /api/bills/v1/vend
  4. POST /api/bills/v1/tsq (if gateway status is not final)
  5. GET /api/bills/v1/gettoken (electricity scenarios)

Money movement expectation:

  • Debit from customer/settlement account.
  • Credit to configured bills ledger.
  • On provider failure, reversal should be triggered.

9.10 Playbook: Card Operations

Common flow:

  1. POST /api/card/v1/addcardtoaccount
  2. GET /api/card/v1/searchcards
  3. Provider operation:
  • Interswitch: PUT /api/card/v1/interswitch/updatecardchannelaccess
  • Providus: PUT /api/card/v1/providus/setcardpin
  • Providus: PUT /api/card/v1/providus/blockunblockcard
  1. Optional generic block/unblock/delete:
  • PUT /api/card/v1/block
  • PUT /api/card/v1/unblock
  • DELETE /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: Agent Lifecycle

Common flow:

  1. POST /api/agent/v1/add
  2. GET /api/agent/v1/search
  3. PUT /api/agent/v1/update (optional)
  4. PUT /api/agent/v1/change-status (optional)
  5. DELETE /api/agent/v1/delete/{ID} only when no loans are attached

Business rule reminder:

  • Agents cannot log in.
  • CoreWave generates the unique institution agent code.
  • Agent is different from account officer.

9.12 Playbook: Loan Lifecycle

Strict sequence:

  1. POST /api/loanaccount/v1/add
  2. GET /api/loanaccount/v1/loancreditbureau?loanAccountNumber={accountNumber} when bureau review is enabled
  3. GET /api/loanaccount/v1/loanaireview?loanAccountNumber={accountNumber} when AI review is enabled
  4. Complete approval in the institution flow
  5. POST /api/loanaccount/v1/disburseloan
  6. POST /api/loanaccount/v1/repayloan (as needed)
  7. POST /api/loanaccount/v1/earlyrepaymentloan (optional)
  8. PUT /api/loanaccount/v1/update (optional)
  9. GET /api/loanaccount/v1/view-certificate/{id}
  10. GET /api/loanaccount/v1/viewloanschedule
  11. GET /api/loanaccount/v1/search
  12. POST /api/loanaccount/v1/addgrouploan
  13. POST /api/loanaccount/v1/disbursegrouploan
  14. POST /api/loanaccount/v1/repaygrouploan
  15. GET /api/loanaccount/v1/searchgrouploan
  16. GET /api/loanaccount/v1/grouploancreditbureau?groupLoanID={id}
  17. GET /api/loanaccount/v1/grouploanaireview?groupLoanID={id}

Business rule reminder:

  • linkedNumber must be the linked account number belonging to the loan owner.
  • agentCode is optional and is separate from accountOfficerCode.

9.13 Playbook: Fixed Deposit Lifecycle

Strict sequence:

  1. POST /api/fixeddepositaccount/v1/add
  2. POST /api/fixeddepositaccount/v1/topup
  3. PUT /api/fixeddepositaccount/v1/update
  4. POST /api/fixeddepositaccount/v1/liquidate
  5. GET /api/fixeddepositaccount/v1/search
  6. GET /api/fixeddepositaccount/v1/view-certificate/{id}/{type}

9.14 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/requestcustomeraccountstatement
  • GET /api/report/v1/exportcustomerstatement
  • GET /api/report/v1/gettransactionreceipt
  • GET /api/report/v1/requestcustomeraccounthistoryreport
  • GET /api/report/v1/gettransactioncalloverreport
  • GET /api/report/v1/getloanexpectationreport
  • GET /api/report/v1/getloantrackingreport
  • GET /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_JSON exactly 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).

11.1 Entity Extra Data

Use entity extra data when an institution needs to attach custom nested JSON fields to a product, customer, account, loan, or fixed-deposit record.

Primary endpoints:

  • GET /api/entity-additional-metadata/v1/supported-entity-types
  • GET /api/entity-additional-metadata/v1/{entityType}/{entityId}
  • PUT /api/entity-additional-metadata/v1/{entityType}/{entityId}
  • DELETE /api/entity-additional-metadata/v1/{entityType}/{entityId}

Operational rules:

  • additionalMetadata must be a JSON object or array.
  • PUT replaces the stored JSON value.
  • Fetch first when an integration needs to merge individual keys.
  • Use DELETE to clear the value.
  • Maximum payload size is 64 KB.
  • All access is institution-scoped from the API-channel token.

For supported entity types and copy-ready requests, see Entity Extra Data.


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 false by default for new institutions.
  • Enable true only for institutions with signed risk acceptance.

12.1 Fraud Copilot AML holds cannot be bypassed

When Fraud Copilot is enabled, AML holds apply before API and portal money movement even when API_BYPASS_APPROVALS=true.

  • Staff release requires approve-aml-held-transactions.
  • API callers receive 202 Accepted and retry the unchanged payload with amlApprovalReference.
  • Portal posting groups resume automatically after AML approval and still honor any configured posting approval queue before balances move.

See Fraud Copilot AML Holds.


13. Idempotency, Retry, and Reconciliation Rules

Idempotency keys to treat as unique:

  • Header: request-reference
  • Business refs: paymentReference, transactionReference, referenceNumber

Retry strategy:

  1. On timeout, do not re-post blindly.
  2. Query search/TSQ endpoint first.
  3. Re-post only if no trace exists.

Reconciliation strategy:

  • Transfer: use TSQ and processingStatus.
  • Bills: use TSQ, then Search to inspect isReversed and requireReversal.
  • Local posting: use TSQ/local or transaction history search.

14. QA Acceptance Matrix (What Must Pass Before Go-Live)

AreaTestPass Criteria
AuthAuthenticate with valid keyToken returned
AuthAuthenticate with inactive keyRejected with clear message
AccountsCreate customer+accountAccount number + customer id returned
AccountsUpload documentUpload accepted and retrievable/deletable
TransfersLocal transferDebit/Credit posted and TSQ local successful
TransfersOutward transfer success pathTSQ reaches Processed
TransfersOutward transfer failure pathReversal status is visible when failed
BillsVend success pathSuccessful status with traceable refs
BillsVend failure pathReversal path works and searchable
BillsElectricity tokenToken retrievable and sent via notifications
CardsAdd/search/block/unblock/set pinProvider actions reflected in state
LoansAdd/disburse/repay/search/scheduleAll states consistent
FDAdd/topup/update/liquidate/searchAll operations consistent
ReportsStatement + export + receiptData rendered and export streams correctly
LimitsAdd/update/get account transfer limitValues persist and are enforced
MetadataAdd/fetch/replace/clear extra dataNested JSON persists and stays tenant-scoped
SecurityAPI key inactivity auto-disableKey disabled after 14 days of no usage

15. Reference Material

Use resources in this order:

  1. This document: execution flow and operational behavior.
  2. The API Channel Reference (api-channel-reference): endpoint inventory, request/response formats, and validation rules.
  3. The Postman collection available for download from the site navigation header.