Skip to content

Virtual cards and POS

Card issuing and POS acquiring are enabled per partner by the bank, on request, and come with their own onboarding: card products, terminal mappings, key injection and the acquirer’s test cycle. This page is an orientation. The field-level reference for everything beyond the two calls shown here, together with test material, is available from the bank once the capability is enabled for your client.

Virtual Verve cards are issued against a wallet’s customer and operated from the same account number. Two route families exist; they do the same things and differ only in where the account number goes.

Wallet-scoped (account number in the path):

Operation Endpoint
Create POST /api/legacy/provider/wallets/{accountNumber}/virtual_card
Details POST …/virtual_card/info
Status at the scheme POST …/virtual_card/status
Block / unblock POST …/virtual_card/block, POST …/virtual_card/unblock
PIN reset / change POST …/virtual_card/pinreset, POST …/virtual_card/pinchange

Provider-scoped (account number or card reference in the body), the jCard shape:

Operation Endpoint
Create POST /api/legacy/provider/virtual_card/create
Details POST /api/legacy/provider/virtual_card/info, GET/POST …/infoByClientReference
Status, block, unblock POST …/status, POST …/block, POST …/unblock
PIN reset / change POST …/reset_pin, POST …/change_pin
3-D Secure enrolment POST …/enrollSafeToken

Every call needs the bearer token. Where a card is addressed by account number alone, the most recently issued card that is not closed, expired, lost or stolen is the one acted on; pass cardReference to pick a specific card.

POST/api/legacy/provider/wallets/{accountNumber}/virtual_card
Field Type Required Description
cardProductId UUID Yes The card product the bank assigned you.
clientReference string Yes Your reference. The idempotency key for a safe retry.
creationChannel string No Free text recorded on the card. Default API.
Terminal window
curl -X POST https://api.bankcore.ng/api/legacy/provider/wallets/6020012345/virtual_card \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cardProductId": "550e8400-e29b-41d4-a716-446655440000",
"clientReference": "CARD-REQ-0001"
}'

Card responses are not the legacy code/desc envelope on success: create answers HTTP 201 and the others 200, with responseCode 00. The full PAN, CVV and default PIN are returned on issuance and PIN operations only, and only when the scheme returned them for that call; treat the response as cardholder data and never log it. Failures do use the legacy envelope: a missing cardProductId or clientReference is 0012, an unknown account 0012, and anything unexpected 0096.

The provider-scoped create takes accountNumber, clientReference, optional cardType (only VERVE is accepted) and cardProductId, which may be omitted when your tenant has exactly one active virtual product. Its reply is the flat jCard card object (cardReference, clientReference, accountNumber, pan, cvv, cvv2, createdAt and expiresAt as yy/MM, status booleans), plus defaultPin.

Card activity reaches you as card.authorization and card.reversed webhooks; see Events and payloads.

POS endpoints are agent endpoints: each call names the agent whose terminal is used with X-Agent-Account, and a sub-agent’s account needs sub-agents:debit.

Operation Endpoint Scope
mPOS cash-out POST /api/legacy/agent/transact/mpos/cashout2 pos:cashout
mPOS bill payment POST /api/legacy/agent/transact/mpos/cashout2_bills pos:bill-pay
Third-party terminal (PAX, Ingenico; cash-out, bills, contactless) POST /api/legacy/agent/transact/pos pos:cashout
List your POS transactions GET /api/pos-transactions pos:read
POST/api/legacy/agent/transact/mpos/cashout2scope: pos:cashout
Header Required Description
X-Agent-Account Yes The agent’s 10-digit transaction account.
Field Type Required Description
terminalId string Yes A terminal mapped to the agent.
data string Yes The EMV/ICC TLV data from the card read, as a hex string. The PIN block is inside the TLV.
total string Yes Amount in kobo ("500000" is ₦5,000). amount is accepted as an alias, also in kobo; total wins when both are sent.
mode string No Entry mode passed through to the acquirer.
type string No CASHOUT (default) or BILL_PAY, which routes to the bill-payment handler and needs billerId, productId and subscriberId.
clientRef string No Your reference, echoed back. transactionRef and ref are accepted as aliases.
{
"responseCode": "0000",
"responseRef": "KMN-20260401-0001",
"merchantRef": "KMN-20260401-0001",
"paymentRef": "KMN-20260401-0001",
"clientRef": "POS-0001",
"description": "Approved",
"amount": 5000.00,
"fee": 65.00,
"agentPortion": 40.00
}
Field Description
responseCode 0000 approved, 0009 pending at the acquirer (09, 10, 91 from the switch), 9999 declined or failed.
responseRef, merchantRef, paymentRef The acquirer’s reference, the same value three times for jCard compatibility. Use it for reconciliation and disputes.
description The acquirer’s response message.
fee, agentPortion The issuer fee charged and the agent’s commission.
token, units, receipt Present only on a bill payment against a vending product.

A request the platform cannot process (missing amount, unknown terminal) answers responseCode 9999 with the reason in description; an unexpected error on cashout2 is an HTTP 500 with the same body. The third-party /transact/pos route takes the acquirer’s structured fields instead (deviceId, sendIccData, field52, pinKsn, 12-digit kobo amount, payType, extra) and replies with a printable receipt object; its reference is in the material the bank provides on enablement.

Card and POS activity is not a separate page. Settled POS cash-outs and bill payments appear on the agent’s statement under Agents and in the Transactions register.