The NetPOS REST API provides HTTP endpoints for user authentication, transaction management, terminal configuration, and data retrieval.
Base URLs
NetPOS uses multiple API base URLs for different services:
| Service | Base URL | Description |
|---|
| Main API | https://netpos.netpluspay.com/ | Core POS operations |
| Bills/Storm | https://storm.netpluspay.com/ | Bill payments and Storm services |
| Cash Service | https://netpos.netpluspay.com/api/cash/ | Cash transaction tracking |
| Zenith PBT | https://api.zenith-pbt.netpluspay.com/ | Zenith Pay-by-Transfer |
| QR Payments | https://masterpassqr.netpluspay.com/api/v1/ | QR payment processing |
| SMS Service | https://sms.netpluspay.com | SMS notifications |
Authentication
App Token
Obtain application-level authentication token:
import com.google.gson.JsonObject
import com.woleapp.netpos.network.StormApiClient
val credentials = JsonObject().apply {
addProperty("client_id", "your_client_id")
addProperty("client_secret", "your_client_secret")
}
StormApiClient.getBillsInstance()
.appToken(credentials)
.subscribe { response, error ->
response?.let {
val token = it.token
// Store token for subsequent requests
}
}
Endpoint: POST /api/token
Request Body:
Application client secret
Response:
Token expiration time in seconds
User Authentication
Authenticate a user and obtain user token:
val credentials = JsonObject().apply {
addProperty("username", "[email protected]")
addProperty("password", "password123")
addProperty("terminal_id", "2058XU23")
}
StormApiClient.getBillsInstance()
.userToken(credentials)
.subscribe { response, error ->
response?.let {
val userToken = it.token
val user = it.user
// Store user session
}
}
Endpoint: POST /api/auth
Request Body:
Terminal ID for this session
Response:
User profile data including terminal_id, business_name, netplus_id
Transactions
Log Transaction (Before NIBSS)
Log transaction details before connecting to NIBSS:
val transactionData = TransactionToLogBeforeConnectingToNibbs(
terminalId = "2058XU23",
amount = "500000", // Amount in kobo
stan = "000123",
rrn = "202112011234567",
cardPan = "506066******1234",
cardExpiry = "12/25",
timestamp = System.currentTimeMillis()
)
StormApiClient.getStormApiLoginInstance()
.logTransactionBeforeConnectingToNibss(transactionData)
.subscribe { response, error ->
response?.let {
val transactionId = it.id
}
}
Endpoint: POST /pos_transaction
Headers:
Bearer token from user authentication
Request Body:
Transaction amount in kobo (minor units)
System Trace Audit Number
Retrieval Reference Number
Update Transaction (After NIBSS)
Update transaction with response from NIBSS:
val rrn = "202112011234567"
val updateData = DataToLogAfterConnectingToNibss(
responseCode = "00",
responseMessage = "Approved",
authCode = "123456",
isoString = "0200...",
responseTime = System.currentTimeMillis()
)
StormApiClient.getStormApiLoginInstance()
.updateLogAfterConnectingToNibss(rrn, updateData)
.subscribe { response, error ->
response?.let {
// Transaction updated
}
}
Endpoint: PUT /pos_transaction/{rrn}
Path Parameters:
Retrieval Reference Number from initial transaction log
Request Body:
ISO 8583 response code (“00” for approved)
Human-readable response message
Authorization code from issuer
Full ISO 8583 message for audit
Get Transactions
Retrieve transactions by terminal and date range:
val terminalId = "2058XU23"
val from = "2021-12-01 00:00:00"
val to = "2021-12-31 23:59:59"
val page = 1
val pageSize = 50
StormApiClient.getStormApiLoginInstance()
.getTransactionsFromNewService(terminalId, from, to, page, pageSize)
.subscribe { response, error ->
response?.let {
val transactions = it.data
val totalPages = it.totalPages
}
}
Endpoint: GET /pos_transactions/terminal/{terminalId}/btw/{from}/{to}/{page}/{pageSize}
Path Parameters:
Start date (format: YYYY-MM-DD HH:mm:ss)
End date (format: YYYY-MM-DD HH:mm:ss)
Number of records per page
Response:
Array of transaction objects
Agent Management
Get Agent Details
val stormId = "AGT123456"
StormApiClient.getInstance()
.getAgentDetails(stormId)
.subscribe { user, error ->
user?.let {
val terminalId = it.terminal_id
val businessName = it.business_name
}
}
Endpoint: GET /api/agents/{stormId}
Path Parameters:
Response:
NIP (Bank Transfer)
Get NIP Notifications
Retrieve NIP transfer notifications:
val terminalId = "2058XU23"
val from = "2021-12-01"
val to = "2021-12-31"
val clientId = "85522f45-e459-4548-8b20-3a922196c515"
val accessCode = "a14014e18e2cffc4d74e150ed68a472bd94189db82d374306d5b307dc7620f20"
StormApiClient.getInstance()
.getNotifications(terminalId, from, to, clientId, accessCode)
.subscribe { notifications, error ->
notifications?.let {
it.forEach { notification ->
val amount = notification.amount
val reference = notification.referenceNo
}
}
}
Endpoint: GET /api/nip-notifications
Headers:
Query Parameters:
Specific transaction reference (alternative to date range)
Get Session Code
Generate session code for NIP transfers:
StormApiClient.getNipInstance()
.getSessionCode()
.subscribe { sessionCode, error ->
sessionCode?.let {
val code = it.code
val expiresAt = it.expiresAt
}
}
Endpoint: GET /api/sessionCode
Response:
Cash Transactions
Add Cash Transaction
val cashTransaction = JsonObject().apply {
addProperty("terminalId", "2058XU23")
addProperty("amount", 50000) // In kobo
addProperty("type", "CASH_IN")
addProperty("reference", "CASH202112011234")
addProperty("timestamp", System.currentTimeMillis())
}
StormApiClient.getCashInstance()
.addCashTransaction(cashTransaction)
.subscribe { response, error ->
response?.let {
// Cash transaction logged
}
}
Endpoint: POST /addTransactions
Request Body:
Transaction type: CASH_IN or CASH_OUT
Unique transaction reference
QR Payments
Pay with QR
val qrPaymentRequest = PayWithQrRequest(
qrData = "scanned_qr_code_data",
amount = 500000, // In kobo
terminalId = "2058XU23"
)
val qrService = Retrofit.Builder()
.baseUrl("https://masterpassqr.netpluspay.com/api/v1/")
.build()
.create(QrPaymentService::class.java)
qrService.payWithQr(qrPaymentRequest)
.subscribe { response, error ->
response?.let {
if (it.isSuccessful) {
// Payment successful
}
}
}
Endpoint: POST /contactlessQr
Request Body:
Password Management
Reset Password
val resetPayload = JsonObject().apply {
addProperty("email", "[email protected]")
addProperty("terminal_id", "2058XU23")
}
StormApiClient.getBillsInstance()
.passwordReset(resetPayload)
.subscribe { response, error ->
response?.let {
// Password reset email sent
}
}
Endpoint: POST /api/passwordReset
Request Body:
API Client Configuration
NetPOS uses Retrofit with custom interceptors:
private fun getOkHttpClient() =
OkHttpClient.Builder()
.addInterceptor(TokenInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.build()
class TokenInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val headersInReq = request.headers
if (headersInReq["Authorization"].isNullOrEmpty()) {
Prefs.getString(PREF_USER_TOKEN, null)?.let {
request = request.newBuilder()
.addHeader("Authorization", "Bearer $it")
.build()
}
}
return chain.proceed(request)
}
}
Error Handling
API errors follow standard HTTP status codes:
| Status Code | Meaning |
|---|
| 200 | Success |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or expired token |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource doesn’t exist |
| 500 | Internal Server Error |
Next Steps
Webhooks
Set up webhook notifications for real-time events